mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-01 10:52:18 +00:00
Constrain with Types SoA, sans borrow checker
This commit is contained in:
parent
e3ef9828c7
commit
59d2de5a55
7 changed files with 710 additions and 328 deletions
|
@ -7,11 +7,12 @@ use roc_region::all::{Loc, Region};
|
|||
use roc_types::num::{NumericRange, SingleQuoteBound};
|
||||
use roc_types::subs::Variable;
|
||||
use roc_types::types::Type::{self, *};
|
||||
use roc_types::types::{AliasKind, Category};
|
||||
use roc_types::types::{AliasKind, Category, Types};
|
||||
use roc_types::types::{OptAbleType, Reason};
|
||||
|
||||
#[inline(always)]
|
||||
pub fn add_numeric_bound_constr(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
num_constraints: &mut impl Extend<Constraint>,
|
||||
num_var: Variable,
|
||||
|
@ -30,9 +31,9 @@ pub fn add_numeric_bound_constr(
|
|||
num_num(Variable(num_var))
|
||||
}
|
||||
NumericBound::FloatExact(width) => {
|
||||
let actual_type = constraints.push_type(Variable(float_width_to_variable(width)));
|
||||
let actual_type = constraints.push_variable(float_width_to_variable(width));
|
||||
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
||||
let type_index = constraints.push_type(Variable(num_var));
|
||||
let type_index = constraints.push_variable(num_var);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let because_suffix =
|
||||
constraints.equal_types(type_index, expected_index, category, region);
|
||||
|
@ -42,9 +43,9 @@ pub fn add_numeric_bound_constr(
|
|||
Variable(num_var)
|
||||
}
|
||||
NumericBound::IntExact(width) => {
|
||||
let actual_type = constraints.push_type(Variable(int_lit_width_to_variable(width)));
|
||||
let actual_type = constraints.push_variable(int_lit_width_to_variable(width));
|
||||
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
||||
let type_index = constraints.push_type(Variable(num_var));
|
||||
let type_index = constraints.push_variable(num_var);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let because_suffix =
|
||||
constraints.equal_types(type_index, expected_index, category, region);
|
||||
|
@ -54,8 +55,10 @@ pub fn add_numeric_bound_constr(
|
|||
Variable(num_var)
|
||||
}
|
||||
NumericBound::Range(range) => {
|
||||
let precision_type = constraints.push_type(Variable(precision_var));
|
||||
let expected = Expected::NoExpectation(constraints.push_type(RangedNumber(range)));
|
||||
let precision_type = constraints.push_variable(precision_var);
|
||||
let expected = Expected::NoExpectation(
|
||||
constraints.push_type(types, types.from_old_type(&RangedNumber(range))),
|
||||
);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let constr = constraints.equal_types(precision_type, expected_index, category, region);
|
||||
|
||||
|
@ -68,6 +71,7 @@ pub fn add_numeric_bound_constr(
|
|||
|
||||
#[inline(always)]
|
||||
pub fn int_literal(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
|
@ -80,6 +84,7 @@ pub fn int_literal(
|
|||
// Always add the bound first; this improves the resolved type quality in case it's an alias like "U8".
|
||||
let mut constrs = ArrayVec::<_, 3>::new();
|
||||
let num_type = add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut constrs,
|
||||
num_var,
|
||||
|
@ -89,8 +94,11 @@ pub fn int_literal(
|
|||
Category::Num,
|
||||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
|
||||
let num_type_index = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
let int_precision_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&num_int(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
|
||||
|
@ -106,6 +114,7 @@ pub fn int_literal(
|
|||
}
|
||||
|
||||
pub fn single_quote_literal(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
|
@ -118,6 +127,7 @@ pub fn single_quote_literal(
|
|||
// Always add the bound first; this improves the resolved type quality in case it's an alias like "U8".
|
||||
let mut constrs = ArrayVec::<_, 3>::new();
|
||||
let num_type = add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut constrs,
|
||||
num_var,
|
||||
|
@ -127,8 +137,11 @@ pub fn single_quote_literal(
|
|||
Category::Character,
|
||||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
|
||||
let num_type_index = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
let int_precision_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&num_int(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
|
||||
|
@ -149,6 +162,7 @@ pub fn single_quote_literal(
|
|||
|
||||
#[inline(always)]
|
||||
pub fn float_literal(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
|
@ -160,6 +174,7 @@ pub fn float_literal(
|
|||
|
||||
let mut constrs = ArrayVec::<_, 3>::new();
|
||||
let num_type = add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut constrs,
|
||||
num_var,
|
||||
|
@ -169,8 +184,11 @@ pub fn float_literal(
|
|||
Category::Frac,
|
||||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let float_precision_type = constraints.push_type(num_float(Type::Variable(precision_var)));
|
||||
let num_type_index = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
let float_precision_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&num_float(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, float_precision_type, region));
|
||||
|
@ -186,6 +204,7 @@ pub fn float_literal(
|
|||
|
||||
#[inline(always)]
|
||||
pub fn num_literal(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
expected: ExpectedTypeIndex,
|
||||
|
@ -194,6 +213,7 @@ pub fn num_literal(
|
|||
) -> Constraint {
|
||||
let mut constrs = ArrayVec::<_, 2>::new();
|
||||
let num_type = add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut constrs,
|
||||
num_var,
|
||||
|
@ -203,7 +223,7 @@ pub fn num_literal(
|
|||
Category::Num,
|
||||
);
|
||||
|
||||
let type_index = constraints.push_type(num_type);
|
||||
let type_index = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
constrs.extend([constraints.equal_types(type_index, expected, Category::Num, region)]);
|
||||
|
||||
let and_constraint = constraints.and_constraint(constrs);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,19 +6,26 @@ use roc_can::expr::Declarations;
|
|||
use roc_can::pattern::Pattern;
|
||||
use roc_module::symbol::{ModuleId, Symbol};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_types::types::{AnnotationSource, Category, Type};
|
||||
use roc_types::types::{AnnotationSource, Category, Type, Types};
|
||||
|
||||
pub fn constrain_module(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
||||
abilities_store: &PendingAbilitiesStore,
|
||||
declarations: &Declarations,
|
||||
home: ModuleId,
|
||||
) -> Constraint {
|
||||
let constraint = crate::expr::constrain_decls(constraints, home, declarations);
|
||||
let constraint = crate::expr::constrain_decls(types, constraints, home, declarations);
|
||||
let constraint = constrain_symbols_from_requires(
|
||||
types,
|
||||
constraints,
|
||||
symbols_from_requires,
|
||||
home,
|
||||
constraint,
|
||||
);
|
||||
let constraint =
|
||||
constrain_symbols_from_requires(constraints, symbols_from_requires, home, constraint);
|
||||
let constraint = frontload_ability_constraints(constraints, abilities_store, home, constraint);
|
||||
frontload_ability_constraints(types, constraints, abilities_store, home, constraint);
|
||||
|
||||
// The module constraint should always save the environment at the end.
|
||||
debug_assert!(constraints.contains_save_the_environment(&constraint));
|
||||
|
@ -27,6 +34,7 @@ pub fn constrain_module(
|
|||
}
|
||||
|
||||
fn constrain_symbols_from_requires(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
symbols_from_requires: Vec<(Loc<Symbol>, Loc<Type>)>,
|
||||
home: ModuleId,
|
||||
|
@ -50,9 +58,9 @@ fn constrain_symbols_from_requires(
|
|||
};
|
||||
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(loc_symbol.value));
|
||||
|
||||
let type_index = constraints.push_type(loc_type.value);
|
||||
let type_index = constraints.push_type(types, types.from_old_type(&loc_type.value));
|
||||
let def_pattern_state =
|
||||
constrain_def_pattern(constraints, &mut env, &pattern, type_index);
|
||||
constrain_def_pattern(types, constraints, &mut env, &pattern, type_index);
|
||||
|
||||
debug_assert!(env.resolutions_to_make.is_empty());
|
||||
|
||||
|
@ -71,7 +79,7 @@ fn constrain_symbols_from_requires(
|
|||
// provided by the app is in fact what the package module requires.
|
||||
let arity = loc_type.value.arity();
|
||||
let typ = loc_type.value;
|
||||
let type_index = constraints.push_type(typ);
|
||||
let type_index = constraints.push_type(types, types.from_old_type(&typ));
|
||||
let expected = constraints.push_expected_type(Expected::FromAnnotation(
|
||||
loc_symbol.map(|&s| Pattern::Identifier(s)),
|
||||
arity,
|
||||
|
@ -88,6 +96,7 @@ fn constrain_symbols_from_requires(
|
|||
}
|
||||
|
||||
pub fn frontload_ability_constraints(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
abilities_store: &PendingAbilitiesStore,
|
||||
home: ModuleId,
|
||||
|
@ -109,10 +118,11 @@ pub fn frontload_ability_constraints(
|
|||
};
|
||||
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(*member_name));
|
||||
|
||||
let signature_index = constraints.push_type(signature.clone());
|
||||
let signature_index =
|
||||
constraints.push_type(types, types.from_old_type(&signature.clone()));
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, &mut env, &pattern, signature_index);
|
||||
constrain_def_pattern(types, constraints, &mut env, &pattern, signature_index);
|
||||
|
||||
debug_assert!(env.resolutions_to_make.is_empty());
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use roc_region::all::{Loc, Region};
|
|||
use roc_types::subs::Variable;
|
||||
use roc_types::types::{
|
||||
AliasKind, Category, OptAbleType, PReason, PatternCategory, Reason, RecordField, Type,
|
||||
TypeExtension,
|
||||
TypeExtension, TypeTag, Types,
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
|
@ -31,6 +31,7 @@ pub struct PatternState {
|
|||
/// Would add `x => <42>` to the headers (i.e., symbol points to a type variable). If the
|
||||
/// definition has an annotation, we instead now add `x => Int`.
|
||||
pub fn headers_from_annotation(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
pattern: &Pattern,
|
||||
annotation: &Loc<&Type>,
|
||||
|
@ -40,7 +41,7 @@ pub fn headers_from_annotation(
|
|||
// in such incorrect cases we don't put the full annotation in headers, just a variable, and let
|
||||
// inference generate a proper error.
|
||||
let is_structurally_valid =
|
||||
headers_from_annotation_help(constraints, pattern, annotation, &mut headers);
|
||||
headers_from_annotation_help(types, constraints, pattern, annotation, &mut headers);
|
||||
|
||||
if is_structurally_valid {
|
||||
Some(headers)
|
||||
|
@ -50,6 +51,7 @@ pub fn headers_from_annotation(
|
|||
}
|
||||
|
||||
fn headers_from_annotation_help(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
pattern: &Pattern,
|
||||
annotation: &Loc<&Type>,
|
||||
|
@ -63,7 +65,7 @@ fn headers_from_annotation_help(
|
|||
ident: symbol,
|
||||
specializes: _,
|
||||
} => {
|
||||
let annotation_index = constraints.push_type(annotation.value.clone());
|
||||
let annotation_index = constraints.push_type(types, types.from_old_type(&annotation.value));
|
||||
let typ = Loc::at(annotation.region, annotation_index);
|
||||
headers.insert(*symbol, typ);
|
||||
true
|
||||
|
@ -91,7 +93,7 @@ fn headers_from_annotation_help(
|
|||
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
|
||||
// the type of `x` within the binding itself is the same.
|
||||
if let Some(field_type) = fields.get(&destruct.label) {
|
||||
let field_type_index = constraints.push_type(field_type.as_inner().clone());
|
||||
let field_type_index = constraints.push_type(types, types.from_old_type(&field_type.as_inner().clone()));
|
||||
headers.insert(
|
||||
destruct.symbol,
|
||||
Loc::at(annotation.region, field_type_index),
|
||||
|
@ -130,6 +132,7 @@ fn headers_from_annotation_help(
|
|||
.zip(arg_types.iter())
|
||||
.all(|(arg_pattern, arg_type)| {
|
||||
headers_from_annotation_help(
|
||||
types,
|
||||
constraints,
|
||||
&arg_pattern.1.value,
|
||||
&Loc::at(annotation.region, arg_type),
|
||||
|
@ -162,13 +165,14 @@ fn headers_from_annotation_help(
|
|||
&& type_arguments.len() == pat_type_arguments.len()
|
||||
&& lambda_set_variables.len() == pat_lambda_set_variables.len() =>
|
||||
{
|
||||
let annotation_index = constraints.push_type(annotation.value.clone());
|
||||
let annotation_index = constraints.push_type(types, types.from_old_type( &annotation.value ));
|
||||
let typ = Loc::at(annotation.region, annotation_index);
|
||||
headers.insert(*opaque, typ);
|
||||
|
||||
let (_, argument_pat) = &**argument;
|
||||
headers_from_annotation_help(
|
||||
constraints,
|
||||
types,
|
||||
constraints,
|
||||
&argument_pat.value,
|
||||
&Loc::at(annotation.region, actual),
|
||||
headers,
|
||||
|
@ -183,6 +187,7 @@ fn headers_from_annotation_help(
|
|||
/// initialize the Vecs in PatternState using with_capacity
|
||||
/// based on its knowledge of their lengths.
|
||||
pub fn constrain_pattern(
|
||||
types: &mut Types,
|
||||
constraints: &mut Constraints,
|
||||
env: &mut Env,
|
||||
pattern: &Pattern,
|
||||
|
@ -199,7 +204,7 @@ pub fn constrain_pattern(
|
|||
// _ -> ""
|
||||
// so, we know that "x" (in this case, a tag union) must be open.
|
||||
let expected_type = *constraints[expected].get_type_ref();
|
||||
if could_be_a_tag_union(constraints, expected_type) {
|
||||
if could_be_a_tag_union(types, constraints, expected_type) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(expected_type));
|
||||
|
@ -213,7 +218,7 @@ pub fn constrain_pattern(
|
|||
let expected = &constraints[expected];
|
||||
let type_index = *expected.get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(constraints, type_index) {
|
||||
if could_be_a_tag_union(types, constraints, type_index) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(type_index));
|
||||
|
@ -235,7 +240,7 @@ pub fn constrain_pattern(
|
|||
let expected = &constraints[expected];
|
||||
let type_index = *expected.get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(constraints, type_index) {
|
||||
if could_be_a_tag_union(types, constraints, type_index) {
|
||||
state.constraints.push(constraints.is_open_type(type_index));
|
||||
}
|
||||
|
||||
|
@ -252,6 +257,7 @@ pub fn constrain_pattern(
|
|||
state.vars.push(precision_var);
|
||||
|
||||
let num_type = builtins::add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut state.constraints,
|
||||
precision_var,
|
||||
|
@ -260,7 +266,7 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
Category::Num,
|
||||
);
|
||||
let num_type = constraints.push_type(num_type);
|
||||
let num_type = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
|
||||
state.constraints.push(constraints.equal_pattern_types(
|
||||
num_type,
|
||||
|
@ -274,6 +280,7 @@ pub fn constrain_pattern(
|
|||
// First constraint on the free num var; this improves the resolved type quality in
|
||||
// case the bound is an alias.
|
||||
let num_type = builtins::add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut state.constraints,
|
||||
num_precision_var,
|
||||
|
@ -282,10 +289,13 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
Category::Int,
|
||||
);
|
||||
let num_type = constraints.push_type(num_type);
|
||||
let num_type = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
|
||||
let int_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&builtins::num_int(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
|
@ -306,6 +316,7 @@ pub fn constrain_pattern(
|
|||
// First constraint on the free num var; this improves the resolved type quality in
|
||||
// case the bound is an alias.
|
||||
let num_type = builtins::add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut state.constraints,
|
||||
num_precision_var,
|
||||
|
@ -314,11 +325,13 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
Category::Frac,
|
||||
);
|
||||
let num_type_index = constraints.push_type(num_type); // TODO check me if something breaks!
|
||||
let num_type_index = constraints.push_type(types, types.from_old_type(&num_type)); // NOTE: check me if something breaks!
|
||||
|
||||
// Link the free num var with the float var and our expectation.
|
||||
let float_type =
|
||||
constraints.push_type(builtins::num_float(Type::Variable(precision_var)));
|
||||
let float_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&builtins::num_float(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
|
@ -336,7 +349,8 @@ pub fn constrain_pattern(
|
|||
}
|
||||
|
||||
StrLiteral(_) => {
|
||||
let str_type = constraints.push_type(builtins::str_type());
|
||||
// TODO(types-soa) use Types::STR
|
||||
let str_type = constraints.push_type(types, types.from_old_type(&builtins::str_type()));
|
||||
state.constraints.push(constraints.equal_pattern_types(
|
||||
str_type,
|
||||
expected,
|
||||
|
@ -349,6 +363,7 @@ pub fn constrain_pattern(
|
|||
// First constraint on the free num var; this improves the resolved type quality in
|
||||
// case the bound is an alias.
|
||||
let num_type = builtins::add_numeric_bound_constr(
|
||||
types,
|
||||
constraints,
|
||||
&mut state.constraints,
|
||||
num_var,
|
||||
|
@ -358,10 +373,13 @@ pub fn constrain_pattern(
|
|||
Category::Int,
|
||||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let num_type_index = constraints.push_type(types, types.from_old_type(&num_type));
|
||||
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
|
||||
let int_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&builtins::num_int(Type::Variable(precision_var))),
|
||||
);
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
|
@ -406,7 +424,9 @@ pub fn constrain_pattern(
|
|||
} in destructs
|
||||
{
|
||||
let pat_type = Type::Variable(*var);
|
||||
let pat_type_index = constraints.push_type(pat_type.clone());
|
||||
let pat_type_index =
|
||||
// TODO(types-soa) use variable here instead
|
||||
constraints.push_type(types, types.from_old_type(&pat_type.clone()));
|
||||
let expected =
|
||||
constraints.push_pat_expected_type(PExpected::NoExpectation(pat_type_index));
|
||||
|
||||
|
@ -418,7 +438,7 @@ pub fn constrain_pattern(
|
|||
|
||||
let field_type = match typ {
|
||||
DestructType::Guard(guard_var, loc_guard) => {
|
||||
let guard_type = constraints.push_type(Type::Variable(*guard_var));
|
||||
let guard_type = constraints.push_variable(*guard_var);
|
||||
let expected_pat =
|
||||
constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::PatternGuard,
|
||||
|
@ -435,6 +455,7 @@ pub fn constrain_pattern(
|
|||
state.vars.push(*guard_var);
|
||||
|
||||
constrain_pattern(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
&loc_guard.value,
|
||||
|
@ -446,7 +467,7 @@ pub fn constrain_pattern(
|
|||
RecordField::Demanded(pat_type)
|
||||
}
|
||||
DestructType::Optional(expr_var, loc_expr) => {
|
||||
let expr_type = constraints.push_type(Type::Variable(*expr_var));
|
||||
let expr_type = constraints.push_variable(*expr_var);
|
||||
let expected_pat =
|
||||
constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::OptionalField,
|
||||
|
@ -470,6 +491,7 @@ pub fn constrain_pattern(
|
|||
));
|
||||
|
||||
let expr_con = constrain_expr(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
loc_expr.region,
|
||||
|
@ -491,12 +513,15 @@ pub fn constrain_pattern(
|
|||
state.vars.push(*var);
|
||||
}
|
||||
|
||||
let record_type = constraints.push_type(Type::Record(
|
||||
field_types,
|
||||
TypeExtension::from_type(ext_type),
|
||||
));
|
||||
let record_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&Type::Record(
|
||||
field_types,
|
||||
TypeExtension::from_type(ext_type),
|
||||
)),
|
||||
);
|
||||
|
||||
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
|
||||
let whole_var_index = constraints.push_variable(*whole_var);
|
||||
let expected_record =
|
||||
constraints.push_expected_type(Expected::NoExpectation(record_type));
|
||||
let whole_con = constraints.equal_types(
|
||||
|
@ -526,7 +551,7 @@ pub fn constrain_pattern(
|
|||
opt_rest: _,
|
||||
},
|
||||
} => {
|
||||
let elem_var_index = constraints.push_type(Type::Variable(*elem_var));
|
||||
let elem_var_index = constraints.push_variable(*elem_var);
|
||||
|
||||
for loc_pat in patterns.iter() {
|
||||
let expected = constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
|
@ -536,6 +561,7 @@ pub fn constrain_pattern(
|
|||
));
|
||||
|
||||
constrain_pattern(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
&loc_pat.value,
|
||||
|
@ -545,12 +571,15 @@ pub fn constrain_pattern(
|
|||
);
|
||||
}
|
||||
|
||||
let list_var_index = constraints.push_type(Type::Variable(*list_var));
|
||||
let solved_list = constraints.push_type(Type::Apply(
|
||||
Symbol::LIST_LIST,
|
||||
vec![Loc::at(region, Type::Variable(*elem_var))],
|
||||
region,
|
||||
));
|
||||
let list_var_index = constraints.push_variable(*list_var);
|
||||
let solved_list = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&Type::Apply(
|
||||
Symbol::LIST_LIST,
|
||||
vec![Loc::at(region, Type::Variable(*elem_var))],
|
||||
region,
|
||||
)),
|
||||
);
|
||||
let store_solved_list = constraints.store(solved_list, *list_var, file!(), line!());
|
||||
|
||||
let expected_constraint = constraints.pattern_presence(
|
||||
|
@ -577,7 +606,7 @@ pub fn constrain_pattern(
|
|||
for (index, (pattern_var, loc_pattern)) in arguments.iter().enumerate() {
|
||||
state.vars.push(*pattern_var);
|
||||
|
||||
let pattern_type = constraints.push_type(Type::Variable(*pattern_var));
|
||||
let pattern_type = constraints.push_variable(*pattern_var);
|
||||
|
||||
let expected = constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::TagArg {
|
||||
|
@ -588,6 +617,7 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
));
|
||||
constrain_pattern(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
|
@ -608,7 +638,7 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
);
|
||||
|
||||
let whole_type = constraints.push_type(Type::Variable(*whole_var));
|
||||
let whole_type = constraints.push_variable(*whole_var);
|
||||
|
||||
let tag_con = constraints.pattern_presence(whole_type, expected, pat_category, region);
|
||||
|
||||
|
@ -629,27 +659,31 @@ pub fn constrain_pattern(
|
|||
// Suppose we are constraining the pattern \@Id who, where Id n := [Id U64 n]
|
||||
let (arg_pattern_var, loc_arg_pattern) = &**argument;
|
||||
let arg_pattern_type = Type::Variable(*arg_pattern_var);
|
||||
let arg_pattern_type_index = constraints.push_type(Type::Variable(*arg_pattern_var));
|
||||
let arg_pattern_type_index = constraints.push_variable(*arg_pattern_var);
|
||||
|
||||
let opaque_type = constraints.push_type(Type::Alias {
|
||||
symbol: *opaque,
|
||||
type_arguments: type_arguments
|
||||
.iter()
|
||||
.map(|v| OptAbleType {
|
||||
typ: Type::Variable(v.var),
|
||||
opt_abilities: v.opt_abilities.clone(),
|
||||
})
|
||||
.collect(),
|
||||
lambda_set_variables: lambda_set_variables.clone(),
|
||||
infer_ext_in_output_types: vec![],
|
||||
actual: Box::new(arg_pattern_type.clone()),
|
||||
kind: AliasKind::Opaque,
|
||||
});
|
||||
let opaque_type = constraints.push_type(
|
||||
types,
|
||||
types.from_old_type(&Type::Alias {
|
||||
symbol: *opaque,
|
||||
type_arguments: type_arguments
|
||||
.iter()
|
||||
.map(|v| OptAbleType {
|
||||
typ: Type::Variable(v.var),
|
||||
opt_abilities: v.opt_abilities.clone(),
|
||||
})
|
||||
.collect(),
|
||||
lambda_set_variables: lambda_set_variables.clone(),
|
||||
infer_ext_in_output_types: vec![],
|
||||
actual: Box::new(arg_pattern_type.clone()),
|
||||
kind: AliasKind::Opaque,
|
||||
}),
|
||||
);
|
||||
|
||||
// First, add a constraint for the argument "who"
|
||||
let arg_pattern_expected = constraints
|
||||
.push_pat_expected_type(PExpected::NoExpectation(arg_pattern_type_index));
|
||||
constrain_pattern(
|
||||
types,
|
||||
constraints,
|
||||
env,
|
||||
&loc_arg_pattern.value,
|
||||
|
@ -659,7 +693,7 @@ pub fn constrain_pattern(
|
|||
);
|
||||
|
||||
// Next, link `whole_var` to the opaque type of "@Id who"
|
||||
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
|
||||
let whole_var_index = constraints.push_variable(*whole_var);
|
||||
let expected_opaque =
|
||||
constraints.push_expected_type(Expected::NoExpectation(opaque_type));
|
||||
let whole_con = constraints.equal_types(
|
||||
|
@ -682,8 +716,13 @@ pub fn constrain_pattern(
|
|||
// This must **always** be a presence constraint, that is enforcing
|
||||
// `[A k1, B k1] += typeof (A s)`, because we are in a destructure position and not
|
||||
// all constructors are covered in this branch!
|
||||
let arg_pattern_type = constraints.push_type(arg_pattern_type);
|
||||
let specialized_type_index = constraints.push_type((**specialized_def_type).clone());
|
||||
let arg_pattern_type = constraints.push_type(
|
||||
types,
|
||||
// TODO(types-soa) this is just a variable
|
||||
types.from_old_type(&arg_pattern_type),
|
||||
);
|
||||
let specialized_type_index =
|
||||
constraints.push_type(types, types.from_old_type(&(**specialized_def_type)));
|
||||
let specialized_type_expected = constraints
|
||||
.push_pat_expected_type(PExpected::NoExpectation(specialized_type_index));
|
||||
|
||||
|
@ -695,7 +734,7 @@ pub fn constrain_pattern(
|
|||
);
|
||||
|
||||
// Next, link `whole_var` (the type of "@Id who") to the expected type
|
||||
let whole_type = constraints.push_type(Type::Variable(*whole_var));
|
||||
let whole_type = constraints.push_variable(*whole_var);
|
||||
let opaque_pattern_con = constraints.pattern_presence(
|
||||
whole_type,
|
||||
expected,
|
||||
|
@ -721,13 +760,13 @@ pub fn constrain_pattern(
|
|||
}
|
||||
}
|
||||
|
||||
fn could_be_a_tag_union(constraints: &mut Constraints, typ: TypeOrVar) -> bool {
|
||||
fn could_be_a_tag_union(types: &Types, constraints: &mut Constraints, typ: TypeOrVar) -> bool {
|
||||
match typ.split() {
|
||||
Ok(typ_index) => {
|
||||
let typ_cell = &mut constraints.types[typ_index.index()];
|
||||
!matches!(
|
||||
typ_cell.get_mut(),
|
||||
Type::Apply(..) | Type::Function(..) | Type::Record(..)
|
||||
types[*typ_cell.get_mut()],
|
||||
TypeTag::Apply { .. } | TypeTag::Function(..) | TypeTag::Record(..)
|
||||
)
|
||||
}
|
||||
Err(_) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue