all: various fixes for [heap]/auto-heap handling (#10033)
parent
5b4eef8010
commit
d26ac5692e
|
@ -43,7 +43,7 @@ fn (mut ctx Context) println(s string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_timeout(c &Context) {
|
fn do_timeout(c &Context) {
|
||||||
mut ctx := c
|
mut ctx := unsafe { c }
|
||||||
time.sleep(ctx.timeout_ms * time.millisecond)
|
time.sleep(ctx.timeout_ms * time.millisecond)
|
||||||
exit(ctx.exitcode)
|
exit(ctx.exitcode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,7 @@ fn (mut context Context) get_changed_vfiles() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_detection_loop(ocontext &Context) {
|
fn change_detection_loop(ocontext &Context) {
|
||||||
mut context := ocontext
|
mut context := unsafe { ocontext }
|
||||||
for {
|
for {
|
||||||
if context.v_cycles >= max_v_cycles || context.scan_cycles >= max_scan_cycles {
|
if context.v_cycles >= max_v_cycles || context.scan_cycles >= max_scan_cycles {
|
||||||
context.is_exiting = true
|
context.is_exiting = true
|
||||||
|
|
|
@ -13,7 +13,7 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn my_audio_stream_callback(buffer &f32, num_frames int, num_channels int, mut acontext AppState) {
|
fn my_audio_stream_callback(buffer &f32, num_frames int, num_channels int, mut acontext AppState) {
|
||||||
mut soundbuffer := buffer
|
mut soundbuffer := unsafe { buffer }
|
||||||
for frame := 0; frame < num_frames; frame++ {
|
for frame := 0; frame < num_frames; frame++ {
|
||||||
t := int(f32(acontext.frame_0 + frame) * 0.245)
|
t := int(f32(acontext.frame_0 + frame) * 0.245)
|
||||||
// "Techno" by Gabriel Miceli
|
// "Techno" by Gabriel Miceli
|
||||||
|
|
|
@ -16,6 +16,7 @@ const (
|
||||||
orange = ui.Color{255, 140, 0}
|
orange = ui.Color{255, 140, 0}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
[heap]
|
||||||
struct App {
|
struct App {
|
||||||
mut:
|
mut:
|
||||||
tui &ui.Context = 0
|
tui &ui.Context = 0
|
||||||
|
@ -238,6 +239,7 @@ fn (mut b Ball) update(dt f32) {
|
||||||
b.pos.y += b.vel.y * b.acc.y * dt
|
b.pos.y += b.vel.y * b.acc.y * dt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
struct Game {
|
struct Game {
|
||||||
mut:
|
mut:
|
||||||
app &App = 0
|
app &App = 0
|
||||||
|
|
|
@ -256,6 +256,7 @@ fn (mut r Rat) randomize() {
|
||||||
r.app.height - block_size - buffer)
|
r.app.height - block_size - buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
struct App {
|
struct App {
|
||||||
mut:
|
mut:
|
||||||
termui &termui.Context = 0
|
termui &termui.Context = 0
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub fn memcpy(dest &C.void, src &C.void, n size_t) &C.void {
|
||||||
dest_[i] = src_[i]
|
dest_[i] = src_[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dest
|
return unsafe { dest }
|
||||||
}
|
}
|
||||||
|
|
||||||
[export: 'malloc']
|
[export: 'malloc']
|
||||||
|
@ -37,7 +37,7 @@ fn realloc(old_area &C.void, new_size size_t) &C.void {
|
||||||
}
|
}
|
||||||
old_size := unsafe { *(&u64(old_area - sizeof(u64))) }
|
old_size := unsafe { *(&u64(old_area - sizeof(u64))) }
|
||||||
if u64(new_size) <= old_size {
|
if u64(new_size) <= old_size {
|
||||||
return old_area
|
return unsafe { old_area }
|
||||||
} else {
|
} else {
|
||||||
new_area := unsafe { malloc(int(new_size)) }
|
new_area := unsafe { malloc(int(new_size)) }
|
||||||
unsafe { memmove(new_area, old_area, size_t(old_size)) }
|
unsafe { memmove(new_area, old_area, size_t(old_size)) }
|
||||||
|
@ -54,7 +54,7 @@ fn memset(s &C.void, c int, n size_t) &C.void {
|
||||||
s_[i] = char(c)
|
s_[i] = char(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return unsafe { s }
|
||||||
}
|
}
|
||||||
|
|
||||||
[unsafe]
|
[unsafe]
|
||||||
|
@ -74,7 +74,7 @@ fn memmove(dest &C.void, src &C.void, n size_t) &C.void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe { free(temp_buf) }
|
unsafe { free(temp_buf) }
|
||||||
return dest
|
return unsafe { dest }
|
||||||
}
|
}
|
||||||
|
|
||||||
[export: 'calloc']
|
[export: 'calloc']
|
||||||
|
|
|
@ -77,7 +77,7 @@ pub fn tos(s &byte, len int) string {
|
||||||
panic('tos(): nil string')
|
panic('tos(): nil string')
|
||||||
}
|
}
|
||||||
return string{
|
return string{
|
||||||
str: s
|
str: unsafe { s }
|
||||||
len: len
|
len: len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ pub fn tos2(s &byte) string {
|
||||||
panic('tos2: nil string')
|
panic('tos2: nil string')
|
||||||
}
|
}
|
||||||
return string{
|
return string{
|
||||||
str: s
|
str: unsafe { s }
|
||||||
len: unsafe { vstrlen(s) }
|
len: unsafe { vstrlen(s) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ pub fn tos_lit(s &char) string {
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn (bp &byte) vstring() string {
|
pub fn (bp &byte) vstring() string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: unsafe { bp }
|
||||||
len: unsafe { C.strlen(&char(bp)) }
|
len: unsafe { C.strlen(&char(bp)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ pub fn (bp &byte) vstring() string {
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn (bp &byte) vstring_with_len(len int) string {
|
pub fn (bp &byte) vstring_with_len(len int) string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: unsafe { bp }
|
||||||
len: len
|
len: len
|
||||||
is_lit: 0
|
is_lit: 0
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ pub fn (cp &char) vstring_with_len(len int) string {
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn (bp &byte) vstring_literal() string {
|
pub fn (bp &byte) vstring_literal() string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: unsafe { bp }
|
||||||
len: unsafe { C.strlen(&char(bp)) }
|
len: unsafe { C.strlen(&char(bp)) }
|
||||||
is_lit: 1
|
is_lit: 1
|
||||||
}
|
}
|
||||||
|
@ -205,7 +205,7 @@ pub fn (bp &byte) vstring_literal() string {
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn (bp &byte) vstring_literal_with_len(len int) string {
|
pub fn (bp &byte) vstring_literal_with_len(len int) string {
|
||||||
return string{
|
return string{
|
||||||
str: bp
|
str: unsafe { bp }
|
||||||
len: len
|
len: len
|
||||||
is_lit: 1
|
is_lit: 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn (mut cmd Command) add_command(command Command) {
|
||||||
println('Command with the name `$subcmd.name` already exists')
|
println('Command with the name `$subcmd.name` already exists')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
subcmd.parent = cmd
|
subcmd.parent = unsafe { cmd }
|
||||||
cmd.commands << subcmd
|
cmd.commands << subcmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ pub fn (mut cmd Command) add_command(command Command) {
|
||||||
// is linked as a chain.
|
// is linked as a chain.
|
||||||
pub fn (mut cmd Command) setup() {
|
pub fn (mut cmd Command) setup() {
|
||||||
for mut subcmd in cmd.commands {
|
for mut subcmd in cmd.commands {
|
||||||
subcmd.parent = cmd
|
subcmd.parent = unsafe { cmd }
|
||||||
subcmd.setup()
|
subcmd.setup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ pub:
|
||||||
native_rendering bool // Cocoa on macOS/iOS, GDI+ on Windows
|
native_rendering bool // Cocoa on macOS/iOS, GDI+ on Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
render_text bool
|
render_text bool
|
||||||
mut:
|
mut:
|
||||||
|
|
|
@ -10,6 +10,7 @@ import sokol
|
||||||
import sokol.sgl
|
import sokol.sgl
|
||||||
import stbi
|
import stbi
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub mut:
|
pub mut:
|
||||||
id int
|
id int
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub fn vec3(x f32, y f32, z f32) Vec3 {
|
||||||
|
|
||||||
fn mat4(f &f32) Mat4 {
|
fn mat4(f &f32) Mat4 {
|
||||||
res := Mat4{
|
res := Mat4{
|
||||||
data: f
|
data: unsafe { f }
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn (mut r Response) write_string(s string) {
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut r Response) http_ok() &Response {
|
pub fn (mut r Response) http_ok() &Response {
|
||||||
r.write_string('HTTP/1.1 200 OK\r\n')
|
r.write_string('HTTP/1.1 200 OK\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -29,7 +29,7 @@ pub fn (mut r Response) header(k string, v string) &Response {
|
||||||
r.write_string(': ')
|
r.write_string(': ')
|
||||||
r.write_string(v)
|
r.write_string(v)
|
||||||
r.write_string('\r\n')
|
r.write_string('\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -39,13 +39,13 @@ pub fn (mut r Response) header_date() &Response {
|
||||||
r.buf += cpy(r.buf, r.date, 29)
|
r.buf += cpy(r.buf, r.date, 29)
|
||||||
}
|
}
|
||||||
r.write_string('\r\n')
|
r.write_string('\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut r Response) header_server() &Response {
|
pub fn (mut r Response) header_server() &Response {
|
||||||
r.write_string('Server: V\r\n')
|
r.write_string('Server: V\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -53,25 +53,25 @@ pub fn (mut r Response) content_type(s string) &Response {
|
||||||
r.write_string('Content-Type: ')
|
r.write_string('Content-Type: ')
|
||||||
r.write_string(s)
|
r.write_string(s)
|
||||||
r.write_string('\r\n')
|
r.write_string('\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut r Response) html() &Response {
|
pub fn (mut r Response) html() &Response {
|
||||||
r.write_string('Content-Type: text/html\r\n')
|
r.write_string('Content-Type: text/html\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut r Response) plain() &Response {
|
pub fn (mut r Response) plain() &Response {
|
||||||
r.write_string('Content-Type: text/plain\r\n')
|
r.write_string('Content-Type: text/plain\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (mut r Response) json() &Response {
|
pub fn (mut r Response) json() &Response {
|
||||||
r.write_string('Content-Type: application/json\r\n')
|
r.write_string('Content-Type: application/json\r\n')
|
||||||
return r
|
return unsafe { r }
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub fn get_current_rng() &PRNG {
|
||||||
// should be restored if work with the custom RNG is complete. It is not necessary to restore if the
|
// should be restored if work with the custom RNG is complete. It is not necessary to restore if the
|
||||||
// program terminates soon afterwards.
|
// program terminates soon afterwards.
|
||||||
pub fn set_rng(rng &PRNG) {
|
pub fn set_rng(rng &PRNG) {
|
||||||
default_rng = rng
|
default_rng = unsafe { rng }
|
||||||
}
|
}
|
||||||
|
|
||||||
// seed sets the given array of `u32` values as the seed for the `default_rng`. The default_rng is
|
// seed sets the given array of `u32` values as the seed for the `default_rng`. The default_rng is
|
||||||
|
|
|
@ -150,6 +150,7 @@ pub fn (b &C.sg_bindings) append_index_buffer(data voidptr, element_size int, el
|
||||||
return C.sg_append_buffer(b.index_buffer, &range)
|
return C.sg_append_buffer(b.index_buffer, &range)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct C.sg_shader_desc {
|
pub struct C.sg_shader_desc {
|
||||||
pub mut:
|
pub mut:
|
||||||
_start_canary u32
|
_start_canary u32
|
||||||
|
|
|
@ -510,7 +510,6 @@ pub mut:
|
||||||
is_or bool // `x := foo() or { ... }`
|
is_or bool // `x := foo() or { ... }`
|
||||||
is_tmp bool // for tmp for loop vars, so that autofree can skip them
|
is_tmp bool // for tmp for loop vars, so that autofree can skip them
|
||||||
is_auto_heap bool // value whoes address goes out of scope
|
is_auto_heap bool // value whoes address goes out of scope
|
||||||
is_heap_ref bool // *known* to be pointer to heap memory (ptr to [heap] struct)
|
|
||||||
is_stack_obj bool // may be pointer to stack value (`mut` or `&` arg and not [heap] struct)
|
is_stack_obj bool // may be pointer to stack value (`mut` or `&` arg and not [heap] struct)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module ast
|
module ast
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
pub mut:
|
pub mut:
|
||||||
// mut:
|
// mut:
|
||||||
|
|
|
@ -282,7 +282,7 @@ pub fn (t &Table) type_has_method(s &TypeSymbol, name string) bool {
|
||||||
// search from current type up through each parent looking for method
|
// search from current type up through each parent looking for method
|
||||||
pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
|
pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
|
||||||
// println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
// println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||||
mut ts := s
|
mut ts := unsafe { s }
|
||||||
for {
|
for {
|
||||||
if method := ts.find_method(name) {
|
if method := ts.find_method(name) {
|
||||||
return method
|
return method
|
||||||
|
@ -337,7 +337,7 @@ pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool {
|
||||||
// search from current type up through each parent looking for field
|
// search from current type up through each parent looking for field
|
||||||
pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
|
pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
|
||||||
// println('find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
// println('find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
|
||||||
mut ts := s
|
mut ts := unsafe { s }
|
||||||
for {
|
for {
|
||||||
match mut ts.info {
|
match mut ts.info {
|
||||||
Struct {
|
Struct {
|
||||||
|
@ -401,7 +401,7 @@ pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?St
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t &Table) resolve_common_sumtype_fields(sym_ &TypeSymbol) {
|
pub fn (t &Table) resolve_common_sumtype_fields(sym_ &TypeSymbol) {
|
||||||
mut sym := sym_
|
mut sym := unsafe { sym_ }
|
||||||
mut info := sym.info as SumType
|
mut info := sym.info as SumType
|
||||||
if info.found_fields {
|
if info.found_fields {
|
||||||
return
|
return
|
||||||
|
|
|
@ -64,6 +64,7 @@ pub fn pref_arch_to_table_language(pref_arch pref.Arch) Language {
|
||||||
// * Table.type_kind(typ) not TypeSymbol.kind.
|
// * Table.type_kind(typ) not TypeSymbol.kind.
|
||||||
// Each TypeSymbol is entered into `Table.types`.
|
// Each TypeSymbol is entered into `Table.types`.
|
||||||
// See also: Table.get_type_symbol.
|
// See also: Table.get_type_symbol.
|
||||||
|
|
||||||
pub struct TypeSymbol {
|
pub struct TypeSymbol {
|
||||||
pub:
|
pub:
|
||||||
parent_idx int
|
parent_idx int
|
||||||
|
@ -557,6 +558,15 @@ pub fn (t &TypeSymbol) sumtype_info() SumType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t &TypeSymbol) is_heap() bool {
|
||||||
|
if t.kind == .struct_ {
|
||||||
|
info := t.info as Struct
|
||||||
|
return info.is_heap
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn (t TypeSymbol) str() string {
|
pub fn (t TypeSymbol) str() string {
|
||||||
return t.name
|
return t.name
|
||||||
|
|
|
@ -152,7 +152,7 @@ pub fn (mut c Checker) check2(ast_file &ast.File) []errors.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) change_current_file(file &ast.File) {
|
pub fn (mut c Checker) change_current_file(file &ast.File) {
|
||||||
c.file = file
|
c.file = unsafe { file }
|
||||||
c.vmod_file_content = ''
|
c.vmod_file_content = ''
|
||||||
c.mod = file.mod.name
|
c.mod = file.mod.name
|
||||||
}
|
}
|
||||||
|
@ -666,11 +666,6 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
||||||
c.error('struct `$type_sym.name` is declared with a `[noinit]` attribute, so ' +
|
c.error('struct `$type_sym.name` is declared with a `[noinit]` attribute, so ' +
|
||||||
'it cannot be initialized with `$type_sym.name{}`', struct_init.pos)
|
'it cannot be initialized with `$type_sym.name{}`', struct_init.pos)
|
||||||
}
|
}
|
||||||
if info.is_heap && c.inside_decl_rhs && !c.inside_ref_lit && !c.inside_unsafe
|
|
||||||
&& !struct_init.typ.is_ptr() {
|
|
||||||
c.error('`$type_sym.name` type can only be used as a reference `&$type_sym.name` or inside a `struct` reference',
|
|
||||||
struct_init.pos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if type_sym.name.len == 1 && c.cur_fn.generic_names.len == 0 {
|
if type_sym.name.len == 1 && c.cur_fn.generic_names.len == 0 {
|
||||||
c.error('unknown struct `$type_sym.name`', struct_init.pos)
|
c.error('unknown struct `$type_sym.name`', struct_init.pos)
|
||||||
|
@ -754,9 +749,12 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mut expr_type := ast.Type(0)
|
||||||
|
mut expected_type := ast.Type(0)
|
||||||
if is_embed {
|
if is_embed {
|
||||||
c.expected_type = embed_type
|
expected_type = embed_type
|
||||||
expr_type := c.expr(field.expr)
|
c.expected_type = expected_type
|
||||||
|
expr_type = c.expr(field.expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||||
if expr_type != ast.void_type && expr_type_sym.kind != .placeholder {
|
if expr_type != ast.void_type && expr_type_sym.kind != .placeholder {
|
||||||
c.check_expected(expr_type, embed_type) or {
|
c.check_expected(expr_type, embed_type) or {
|
||||||
|
@ -769,8 +767,9 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
||||||
} else {
|
} else {
|
||||||
inited_fields << field_name
|
inited_fields << field_name
|
||||||
field_type_sym := c.table.get_type_symbol(info_field.typ)
|
field_type_sym := c.table.get_type_symbol(info_field.typ)
|
||||||
c.expected_type = info_field.typ
|
expected_type = info_field.typ
|
||||||
mut expr_type := c.expr(field.expr)
|
c.expected_type = expected_type
|
||||||
|
expr_type = c.expr(field.expr)
|
||||||
if !info_field.typ.has_flag(.optional) {
|
if !info_field.typ.has_flag(.optional) {
|
||||||
expr_type = c.check_expr_opt_call(field.expr, expr_type)
|
expr_type = c.check_expr_opt_call(field.expr, expr_type)
|
||||||
}
|
}
|
||||||
|
@ -798,6 +797,28 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) ast.Type {
|
||||||
struct_init.fields[i].typ = expr_type
|
struct_init.fields[i].typ = expr_type
|
||||||
struct_init.fields[i].expected_type = info_field.typ
|
struct_init.fields[i].expected_type = info_field.typ
|
||||||
}
|
}
|
||||||
|
if expr_type.is_ptr() && expected_type.is_ptr() {
|
||||||
|
if mut field.expr is ast.Ident {
|
||||||
|
if mut field.expr.obj is ast.Var {
|
||||||
|
mut obj := unsafe { &field.expr.obj }
|
||||||
|
if c.fn_scope != voidptr(0) {
|
||||||
|
obj = c.fn_scope.find_var(obj.name) or { obj }
|
||||||
|
}
|
||||||
|
if obj.is_stack_obj && !c.inside_unsafe {
|
||||||
|
sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0))
|
||||||
|
if !sym.is_heap() {
|
||||||
|
suggestion := if sym.kind == .struct_ {
|
||||||
|
'declaring `$sym.name` as `[heap]`'
|
||||||
|
} else {
|
||||||
|
'wrapping the `$sym.name` object in a `struct` declared as `[heap]`'
|
||||||
|
}
|
||||||
|
c.error('`$field.expr.name` cannot be assigned outside `unsafe` blocks as it might refer to an object stored on stack. Consider ${suggestion}.',
|
||||||
|
field.expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Check uninitialized refs/sum types
|
// Check uninitialized refs/sum types
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
|
@ -2954,6 +2975,29 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
c.error('fn `$c.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
c.error('fn `$c.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
|
if exp_type.is_ptr() && got_typ.is_ptr() {
|
||||||
|
mut r_expr := &return_stmt.exprs[i]
|
||||||
|
if mut r_expr is ast.Ident {
|
||||||
|
if mut r_expr.obj is ast.Var {
|
||||||
|
mut obj := unsafe { &r_expr.obj }
|
||||||
|
if c.fn_scope != voidptr(0) {
|
||||||
|
obj = c.fn_scope.find_var(r_expr.obj.name) or { obj }
|
||||||
|
}
|
||||||
|
if obj.is_stack_obj && !c.inside_unsafe {
|
||||||
|
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0))
|
||||||
|
if !type_sym.is_heap() {
|
||||||
|
suggestion := if type_sym.kind == .struct_ {
|
||||||
|
'declaring `$type_sym.name` as `[heap]`'
|
||||||
|
} else {
|
||||||
|
'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`'
|
||||||
|
}
|
||||||
|
c.error('`$r_expr.name` cannot be returned outside `unsafe` blocks as it might refer to an object stored on stack. Consider ${suggestion}.',
|
||||||
|
r_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if exp_is_optional && return_stmt.exprs.len > 0 {
|
if exp_is_optional && return_stmt.exprs.len > 0 {
|
||||||
expr0 := return_stmt.exprs[0]
|
expr0 := return_stmt.exprs[0]
|
||||||
|
@ -3176,6 +3220,28 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
c.fail_if_immutable(left)
|
c.fail_if_immutable(left)
|
||||||
// left_type = c.expr(left)
|
// left_type = c.expr(left)
|
||||||
}
|
}
|
||||||
|
if right_type.is_ptr() && left_type.is_ptr() {
|
||||||
|
if mut right is ast.Ident {
|
||||||
|
if mut right.obj is ast.Var {
|
||||||
|
mut obj := unsafe { &right.obj }
|
||||||
|
if c.fn_scope != voidptr(0) {
|
||||||
|
obj = c.fn_scope.find_var(right.obj.name) or { obj }
|
||||||
|
}
|
||||||
|
if obj.is_stack_obj && !c.inside_unsafe {
|
||||||
|
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0))
|
||||||
|
if !type_sym.is_heap() {
|
||||||
|
suggestion := if type_sym.kind == .struct_ {
|
||||||
|
'declaring `$type_sym.name` as `[heap]`'
|
||||||
|
} else {
|
||||||
|
'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`'
|
||||||
|
}
|
||||||
|
c.error('`$right.name` cannot be assigned outside `unsafe` blocks as it might refer to an object stored on stack. Consider ${suggestion}.',
|
||||||
|
right.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
assign_stmt.left_types << left_type
|
assign_stmt.left_types << left_type
|
||||||
match mut left {
|
match mut left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
@ -3216,6 +3282,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
if left.obj.is_auto_deref {
|
if left.obj.is_auto_deref {
|
||||||
left.obj.is_used = true
|
left.obj.is_used = true
|
||||||
}
|
}
|
||||||
|
if !left_type.is_ptr() {
|
||||||
|
if c.table.get_type_symbol(left_type).is_heap() {
|
||||||
|
left.obj.is_auto_heap = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.GlobalField {
|
ast.GlobalField {
|
||||||
left.obj.typ = left_type
|
left.obj.typ = left_type
|
||||||
|
@ -6046,17 +6117,27 @@ pub fn (mut c Checker) mark_as_referenced(mut node ast.Expr) {
|
||||||
if mut node.obj is ast.Var {
|
if mut node.obj is ast.Var {
|
||||||
mut obj := unsafe { &node.obj }
|
mut obj := unsafe { &node.obj }
|
||||||
if c.fn_scope != voidptr(0) {
|
if c.fn_scope != voidptr(0) {
|
||||||
obj = c.fn_scope.find_var(node.obj.name) or { unsafe { &node.obj } }
|
obj = c.fn_scope.find_var(node.obj.name) or { obj }
|
||||||
}
|
}
|
||||||
type_sym := c.table.get_type_symbol(obj.typ)
|
type_sym := c.table.get_type_symbol(obj.typ.set_nr_muls(0))
|
||||||
if obj.is_stack_obj {
|
if obj.is_stack_obj && !type_sym.is_heap() {
|
||||||
c.error('`$node.name` cannot be referenced outside `unsafe` blocks as it might be stored on stack. Consider declaring `$type_sym.name` as `[heap]`.',
|
suggestion := if type_sym.kind == .struct_ {
|
||||||
|
'declaring `$type_sym.name` as `[heap]`'
|
||||||
|
} else {
|
||||||
|
'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`'
|
||||||
|
}
|
||||||
|
c.error('`$node.name` cannot be referenced outside `unsafe` blocks as it might be stored on stack. Consider ${suggestion}.',
|
||||||
node.pos)
|
node.pos)
|
||||||
} else if type_sym.kind == .array_fixed {
|
} else if type_sym.kind == .array_fixed {
|
||||||
c.error('cannot reference fixed array `$node.name` outside `unsafe` blocks as it is supposed to be stored on stack',
|
c.error('cannot reference fixed array `$node.name` outside `unsafe` blocks as it is supposed to be stored on stack',
|
||||||
node.pos)
|
node.pos)
|
||||||
} else {
|
} else {
|
||||||
node.obj.is_auto_heap = true
|
if type_sym.kind == .struct_ {
|
||||||
|
info := type_sym.info as ast.Struct
|
||||||
|
if !info.is_heap {
|
||||||
|
node.obj.is_auto_heap = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6930,7 +7011,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.expected_type = ast.void_type
|
c.expected_type = ast.void_type
|
||||||
c.cur_fn = node
|
c.cur_fn = unsafe { node }
|
||||||
// Add return if `fn(...) ? {...}` have no return at end
|
// Add return if `fn(...) ? {...}` have no return at end
|
||||||
if node.return_type != ast.void_type && node.return_type.has_flag(.optional)
|
if node.return_type != ast.void_type && node.return_type.has_flag(.optional)
|
||||||
&& (node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return) {
|
&& (node.stmts.len == 0 || node.stmts[node.stmts.len - 1] !is ast.Return) {
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
vlib/v/checker/tests/heap_struct.vv:18:7: error: `Abc` type can only be used as a reference `&Abc` or inside a `struct` reference
|
|
||||||
16 |
|
|
||||||
17 | fn main() {
|
|
||||||
18 | a := Abc{ n: 3 }
|
|
||||||
| ~~~~~~~~~~~
|
|
||||||
19 | b := St{
|
|
||||||
20 | Abc{ n: 7 }
|
|
||||||
vlib/v/checker/tests/heap_struct.vv:19:7: error: `St` type can only be used as a reference `&St` or inside a `struct` reference
|
|
||||||
17 | fn main() {
|
|
||||||
18 | a := Abc{ n: 3 }
|
|
||||||
19 | b := St{
|
|
||||||
| ~~~
|
|
||||||
20 | Abc{ n: 7 }
|
|
||||||
21 | }
|
|
||||||
vlib/v/checker/tests/heap_struct.vv:20:3: error: `Abc` type can only be used as a reference `&Abc` or inside a `struct` reference
|
|
||||||
18 | a := Abc{ n: 3 }
|
|
||||||
19 | b := St{
|
|
||||||
20 | Abc{ n: 7 }
|
|
||||||
| ~~~~~~~~~~~
|
|
||||||
21 | }
|
|
||||||
22 | x := Qwe{
|
|
||||||
vlib/v/checker/tests/heap_struct.vv:22:7: error: `Qwe` type can only be used as a reference `&Qwe` or inside a `struct` reference
|
|
||||||
20 | Abc{ n: 7 }
|
|
||||||
21 | }
|
|
||||||
22 | x := Qwe{
|
|
||||||
| ~~~~
|
|
||||||
23 | f: 12.25
|
|
||||||
24 | a: Abc{ n: 23 }
|
|
||||||
vlib/v/checker/tests/heap_struct.vv:24:6: error: `Abc` type can only be used as a reference `&Abc` or inside a `struct` reference
|
|
||||||
22 | x := Qwe{
|
|
||||||
23 | f: 12.25
|
|
||||||
24 | a: Abc{ n: 23 }
|
|
||||||
| ~~~~~~~~~~~~
|
|
||||||
25 | }
|
|
||||||
26 | println('$a.n $b.n $x.a.n')
|
|
|
@ -1,27 +0,0 @@
|
||||||
[heap]
|
|
||||||
struct Abc {
|
|
||||||
mut:
|
|
||||||
n int
|
|
||||||
}
|
|
||||||
|
|
||||||
struct St {
|
|
||||||
Abc
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Qwe {
|
|
||||||
mut:
|
|
||||||
f f64
|
|
||||||
a Abc
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
a := Abc{ n: 3 }
|
|
||||||
b := St{
|
|
||||||
Abc{ n: 7 }
|
|
||||||
}
|
|
||||||
x := Qwe{
|
|
||||||
f: 12.25
|
|
||||||
a: Abc{ n: 23 }
|
|
||||||
}
|
|
||||||
println('$a.n $b.n $x.a.n')
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
vlib/v/checker/tests/no_heap_struct.vv:13:6: error: `x` cannot be assigned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `Abc` as `[heap]`.
|
||||||
|
11 | fn f(x &Abc) St {
|
||||||
|
12 | s := St{
|
||||||
|
13 | a: x
|
||||||
|
| ^
|
||||||
|
14 | }
|
||||||
|
15 | return s
|
||||||
|
vlib/v/checker/tests/no_heap_struct.vv:19:9: error: `x` cannot be returned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `Abc` as `[heap]`.
|
||||||
|
17 |
|
||||||
|
18 | fn g(mut x Abc) &Abc {
|
||||||
|
19 | return x
|
||||||
|
| ^
|
||||||
|
20 | }
|
||||||
|
21 |
|
||||||
|
vlib/v/checker/tests/no_heap_struct.vv:23:7: error: `x` cannot be assigned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `Abc` as `[heap]`.
|
||||||
|
21 |
|
||||||
|
22 | fn h(x &Abc) &Abc {
|
||||||
|
23 | y := x
|
||||||
|
| ^
|
||||||
|
24 | return y
|
||||||
|
25 | }
|
|
@ -0,0 +1,25 @@
|
||||||
|
struct Abc {
|
||||||
|
mut:
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct St {
|
||||||
|
mut:
|
||||||
|
a &Abc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f(x &Abc) St {
|
||||||
|
s := St{
|
||||||
|
a: x
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn g(mut x Abc) &Abc {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn h(x &Abc) &Abc {
|
||||||
|
y := x
|
||||||
|
return y
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ mut:
|
||||||
methods map[string][]ast.FnDecl
|
methods map[string][]ast.FnDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
struct JsGen {
|
struct JsGen {
|
||||||
table &ast.Table
|
table &ast.Table
|
||||||
pref &pref.Preferences
|
pref &pref.Preferences
|
||||||
|
|
|
@ -20,6 +20,7 @@ interface CodeGen {
|
||||||
// XXX WHY gen_exit fn (expr ast.Expr)
|
// XXX WHY gen_exit fn (expr ast.Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
pub struct Gen {
|
pub struct Gen {
|
||||||
out_name string
|
out_name string
|
||||||
pref &pref.Preferences // Preferences shared from V struct
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
|
@ -67,7 +68,7 @@ fn (g &Gen) get_backend() ?CodeGen {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, table &ast.Table, out_name string, pref &pref.Preferences) (int, int) {
|
pub fn gen(files []ast.File, table &ast.Table, out_name string, pref &pref.Preferences) (int, int) {
|
||||||
mut g := Gen{
|
mut g := &Gen{
|
||||||
table: table
|
table: table
|
||||||
sect_header_name_pos: 0
|
sect_header_name_pos: 0
|
||||||
out_name: out_name
|
out_name: out_name
|
||||||
|
|
|
@ -292,19 +292,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
scope: 0
|
scope: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut is_heap_ref := false // args are only borrowed, so assume maybe on stack
|
|
||||||
mut is_stack_obj := true
|
mut is_stack_obj := true
|
||||||
nr_muls := param.typ.nr_muls()
|
|
||||||
if nr_muls == 1 { // mut a St, b &St
|
|
||||||
base_type_sym := p.table.get_type_symbol(param.typ.set_nr_muls(0))
|
|
||||||
if base_type_sym.kind == .struct_ {
|
|
||||||
info := base_type_sym.info as ast.Struct
|
|
||||||
is_heap_ref = info.is_heap // if type is declared as [heap] we can assume this, too
|
|
||||||
is_stack_obj = !is_heap_ref
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if param.typ.has_flag(.shared_f) {
|
if param.typ.has_flag(.shared_f) {
|
||||||
is_heap_ref = true
|
|
||||||
is_stack_obj = false
|
is_stack_obj = false
|
||||||
}
|
}
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
|
@ -312,7 +301,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
typ: param.typ
|
typ: param.typ
|
||||||
is_mut: param.is_mut
|
is_mut: param.is_mut
|
||||||
is_auto_deref: param.is_mut || param.is_auto_rec
|
is_auto_deref: param.is_mut || param.is_auto_rec
|
||||||
is_heap_ref: is_heap_ref
|
|
||||||
is_stack_obj: is_stack_obj
|
is_stack_obj: is_stack_obj
|
||||||
pos: param.pos
|
pos: param.pos
|
||||||
is_used: true
|
is_used: true
|
||||||
|
@ -601,19 +589,8 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||||
if arg.name.len == 0 {
|
if arg.name.len == 0 {
|
||||||
p.error_with_pos('use `_` to name an unused parameter', arg.pos)
|
p.error_with_pos('use `_` to name an unused parameter', arg.pos)
|
||||||
}
|
}
|
||||||
mut is_heap_ref := false // args are only borrowed, so assume maybe on stack
|
|
||||||
mut is_stack_obj := true
|
mut is_stack_obj := true
|
||||||
nr_muls := arg.typ.nr_muls()
|
|
||||||
if nr_muls == 1 { // mut a St, b &St
|
|
||||||
base_type_sym := p.table.get_type_symbol(arg.typ.set_nr_muls(0))
|
|
||||||
if base_type_sym.kind == .struct_ {
|
|
||||||
info := base_type_sym.info as ast.Struct
|
|
||||||
is_heap_ref = info.is_heap // if type is declared as [heap] we can assume this, too
|
|
||||||
is_stack_obj = !is_heap_ref
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if arg.typ.has_flag(.shared_f) {
|
if arg.typ.has_flag(.shared_f) {
|
||||||
is_heap_ref = true
|
|
||||||
is_stack_obj = false
|
is_stack_obj = false
|
||||||
}
|
}
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
|
@ -623,7 +600,6 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||||
pos: arg.pos
|
pos: arg.pos
|
||||||
is_used: true
|
is_used: true
|
||||||
is_arg: true
|
is_arg: true
|
||||||
is_heap_ref: is_heap_ref
|
|
||||||
is_stack_obj: is_stack_obj
|
is_stack_obj: is_stack_obj
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
struct Qwe {
|
[heap]
|
||||||
|
struct Hwe {
|
||||||
mut:
|
mut:
|
||||||
n int
|
n int
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_x(mut x Qwe) &Qwe {
|
fn mut_x(mut x Hwe) &Hwe {
|
||||||
n := x.n
|
n := x.n
|
||||||
// defer statement should not have run, yet
|
// defer statement should not have run, yet
|
||||||
assert n == 10
|
assert n == 10
|
||||||
x.n += 5
|
x.n += 5
|
||||||
return unsafe { &x }
|
return &x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deferer() &Qwe {
|
fn deferer() &Hwe {
|
||||||
mut s := &Qwe{
|
mut s := &Hwe{
|
||||||
n: 10
|
n: 10
|
||||||
}
|
}
|
||||||
defer {
|
defer {
|
||||||
|
@ -28,6 +29,15 @@ fn test_defer_in_return() {
|
||||||
assert q.n == 17
|
assert q.n == 17
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Qwe {
|
||||||
|
mut:
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ret_ref(mut x Qwe) &Qwe {
|
||||||
|
return unsafe { x }
|
||||||
|
}
|
||||||
|
|
||||||
fn defer_multi_ret(mut a Qwe) (int, f64) {
|
fn defer_multi_ret(mut a Qwe) (int, f64) {
|
||||||
defer {
|
defer {
|
||||||
a.n *= 2
|
a.n *= 2
|
||||||
|
|
|
@ -5,7 +5,7 @@ mut:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut s MyStruct<T>) add(e &T) bool {
|
fn (mut s MyStruct<T>) add(e &T) bool {
|
||||||
s.buffer[0] = e
|
s.buffer[0] = unsafe { e }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub fn (mut gitstructure GitStructure) repo_get(name string) ?&GitRepo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_opt_ref_return() {
|
fn test_opt_ref_return() {
|
||||||
mut gitstruct := &GitStructure{
|
mut gitstruct := GitStructure{
|
||||||
root: 'r'
|
root: 'r'
|
||||||
repos: [
|
repos: [
|
||||||
&GitRepo{
|
&GitRepo{
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
[heap]
|
||||||
|
struct Abc {
|
||||||
|
mut:
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct St {
|
||||||
|
Abc
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Qwe {
|
||||||
|
mut:
|
||||||
|
f f64
|
||||||
|
a Abc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pass_abc(q &Abc) &Abc {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pass_st(q &St) &St {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pass_qwe(q &Qwe) &Qwe {
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_ref_structs() (&Abc, &St, &Qwe) {
|
||||||
|
a := Abc{
|
||||||
|
n: 3
|
||||||
|
}
|
||||||
|
b := St{Abc{
|
||||||
|
n: 7
|
||||||
|
}}
|
||||||
|
x := Qwe{
|
||||||
|
f: 12.25
|
||||||
|
a: Abc{
|
||||||
|
n: 23
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aa := pass_abc(&a)
|
||||||
|
bb := pass_st(&b)
|
||||||
|
xx := pass_qwe(&x)
|
||||||
|
return aa, bb, xx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn owerwrite_stack() f64 {
|
||||||
|
a := 12.5
|
||||||
|
b := 3.5
|
||||||
|
c := a + b
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_ref_struct() {
|
||||||
|
u, v, w := get_ref_structs()
|
||||||
|
d := owerwrite_stack()
|
||||||
|
assert u.n == 3
|
||||||
|
assert v.n == 7
|
||||||
|
assert w.a.n == 23
|
||||||
|
}
|
|
@ -11,17 +11,17 @@ fn new(x int) &Test {
|
||||||
|
|
||||||
fn (mut t Test) inc() &Test {
|
fn (mut t Test) inc() &Test {
|
||||||
t.val++
|
t.val++
|
||||||
return t
|
return unsafe { t }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut t Test) add(x int) &Test {
|
fn (mut t Test) add(x int) &Test {
|
||||||
t.val += x
|
t.val += x
|
||||||
return t
|
return unsafe { t }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut t Test) div(x int) &Test {
|
fn (mut t Test) div(x int) &Test {
|
||||||
t.val /= x
|
t.val /= x
|
||||||
return t
|
return unsafe { t }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_method_call_chains() {
|
fn test_method_call_chains() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ mut:
|
||||||
|
|
||||||
fn (mut p Player) set_name(name string) &Player {
|
fn (mut p Player) set_name(name string) &Player {
|
||||||
p.name = name
|
p.name = name
|
||||||
return p // because of automatic (de)reference of return values
|
return unsafe { p } // because of automatic (de)reference of return values
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: `p` is declared as a `mut` parameter,
|
// NB: `p` is declared as a `mut` parameter,
|
||||||
|
|
|
@ -231,7 +231,7 @@ fn opt_ptr(a &int) ?&int {
|
||||||
if isnil(a) {
|
if isnil(a) {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
return a
|
return unsafe { a }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_opt_ptr() {
|
fn test_opt_ptr() {
|
||||||
|
|
|
@ -264,7 +264,7 @@ fn bar_config(c Config, def int) {
|
||||||
fn mut_bar_config(mut c Config, def int) &Config {
|
fn mut_bar_config(mut c Config, def int) &Config {
|
||||||
c.n = c.def
|
c.n = c.def
|
||||||
assert c.n == def
|
assert c.n == def
|
||||||
return c
|
return unsafe { c }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo_user(u User) {}
|
fn foo_user(u User) {}
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub struct SSEMessage {
|
||||||
|
|
||||||
pub fn new_connection(conn &net.TcpConn) &SSEConnection {
|
pub fn new_connection(conn &net.TcpConn) &SSEConnection {
|
||||||
return &SSEConnection{
|
return &SSEConnection{
|
||||||
conn: conn
|
conn: unsafe { conn }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
||||||
}
|
}
|
||||||
app.Context = Context{
|
app.Context = Context{
|
||||||
req: req
|
req: req
|
||||||
conn: conn
|
conn: unsafe { conn }
|
||||||
form: map[string]string{}
|
form: map[string]string{}
|
||||||
static_files: app.static_files
|
static_files: app.static_files
|
||||||
static_mime_types: app.static_mime_types
|
static_mime_types: app.static_mime_types
|
||||||
|
|
|
@ -98,8 +98,8 @@ fn (mut s Server) parse_client_handshake(client_handshake string, mut c Client)
|
||||||
server_client := &ServerClient{
|
server_client := &ServerClient{
|
||||||
resource_name: get_tokens[1]
|
resource_name: get_tokens[1]
|
||||||
client_key: key
|
client_key: key
|
||||||
client: c
|
client: unsafe { c }
|
||||||
server: s
|
server: unsafe { s }
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
lines.free()
|
lines.free()
|
||||||
|
|
Loading…
Reference in New Issue