When a generic function indexes the same TypeVar parameter multiple
times,
all resulting TypeVars must share a single element type. This change
ensures
that subsequent indexing operations unify their fresh TypeVar with an
existing
one if the parameter has already been indexed, preventing incorrect type
inference and false negatives.
A new test, `test_let_poly_multi_index_all_results_typed`, is added to
verify this behavior.
Introduce `StaticType::Forall` to represent universally quantified
types. This enables Hindley-Milner's let-polymorphism, allowing
functions to be generalized and reused with different concrete types.
- **Generalization at `def`:** Function values are now generalized using
`self.generalize` when they are defined, wrapping their type in
`Forall`. This occurs at `def` boundaries.
- **Instantiation at use:** Function types are instantiated with fresh
type variables at each call site using `self.instantiate`. This
ensures that different uses of the same polymorphic function do not
interfere with each other's type inference.
- **Value restriction:** Only function-typed definitions are
generalized. Mutable state like series and scalars remain monomorphic
to prevent unexpected behavior.
- **Type context awareness:** The `generalize` function considers the
current type context to avoid quantifying type variables that are
still in use elsewhere.
Feat: Add Forall type for polymorphism
Introduces the `Forall` type to support polymorphic functions and enable
let-polymorphism.
- `Forall(vars, body)`: Represents a universally quantified type where
`vars` are the type variables bound by this quantification, and `body`
is the type itself.
- `TypeChecker::generalize`: Wraps a type in `Forall` when a `def`
boundary is encountered for function-typed values. This ensures that
each use site of a polymorphic function gets its own instantiation.
- `TypeChecker::instantiate`: Replaces the type variables within a
`Forall` type with fresh ones. This is performed at each call site of
a polymorphic function.
- Updates `TypeChecker::unify` and `TypeChecker::apply_subst` to
correctly handle `Forall` types, ensuring that bound variables within
a `Forall` are not affected by global substitutions and that `Forall`
types are instantiated before unification.
- Adds a new example script `examples/Propa.myc` to demonstrate basic
usage.
- Includes a regression test
`test_let_poly_non_series_callable_no_false_positive` to ensure that
passing non-series callables to generic functions does not lead to
type errors.
- Introduces `TypeChecker::bind_var` to handle lazy propagation of
index-call constraints, crucial for correctly typing series lookups
like `(s 0)`.
This commit introduces a new test suite for HM Let-Polymorphism.
These tests verify that user-defined generic functions work correctly
across multiple series element types without type conflicts. This is
crucial for ensuring that the type inference system can handle
polymorphic functions properly, especially when they are applied to
different types. The tests cover scenarios like generic accessors,
runtime correctness with different series types, record series, and
higher-order functions. They also include a test for the value
restriction to ensure that series bindings are not generalized, which
would lead to incorrect type errors.