mirror of
https://github.com/odin-lang/Odin.git
synced 2026-10-09 14:22:18 -04:00
Remove parapoly scaffolding and fix map internal generation
This commit is contained in:
1 parent
48272ac257
commit
93a3312a29
2 files changed
+40
-28
No files matched your search
@@ -1475,6 +1475,11 @@ gb_internal bool polymorphic_assign_index(Type **gt_, i64 *dst_count, i64 source
|
||||
return false;
|
||||
}
|
||||
|
||||
// In-place matcher: mutates `poly` to bind its polymorphic vars to `source`. This is no longer the
|
||||
// primary resolver (see the substitution engine in check_type.cpp). determine_type_from_polymorphic
|
||||
// uses it only as a fallback for the patterns the engine reports Subst_Unhandled for (genuine
|
||||
// subtyping, and the ^<->[^] case) and for the non-modify_type (no_polymorphic_errors) yes/no probe.
|
||||
// The probe keeps every kind here reachable, so these cases are not dead code.
|
||||
gb_internal bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool compound, bool modify_type) {
|
||||
Operand o = {Addressing_Value};
|
||||
o.type = source;
|
||||
|
||||
+35
-28
@@ -1848,18 +1848,19 @@ gb_internal bool check_type_specialization_to(CheckerContext *ctx, Type *special
|
||||
}
|
||||
|
||||
|
||||
// subst_unify matches a polymorphic pattern against a source PURELY (no node/entity mutation),
|
||||
// accumulating bindings; subst_apply reconstructs the instantiated type by CONSTRUCTION. Guarded by
|
||||
// PARAPOLY_VERIFY_SUBST, determine_type_from_polymorphic runs these alongside the existing in-place
|
||||
// mutation and asserts the two agree, proving the constructive path before anything relies on it.
|
||||
// Coverage is a slice (generic/basic/slice/dynamic-array/fixed [$N]$T); other kinds report
|
||||
// Subst_Unhandled and are skipped. No behavior change. This is refactor scaffolding: it runs a
|
||||
// second (constructive) match per instantiation, so set to 0 (or gate to debug) before release.
|
||||
#define PARAPOLY_VERIFY_SUBST 1
|
||||
// When 1, the substitution is authoritative for handled patterns: determine_type_from_polymorphic
|
||||
// binds the poly-scope entities from the PolySubst and returns the constructed type WITHOUT running
|
||||
// the in-place mutation. When 0, the mutation runs and the subst path only verifies against it.
|
||||
#define PARAPOLY_SUBST_AUTHORITATIVE 1
|
||||
// The substitution engine is the primary way a polymorphic parameter type is resolved:
|
||||
// `subst_unify` matches a pattern against a source PURELY (no node/entity mutation), accumulating
|
||||
// bindings; `subst_apply` reconstructs the instantiated type by CONSTRUCTION; `subst_bind_entities`
|
||||
// binds the poly-scope entities. `determine_type_from_polymorphic` uses them for every pattern the
|
||||
// engine reports `Subst_Matched` for. The in-place mutator `is_polymorphic_type_assignable` remains
|
||||
// only as a fallback for the patterns the engine leaves `Subst_Unhandled` (genuine subtyping, and the
|
||||
// `[^]<->^` handled-by-mutator case), and for the non-`modify_type` yes/no probe.
|
||||
//
|
||||
// PARAPOLY_DEBUG_VERIFY_SUBST is an off-by-default differential debug switch: it makes the old mutator
|
||||
// authoritative and asserts the engine agrees with it (constructed type + entity bindings) on every
|
||||
// instantiation. It compares types structurally via are_types_identical, so it CANNOT catch codegen
|
||||
// state the engine must still set up (e.g. a map's internal types); those need build+run tests.
|
||||
#define PARAPOLY_DEBUG_VERIFY_SUBST 0
|
||||
|
||||
enum SubstResult : u8 {
|
||||
Subst_Unhandled,
|
||||
@@ -2467,6 +2468,7 @@ gb_internal Type *subst_apply(CheckerContext *c, Type *pattern, Type *source, Po
|
||||
Type *m = alloc_type(Type_Map);
|
||||
m->Map.key = subst_apply(c, pattern->Map.key, source->Map.key, subst);
|
||||
m->Map.value = subst_apply(c, pattern->Map.value, source->Map.value, subst);
|
||||
init_map_internal_types(m); // the mutator does this; without it codegen hits a t_invalid
|
||||
return m;
|
||||
}
|
||||
case Type_Array: {
|
||||
@@ -2645,7 +2647,7 @@ gb_internal void subst_bind_entities(PolySubst *subst) {
|
||||
}
|
||||
}
|
||||
|
||||
#if PARAPOLY_VERIFY_SUBST
|
||||
#if PARAPOLY_DEBUG_VERIFY_SUBST
|
||||
// Read-only: assert that the in-place mutation bound each poly-scope entity to exactly what the
|
||||
// substitution captured. This is the entity-level analogue of the apply-reproduction check; once it
|
||||
// holds everywhere, entity binding can be driven from the PolySubst and the mutation removed.
|
||||
@@ -2694,7 +2696,26 @@ gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *pol
|
||||
return t_invalid;
|
||||
}
|
||||
|
||||
#if PARAPOLY_VERIFY_SUBST
|
||||
#if !PARAPOLY_DEBUG_VERIFY_SUBST
|
||||
// Primary path: the substitution engine constructs the instantiation and binds the poly-scope
|
||||
// entities. Patterns it reports Subst_Unhandled for fall through to the mutator fallback below.
|
||||
if (modify_type) {
|
||||
PolySubst subst = {};
|
||||
subst.items.allocator = heap_allocator();
|
||||
defer (array_free(&subst.items));
|
||||
if (subst_unify(ctx, poly_type, operand.type, &subst) == Subst_Matched) {
|
||||
Type *applied = subst_apply(ctx, poly_type, operand.type, &subst);
|
||||
subst_bind_entities(&subst);
|
||||
return applied;
|
||||
}
|
||||
}
|
||||
// Fallback: the in-place mutator handles the deferred patterns (genuine subtyping) and the
|
||||
// non-modify_type probe. A Subst_NoMatch also lands here and the mutator fails too -> error path.
|
||||
if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
|
||||
return poly_type;
|
||||
}
|
||||
#else
|
||||
// Debug differential: the mutator is authoritative and the engine is asserted to agree with it.
|
||||
PolySubst verify_subst = {};
|
||||
verify_subst.items.allocator = heap_allocator();
|
||||
defer (array_free(&verify_subst.items));
|
||||
@@ -2706,19 +2727,7 @@ gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *pol
|
||||
verify_applied = subst_apply(ctx, poly_type, operand.type, &verify_subst);
|
||||
}
|
||||
}
|
||||
#if PARAPOLY_SUBST_AUTHORITATIVE
|
||||
if (verify_ur == Subst_Matched) {
|
||||
// Substitution is authoritative: bind the poly-scope entities and return the constructed
|
||||
// type; the in-place mutation is not run. (A handled NoMatch falls through and the mutation
|
||||
// will also fail, reaching the error path.)
|
||||
subst_bind_entities(&verify_subst);
|
||||
return verify_applied;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
|
||||
#if PARAPOLY_VERIFY_SUBST && !PARAPOLY_SUBST_AUTHORITATIVE
|
||||
if (verify_ur == Subst_Matched) {
|
||||
GB_ASSERT_MSG(are_types_identical(verify_applied, poly_type),
|
||||
"parapoly subst mismatch: applied '%s' vs mutated '%s'",
|
||||
@@ -2728,10 +2737,8 @@ gb_internal Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *pol
|
||||
} else if (verify_ur == Subst_NoMatch) {
|
||||
GB_PANIC("parapoly subst reported NoMatch but in-place match succeeded (result '%s')", type_to_string(poly_type));
|
||||
}
|
||||
#endif
|
||||
return poly_type;
|
||||
}
|
||||
#if PARAPOLY_VERIFY_SUBST && !PARAPOLY_SUBST_AUTHORITATIVE
|
||||
if (verify_ur == Subst_Matched) {
|
||||
GB_PANIC("parapoly subst matched but in-place match failed");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user