self-referential c record imports
This commit is contained in:
@@ -640,9 +640,23 @@ is_c_signature_type :: proc(value: Type, store: ^Store, allow_void := false) ->
|
||||
(is_c_struct(value, store) && is_runtime_value(value, store))
|
||||
}
|
||||
|
||||
contains_distinct :: proc(value: Type, store: ^Store, depth := 0) -> bool {
|
||||
if depth > 256 {
|
||||
return true
|
||||
// contains_distinct reports whether a `distinct` type is reachable from `value`
|
||||
// (by value, behind a pointer, through fields/params/children). A pointer to a
|
||||
// distinct type still counts — distinct types do not cross the C ABI even behind
|
||||
// indirection. The `seen` set makes the graph walk terminate on self-referential
|
||||
// records (e.g. `?*mut Node` inside `Node`), which previously recursed until the
|
||||
// depth cap and wrongly reported `true`.
|
||||
contains_distinct :: proc(value: Type, store: ^Store) -> bool {
|
||||
seen: [dynamic]Type
|
||||
defer delete(seen)
|
||||
return contains_distinct_seen(value, store, &seen)
|
||||
}
|
||||
|
||||
contains_distinct_seen :: proc(value: Type, store: ^Store, seen: ^[dynamic]Type) -> bool {
|
||||
for visited in seen {
|
||||
if visited == value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
item, ok := node(store, value)
|
||||
if !ok {
|
||||
@@ -651,21 +665,22 @@ contains_distinct :: proc(value: Type, store: ^Store, depth := 0) -> bool {
|
||||
if item.kind == .Distinct {
|
||||
return true
|
||||
}
|
||||
append(seen, value)
|
||||
if item.kind == .Struct || item.kind == .Union {
|
||||
for field in fields_for(store, value) {
|
||||
if contains_distinct(field.type, store, depth+1) {
|
||||
if contains_distinct_seen(field.type, store, seen) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
if item.kind == .Function {
|
||||
for param in params_for(store, value) {
|
||||
if contains_distinct(param.type, store, depth+1) {
|
||||
if contains_distinct_seen(param.type, store, seen) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return is_valid(item.child) && contains_distinct(item.child, store, depth+1)
|
||||
return is_valid(item.child) && contains_distinct_seen(item.child, store, seen)
|
||||
}
|
||||
|
||||
is_c_integer_promotion_candidate :: proc(value: Type) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user