cgen: fix shared field init (#11061)
							parent
							
								
									44bacfc931
								
							
						
					
					
						commit
						91ade5bf8c
					
				| 
						 | 
				
			
			@ -2004,7 +2004,10 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
 | 
			
		|||
		} else {
 | 
			
		||||
			g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =')
 | 
			
		||||
		}
 | 
			
		||||
		old_is_shared := g.is_shared
 | 
			
		||||
		g.is_shared = false
 | 
			
		||||
		g.expr(expr)
 | 
			
		||||
		g.is_shared = old_is_shared
 | 
			
		||||
		g.writeln('}, sizeof($shared_styp))')
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -5241,7 +5244,11 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
			
		|||
	}
 | 
			
		||||
	// User set fields
 | 
			
		||||
	mut initialized := false
 | 
			
		||||
	mut old_is_shared := g.is_shared
 | 
			
		||||
	for i, field in struct_init.fields {
 | 
			
		||||
		if !field.typ.has_flag(.shared_f) {
 | 
			
		||||
			g.is_shared = false
 | 
			
		||||
		}
 | 
			
		||||
		inited_fields[field.name] = i
 | 
			
		||||
		if sym.kind != .struct_ {
 | 
			
		||||
			field_name := if sym.language == .v { c_name(field.name) } else { field.name }
 | 
			
		||||
| 
						 | 
				
			
			@ -5273,7 +5280,9 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
			
		|||
			}
 | 
			
		||||
			initialized = true
 | 
			
		||||
		}
 | 
			
		||||
		g.is_shared = old_is_shared
 | 
			
		||||
	}
 | 
			
		||||
	g.is_shared = old_is_shared
 | 
			
		||||
	// The rest of the fields are zeroed.
 | 
			
		||||
	// `inited_fields` is a list of fields that have been init'ed, they are skipped
 | 
			
		||||
	mut nr_fields := 1
 | 
			
		||||
| 
						 | 
				
			
			@ -5284,6 +5293,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
			
		|||
			verror('union must not have more than 1 initializer')
 | 
			
		||||
		}
 | 
			
		||||
		if !info.is_union {
 | 
			
		||||
			old_is_shared2 := g.is_shared
 | 
			
		||||
			mut used_embed_fields := []string{}
 | 
			
		||||
			init_field_names := info.fields.map(it.name)
 | 
			
		||||
			// fields that are initialized but belong to the embedding
 | 
			
		||||
| 
						 | 
				
			
			@ -5311,10 +5321,14 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
			
		|||
					initialized = true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			g.is_shared = old_is_shared2
 | 
			
		||||
		}
 | 
			
		||||
		// g.zero_struct_fields(info, inited_fields)
 | 
			
		||||
		// nr_fields = info.fields.len
 | 
			
		||||
		for mut field in info.fields {
 | 
			
		||||
			if !field.typ.has_flag(.shared_f) {
 | 
			
		||||
				g.is_shared = false
 | 
			
		||||
			}
 | 
			
		||||
			if mut sym.info is ast.Struct {
 | 
			
		||||
				mut found_equal_fields := 0
 | 
			
		||||
				for mut sifield in sym.info.fields {
 | 
			
		||||
| 
						 | 
				
			
			@ -5391,7 +5405,9 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
 | 
			
		|||
				g.write(',')
 | 
			
		||||
			}
 | 
			
		||||
			initialized = true
 | 
			
		||||
			g.is_shared = old_is_shared
 | 
			
		||||
		}
 | 
			
		||||
		g.is_shared = old_is_shared
 | 
			
		||||
	}
 | 
			
		||||
	if is_multiline {
 | 
			
		||||
		g.indent--
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,3 +50,28 @@ fn test_shared_lock() {
 | 
			
		|||
		assert x.a == 7 && y.a == 5
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct App {
 | 
			
		||||
	id string = 'test'
 | 
			
		||||
mut:
 | 
			
		||||
	app_data shared AppData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut a App) init_server_direct() {
 | 
			
		||||
	lock a.app_data {
 | 
			
		||||
		a.app_data = AppData{}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct AppData {
 | 
			
		||||
	id string = 'foo'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_shared_field_init() {
 | 
			
		||||
	mut app1 := App{}
 | 
			
		||||
	app1.init_server_direct()
 | 
			
		||||
	id := rlock app1.app_data {
 | 
			
		||||
		app1.app_data.id
 | 
			
		||||
	}
 | 
			
		||||
	assert id == 'foo'
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue