Skip to content

Commit 90d0660

Browse files
committed
refactor: properly separate type resolution between parser and compiler
**Architecture**: - Parser builds TypedAST with Type::Unresolved for unknown types - Parser tracks declared types (from @opaque, struct, enum) for immediate resolution - Compiler resolves all Type::Unresolved via TypeRegistry before lowering - SSA builder now sees fully resolved types for proper trait dispatch **Changes**: - Added Type::Unresolved variant for types to be resolved by compiler - Parser tracks declared_types HashMap for types defined in current file - Added resolve_unresolved_types pass in runtime before lowering - Removed duplicate type resolution logic from embed runtime - Fixed constraint solver to handle Type::Unresolved - Lowering still has Type::Unresolved handling as fallback **Result**: Operator overloading with imported types now works correctly - types are resolved before SSA, enabling proper trait dispatch for binary operations.
1 parent 3c873ff commit 90d0660

5 files changed

Lines changed: 268 additions & 32 deletions

File tree

crates/compiler/src/lowering.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,19 @@ impl LoweringContext {
966966
HirType::Opaque(*name)
967967
}
968968

969+
Type::Unresolved(name) => {
970+
// Look up the type in TypeRegistry aliases
971+
eprintln!("[DEBUG convert_type] Resolving unresolved type '{}'", name.resolve_global().unwrap_or_default());
972+
if let Some(resolved_type) = self.type_registry.resolve_alias(*name) {
973+
eprintln!("[DEBUG convert_type] Found alias for '{}': {:?}", name.resolve_global().unwrap_or_default(), resolved_type);
974+
// Recursively convert the resolved type
975+
self.convert_type(resolved_type)
976+
} else {
977+
eprintln!("[WARN] Could not resolve type '{}', defaulting to I64", name.resolve_global().unwrap_or_default());
978+
HirType::I64 // Fallback
979+
}
980+
}
981+
969982
Type::Named { id, .. } => {
970983
// Look up type definition in registry
971984
if let Some(type_def) = self.type_registry.get_type_by_id(*id) {

crates/typed_ast/src/constraint_solver.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ impl Substitution {
248248
| Type::Any
249249
| Type::Error
250250
| Type::HigherKinded { .. }
251-
| Type::Extern { .. } => ty.clone(),
251+
| Type::Extern { .. }
252+
| Type::Unresolved(_) => ty.clone(),
252253
Type::Nullable(inner_ty) => {
253254
// For nullable types, substitute the inner type and maintain nullability
254255
let substituted_inner = self.apply(inner_ty);
@@ -2644,6 +2645,10 @@ impl ConstraintSolver {
26442645
// Format extern/opaque type by name
26452646
name.resolve_global().unwrap_or_else(|| format!("extern_{}", name.symbol().to_usize()))
26462647
}
2648+
Type::Unresolved(name) => {
2649+
// Format unresolved type by name
2650+
name.resolve_global().unwrap_or_else(|| format!("unresolved_{}", name.symbol().to_usize()))
2651+
}
26472652
}
26482653
}
26492654

@@ -3400,7 +3405,8 @@ impl ConstraintSolver {
34003405
| Type::Error
34013406
| Type::SelfType
34023407
| Type::HigherKinded { .. }
3403-
| Type::Extern { .. } => ty.clone(),
3408+
| Type::Extern { .. }
3409+
| Type::Unresolved(_) => ty.clone(),
34043410
Type::Nullable(inner_ty) => {
34053411
// For nullable types, substitute the inner type and maintain nullability
34063412
let substituted_inner = self.resolve_associated_types(inner_ty, receiver_type);
@@ -3458,7 +3464,7 @@ impl ConstraintSolver {
34583464
associated_types,
34593465
super_traits,
34603466
} => todo!(),
3461-
Type::Extern { .. } => ty.clone(),
3467+
Type::Extern { .. } | Type::Unresolved(_) => ty.clone(),
34623468
}
34633469
}
34643470

@@ -3571,7 +3577,8 @@ impl ConstraintSolver {
35713577
| Type::Error
35723578
| Type::Associated { .. }
35733579
| Type::HigherKinded { .. }
3574-
| Type::Extern { .. } => ty.clone(),
3580+
| Type::Extern { .. }
3581+
| Type::Unresolved(_) => ty.clone(),
35753582
Type::Nullable(inner_ty) => {
35763583
// For nullable types, substitute the inner type and maintain nullability
35773584
let substituted_inner = self.substitute_self_type(inner_ty, receiver_type);

crates/typed_ast/src/type_registry.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,11 @@ pub enum Type {
436436
name: InternedString,
437437
layout: Option<ExternLayout>,
438438
},
439+
440+
/// Unresolved type name (placeholder from parser, to be resolved by compiler)
441+
/// The compiler's type resolution pass will look this up in TypeRegistry aliases
442+
/// and replace it with the actual type (e.g., Type::Extern)
443+
Unresolved(InternedString),
439444
}
440445

441446
/// Layout information for extern types (optional)

crates/zyn_peg/src/runtime.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,9 @@ pub struct TypedAstBuilder {
11131113
variable_types: HashMap<String, Type>,
11141114
/// Enum type name to variant names (in order, for discriminant calculation)
11151115
enum_types: HashMap<String, Vec<String>>,
1116+
/// Type declarations defined in the current file (name -> Type)
1117+
/// Tracks types from @opaque, struct, enum declarations so type references can be resolved
1118+
declared_types: HashMap<String, Type>,
11161119
/// Program declaration handles (in order)
11171120
program_decls: Vec<NodeHandle>,
11181121
/// Current span being processed (start, end)
@@ -1145,6 +1148,7 @@ impl TypedAstBuilder {
11451148
types: HashMap::new(),
11461149
variable_types: HashMap::new(),
11471150
enum_types: HashMap::new(),
1151+
declared_types: HashMap::new(),
11481152
program_decls: Vec::new(),
11491153
current_span: (0, 0),
11501154
}
@@ -1607,6 +1611,14 @@ impl AstHostFunctions for TypedAstBuilder {
16071611
let name_interned = self.inner.intern(name);
16081612
let runtime_prefix = self.inner.intern(external_name);
16091613

1614+
// Register this extern type so type references can be resolved
1615+
let extern_type = Type::Extern {
1616+
name: runtime_prefix,
1617+
layout: None,
1618+
};
1619+
self.declared_types.insert(name.to_string(), extern_type);
1620+
eprintln!("[DEBUG create_opaque_type] Registered extern type '{}' -> Extern({})", name, external_name);
1621+
16101622
let extern_struct = TypedExternStruct {
16111623
name: name_interned,
16121624
runtime_prefix,
@@ -2090,15 +2102,10 @@ impl AstHostFunctions for TypedAstBuilder {
20902102
"bool" => Type::Primitive(PrimitiveType::Bool),
20912103
"void" | "unit" => Type::Primitive(PrimitiveType::Unit),
20922104
_ => {
2093-
// Unknown type - use Named with placeholder for compiler resolution
2094-
eprintln!("[DEBUG create_primitive_type] Unknown type '{}', creating Named with placeholder TypeId(0)", name);
2095-
Type::Named {
2096-
id: zyntax_typed_ast::TypeId::new(0),
2097-
type_args: vec![],
2098-
const_args: vec![],
2099-
variance: vec![],
2100-
nullability: zyntax_typed_ast::type_registry::NullabilityKind::NonNull,
2101-
}
2105+
// Unknown type - create unresolved for compiler resolution
2106+
eprintln!("[DEBUG create_primitive_type] Unknown type '{}', creating Unresolved", name);
2107+
let name_interned = self.inner.intern(name);
2108+
Type::Unresolved(name_interned)
21022109
}
21032110
};
21042111
self.types.insert(handle, ty);
@@ -2124,16 +2131,16 @@ impl AstHostFunctions for TypedAstBuilder {
21242131
fn create_named_type(&mut self, name: &str) -> NodeHandle {
21252132
let handle = self.alloc_handle();
21262133

2127-
// Create a named type with placeholder ID (0)
2128-
// The compiler's type resolution phase will resolve this to the actual TypeId
2129-
// using the TypeRegistry
2130-
eprintln!("[DEBUG create_named_type] Creating named type '{}' with placeholder TypeId(0)", name);
2131-
let ty = Type::Named {
2132-
id: zyntax_typed_ast::TypeId::new(0),
2133-
type_args: vec![],
2134-
const_args: vec![],
2135-
variance: vec![],
2136-
nullability: zyntax_typed_ast::type_registry::NullabilityKind::NonNull,
2134+
// Check if this type was declared in the current file (e.g., via @opaque, struct, enum)
2135+
let ty = if let Some(declared_ty) = self.declared_types.get(name) {
2136+
eprintln!("[DEBUG create_named_type] Found declared type '{}': {:?}", name, declared_ty);
2137+
declared_ty.clone()
2138+
} else {
2139+
// Type not found in current file - create unresolved for compiler resolution
2140+
// This handles types from imports or forward references
2141+
eprintln!("[DEBUG create_named_type] Creating unresolved type '{}'", name);
2142+
let name_interned = self.inner.intern(name);
2143+
Type::Unresolved(name_interned)
21372144
};
21382145

21392146
self.types.insert(handle, ty);

0 commit comments

Comments
 (0)