mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Include annotation type signatures in Expected
struct
To provide better error messages and suggestions related to changing type annotations, we now pass annotation type signatures all the way down through the constraint solver. At constraint generation we associate the type signature with a unique variable, and during error reporting, we pull out an `ErrorType` corresponding to the original type signature, by looking up the unique variable. This gives us two nice things: 1. It means we don't have to pass the original, AST-like type annotation, which can be quite large, to everyone who looks at an expectation. 2. It gives us a translation from a `Type` to an `ErrorType` for free using the existing translation procedure in `roc_types::subs`, without having to create a new translation function.
This commit is contained in:
parent
8726e38dad
commit
ee34e79790
11 changed files with 152 additions and 42 deletions
|
@ -93,7 +93,7 @@ pub fn constrain_expr(
|
|||
env: &Env,
|
||||
region: Region,
|
||||
expr: &Expr,
|
||||
expected: Expected<Type>,
|
||||
expected: Expected<Type, Variable>,
|
||||
) -> Constraint {
|
||||
match expr {
|
||||
Int(var, precision, _, _) => int_literal(*var, *precision, expected, region),
|
||||
|
@ -468,7 +468,7 @@ pub fn constrain_expr(
|
|||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(index),
|
||||
num_branches,
|
||||
region: ann_source.region(),
|
||||
annotation: *ann_source.annotation(),
|
||||
},
|
||||
tipe.clone(),
|
||||
),
|
||||
|
@ -488,7 +488,7 @@ pub fn constrain_expr(
|
|||
AnnotationSource::TypedIfBranch {
|
||||
index: Index::zero_based(branches.len()),
|
||||
num_branches,
|
||||
region: ann_source.region(),
|
||||
annotation: *ann_source.annotation(),
|
||||
},
|
||||
tipe.clone(),
|
||||
),
|
||||
|
@ -606,7 +606,7 @@ pub fn constrain_expr(
|
|||
*arity,
|
||||
TypedWhenBranch {
|
||||
index: Index::zero_based(index),
|
||||
region: ann_source.region(),
|
||||
annotation: *ann_source.annotation(),
|
||||
},
|
||||
typ.clone(),
|
||||
),
|
||||
|
@ -1021,7 +1021,7 @@ fn constrain_when_branch(
|
|||
region: Region,
|
||||
when_branch: &WhenBranch,
|
||||
pattern_expected: PExpected<Type>,
|
||||
expr_expected: Expected<Type>,
|
||||
expr_expected: Expected<Type, Variable>,
|
||||
) -> Constraint {
|
||||
let ret_constraint = constrain_expr(env, region, &when_branch.value.value, expr_expected);
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ fn constrain_field(env: &Env, field_var: Variable, loc_expr: &Located<Expr>) ->
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn constrain_empty_record(region: Region, expected: Expected<Type>) -> Constraint {
|
||||
fn constrain_empty_record(region: Region, expected: Expected<Type, Variable>) -> Constraint {
|
||||
Eq(EmptyRec, expected, Category::Record, region)
|
||||
}
|
||||
|
||||
|
@ -1182,15 +1182,15 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
rigids: ftv,
|
||||
};
|
||||
|
||||
let annotation_ty = Located::at(annotation.region, annotation.annotation_var);
|
||||
let annotation_expected = FromAnnotation(
|
||||
def.loc_pattern.clone(),
|
||||
arity,
|
||||
AnnotationSource::TypedBody {
|
||||
region: annotation.region,
|
||||
annotation: annotation_ty,
|
||||
},
|
||||
signature.clone(),
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(Eq(
|
||||
expr_type,
|
||||
annotation_expected.clone(),
|
||||
|
@ -1198,6 +1198,16 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
Region::span_across(&annotation.region, &def.loc_expr.region),
|
||||
));
|
||||
|
||||
// Associate the original annotation type itself with an annotation variable,
|
||||
// so we can get it back out later during error reporting if needed. This avoids
|
||||
// passing down the bulky annotation type to everyone who cares about it.
|
||||
def_pattern_state.constraints.push(Store(
|
||||
annotation.signature.clone(),
|
||||
annotation.annotation_var,
|
||||
std::file!(),
|
||||
std::line!(),
|
||||
));
|
||||
|
||||
// when a def is annotated, and it's body is a closure, treat this
|
||||
// as a named function (in elm terms) for error messages.
|
||||
//
|
||||
|
@ -1300,7 +1310,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
def.loc_pattern.clone(),
|
||||
arguments.len(),
|
||||
AnnotationSource::TypedBody {
|
||||
region: annotation.region,
|
||||
annotation: annotation_ty,
|
||||
},
|
||||
ret_type.clone(),
|
||||
);
|
||||
|
@ -1327,7 +1337,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
def.loc_pattern.clone(),
|
||||
arity,
|
||||
AnnotationSource::TypedBody {
|
||||
region: annotation.region,
|
||||
annotation: annotation_ty,
|
||||
},
|
||||
*signature_closure_type.clone(),
|
||||
),
|
||||
|
@ -1559,10 +1569,19 @@ pub fn rec_defs_help(
|
|||
def.loc_pattern.clone(),
|
||||
arity,
|
||||
AnnotationSource::TypedBody {
|
||||
region: annotation.region,
|
||||
annotation: Located::at(annotation.region, annotation.annotation_var),
|
||||
},
|
||||
signature.clone(),
|
||||
);
|
||||
// Associate the original annotation type itself with an annotation variable,
|
||||
// so we can get it back out later during error reporting if needed. This avoids
|
||||
// passing down the bulky annotation type to everyone who cares about it.
|
||||
let annotation_constr = Store(
|
||||
annotation.signature.clone(),
|
||||
annotation.annotation_var,
|
||||
std::file!(),
|
||||
std::line!(),
|
||||
);
|
||||
|
||||
// when a def is annotated, and it's body is a closure, treat this
|
||||
// as a named function (in elm terms) for error messages.
|
||||
|
@ -1695,6 +1714,7 @@ pub fn rec_defs_help(
|
|||
Store(signature, expr_var, std::file!(), std::line!()),
|
||||
Store(ret_type, ret_var, std::file!(), std::line!()),
|
||||
closure_constraint,
|
||||
annotation_constr,
|
||||
]),
|
||||
);
|
||||
|
||||
|
@ -1725,6 +1745,7 @@ pub fn rec_defs_help(
|
|||
})),
|
||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||
Store(signature, expr_var, std::file!(), std::line!()),
|
||||
annotation_constr,
|
||||
]);
|
||||
|
||||
rigid_info.vars.extend(&new_rigids);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue