mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
Revert "Include annotation type signatures in Expected
struct"
This reverts commit 6e4fd5f06a1ae6138659b0073b4e2b375a499588. This idea didn't work out because cloning the type and storing it on a variable still resulted in the solver trying to uify the variable with the type. When there were errors, which there certainly would be if we tried to unify the variable with a structure that had nested flex/rigid vars, the nested flex/rigid vars would inherit those errors, and the program wouldn't typecheck. Since the motivation here was to expose the signature type to `reporting` so that we could modify it with suggestions, we should instead pass that information along in something analogous to the `Expected` struct.
This commit is contained in:
parent
a8e38172ac
commit
d352d2cdf8
16 changed files with 64 additions and 204 deletions
|
@ -6,7 +6,7 @@ use roc_module::{
|
||||||
ident::{Lowercase, TagName},
|
ident::{Lowercase, TagName},
|
||||||
symbol::Symbol,
|
symbol::Symbol,
|
||||||
};
|
};
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::Region;
|
||||||
use roc_types::{
|
use roc_types::{
|
||||||
subs::Variable,
|
subs::Variable,
|
||||||
types::{self, AnnotationSource, PReason, PatternCategory},
|
types::{self, AnnotationSource, PReason, PatternCategory},
|
||||||
|
@ -32,9 +32,9 @@ use crate::{
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Constraint<'a> {
|
pub enum Constraint<'a> {
|
||||||
Eq(Type2, Expected<Type2, Variable>, Category, Region),
|
Eq(Type2, Expected<Type2>, Category, Region),
|
||||||
// Store(Type, Variable, &'static str, u32),
|
// Store(Type, Variable, &'static str, u32),
|
||||||
Lookup(Symbol, Expected<Type2, Variable>, Region),
|
Lookup(Symbol, Expected<Type2>, Region),
|
||||||
Pattern(Region, PatternCategory, Type2, PExpected<Type2>),
|
Pattern(Region, PatternCategory, Type2, PExpected<Type2>),
|
||||||
And(BumpVec<'a, Constraint<'a>>),
|
And(BumpVec<'a, Constraint<'a>>),
|
||||||
Let(&'a LetConstraint<'a>),
|
Let(&'a LetConstraint<'a>),
|
||||||
|
@ -55,7 +55,7 @@ pub fn constrain_expr<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
env: &mut Env,
|
env: &mut Env,
|
||||||
expr: &Expr2,
|
expr: &Expr2,
|
||||||
expected: Expected<Type2, Variable>,
|
expected: Expected<Type2>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint<'a> {
|
) -> Constraint<'a> {
|
||||||
use Constraint::*;
|
use Constraint::*;
|
||||||
|
@ -528,10 +528,7 @@ pub fn constrain_expr<'a>(
|
||||||
AnnotationSource::TypedIfBranch {
|
AnnotationSource::TypedIfBranch {
|
||||||
index: Index::zero_based(index),
|
index: Index::zero_based(index),
|
||||||
num_branches,
|
num_branches,
|
||||||
annotation: Located::at(
|
region: ann_source.region(),
|
||||||
ann_source.region(),
|
|
||||||
ann_source.annotation().value,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
tipe.shallow_clone(),
|
tipe.shallow_clone(),
|
||||||
),
|
),
|
||||||
|
@ -552,10 +549,7 @@ pub fn constrain_expr<'a>(
|
||||||
AnnotationSource::TypedIfBranch {
|
AnnotationSource::TypedIfBranch {
|
||||||
index: Index::zero_based(branches.len()),
|
index: Index::zero_based(branches.len()),
|
||||||
num_branches,
|
num_branches,
|
||||||
annotation: Located::at(
|
region: ann_source.region(),
|
||||||
ann_source.region(),
|
|
||||||
ann_source.annotation().value,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
tipe.shallow_clone(),
|
tipe.shallow_clone(),
|
||||||
),
|
),
|
||||||
|
@ -695,10 +689,7 @@ pub fn constrain_expr<'a>(
|
||||||
*arity,
|
*arity,
|
||||||
AnnotationSource::TypedWhenBranch {
|
AnnotationSource::TypedWhenBranch {
|
||||||
index: Index::zero_based(index),
|
index: Index::zero_based(index),
|
||||||
annotation: Located::at(
|
region: ann_source.region(),
|
||||||
ann_source.region(),
|
|
||||||
ann_source.annotation().value,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
typ.shallow_clone(),
|
typ.shallow_clone(),
|
||||||
),
|
),
|
||||||
|
@ -1185,7 +1176,7 @@ fn exists<'a>(
|
||||||
fn constrain_tag<'a>(
|
fn constrain_tag<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
env: &mut Env,
|
env: &mut Env,
|
||||||
expected: Expected<Type2, Variable>,
|
expected: Expected<Type2>,
|
||||||
region: Region,
|
region: Region,
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
arguments: &PoolVec<(Variable, ExprId)>,
|
arguments: &PoolVec<(Variable, ExprId)>,
|
||||||
|
@ -1275,10 +1266,7 @@ fn constrain_field_update<'a>(
|
||||||
(field_type, con)
|
(field_type, con)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constrain_empty_record<'a>(
|
fn constrain_empty_record<'a>(expected: Expected<Type2>, region: Region) -> Constraint<'a> {
|
||||||
expected: Expected<Type2, Variable>,
|
|
||||||
region: Region,
|
|
||||||
) -> Constraint<'a> {
|
|
||||||
Constraint::Eq(Type2::EmptyRec, expected, Category::Record, region)
|
Constraint::Eq(Type2::EmptyRec, expected, Category::Record, region)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,7 +1277,7 @@ fn constrain_when_branch<'a>(
|
||||||
region: Region,
|
region: Region,
|
||||||
when_branch: &WhenBranch,
|
when_branch: &WhenBranch,
|
||||||
pattern_expected: PExpected<Type2>,
|
pattern_expected: PExpected<Type2>,
|
||||||
expr_expected: Expected<Type2, Variable>,
|
expr_expected: Expected<Type2>,
|
||||||
) -> Constraint<'a> {
|
) -> Constraint<'a> {
|
||||||
let when_expr = env.pool.get(when_branch.body);
|
let when_expr = env.pool.get(when_branch.body);
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,9 @@ pub trait ShallowClone {
|
||||||
fn shallow_clone(&self) -> Self;
|
fn shallow_clone(&self) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Annot> ShallowClone for Expected<T, Annot>
|
impl<T> ShallowClone for Expected<T>
|
||||||
where
|
where
|
||||||
T: ShallowClone,
|
T: ShallowClone,
|
||||||
Annot: Clone,
|
|
||||||
{
|
{
|
||||||
fn shallow_clone(&self) -> Self {
|
fn shallow_clone(&self) -> Self {
|
||||||
use Expected::*;
|
use Expected::*;
|
||||||
|
@ -18,7 +17,7 @@ where
|
||||||
NoExpectation(t) => NoExpectation(t.shallow_clone()),
|
NoExpectation(t) => NoExpectation(t.shallow_clone()),
|
||||||
ForReason(reason, t, region) => ForReason(reason.clone(), t.shallow_clone(), *region),
|
ForReason(reason, t, region) => ForReason(reason.clone(), t.shallow_clone(), *region),
|
||||||
FromAnnotation(loc_pat, n, source, t) => {
|
FromAnnotation(loc_pat, n, source, t) => {
|
||||||
FromAnnotation(loc_pat.clone(), *n, source.clone(), t.shallow_clone())
|
FromAnnotation(loc_pat.clone(), *n, *source, t.shallow_clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ use crate::mem_pool::shallow_clone::ShallowClone;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum TypeError {
|
pub enum TypeError {
|
||||||
BadExpr(Region, Category, ErrorType, Expected<ErrorType, Variable>),
|
BadExpr(Region, Category, ErrorType, Expected<ErrorType>),
|
||||||
BadPattern(Region, PatternCategory, ErrorType, PExpected<ErrorType>),
|
BadPattern(Region, PatternCategory, ErrorType, PExpected<ErrorType>),
|
||||||
CircularType(Region, Symbol, ErrorType),
|
CircularType(Region, Symbol, ErrorType),
|
||||||
BadType(roc_types::types::Problem),
|
BadType(roc_types::types::Problem),
|
||||||
|
|
|
@ -1204,7 +1204,6 @@ fn num_max_i128(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
let annotation = crate::def::Annotation {
|
let annotation = crate::def::Annotation {
|
||||||
signature,
|
signature,
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
introduced_variables: Default::default(),
|
introduced_variables: Default::default(),
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
aliases: Default::default(),
|
aliases: Default::default(),
|
||||||
|
|
|
@ -7,9 +7,9 @@ use roc_types::{subs::Variable, types::VariableDetail};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Constraint {
|
pub enum Constraint {
|
||||||
Eq(Type, Expected<Type, Variable>, Category, Region),
|
Eq(Type, Expected<Type>, Category, Region),
|
||||||
Store(Type, Variable, &'static str, u32),
|
Store(Type, Variable, &'static str, u32),
|
||||||
Lookup(Symbol, Expected<Type, Variable>, Region),
|
Lookup(Symbol, Expected<Type>, Region),
|
||||||
Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
||||||
True, // Used for things that always unify, e.g. blanks and runtime errors
|
True, // Used for things that always unify, e.g. blanks and runtime errors
|
||||||
SaveTheEnvironment,
|
SaveTheEnvironment,
|
||||||
|
|
|
@ -35,7 +35,6 @@ pub struct Def {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Annotation {
|
pub struct Annotation {
|
||||||
pub signature: Type,
|
pub signature: Type,
|
||||||
pub annotation_var: Variable,
|
|
||||||
pub introduced_variables: IntroducedVariables,
|
pub introduced_variables: IntroducedVariables,
|
||||||
pub aliases: SendMap<Symbol, Alias>,
|
pub aliases: SendMap<Symbol, Alias>,
|
||||||
pub region: Region,
|
pub region: Region,
|
||||||
|
@ -876,7 +875,6 @@ fn canonicalize_pending_def<'a>(
|
||||||
pattern_vars: vars_by_symbol.clone(),
|
pattern_vars: vars_by_symbol.clone(),
|
||||||
annotation: Some(Annotation {
|
annotation: Some(Annotation {
|
||||||
signature: typ.clone(),
|
signature: typ.clone(),
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
introduced_variables: output.introduced_variables.clone(),
|
introduced_variables: output.introduced_variables.clone(),
|
||||||
aliases: ann.aliases.clone(),
|
aliases: ann.aliases.clone(),
|
||||||
region: loc_ann.region,
|
region: loc_ann.region,
|
||||||
|
@ -1098,7 +1096,6 @@ fn canonicalize_pending_def<'a>(
|
||||||
pattern_vars: vars_by_symbol.clone(),
|
pattern_vars: vars_by_symbol.clone(),
|
||||||
annotation: Some(Annotation {
|
annotation: Some(Annotation {
|
||||||
signature: typ.clone(),
|
signature: typ.clone(),
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
introduced_variables: output.introduced_variables.clone(),
|
introduced_variables: output.introduced_variables.clone(),
|
||||||
aliases: ann.aliases.clone(),
|
aliases: ann.aliases.clone(),
|
||||||
region: loc_ann.region,
|
region: loc_ann.region,
|
||||||
|
|
|
@ -3,9 +3,9 @@ use roc_region::all::{Located, Region};
|
||||||
use roc_types::types::{AnnotationSource, PReason, Reason};
|
use roc_types::types::{AnnotationSource, PReason, Reason};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Expected<T, Annot> {
|
pub enum Expected<T> {
|
||||||
NoExpectation(T),
|
NoExpectation(T),
|
||||||
FromAnnotation(Located<Pattern>, usize, AnnotationSource<Annot>, T),
|
FromAnnotation(Located<Pattern>, usize, AnnotationSource, T),
|
||||||
ForReason(Reason, T, Region),
|
ForReason(Reason, T, Region),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ impl<T> PExpected<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, Annot> Expected<T, Annot> {
|
impl<T> Expected<T> {
|
||||||
pub fn get_type(self) -> T {
|
pub fn get_type(self) -> T {
|
||||||
match self {
|
match self {
|
||||||
Expected::NoExpectation(val) => val,
|
Expected::NoExpectation(val) => val,
|
||||||
|
@ -73,12 +73,14 @@ impl<T, Annot> Expected<T, Annot> {
|
||||||
|
|
||||||
pub fn get_annotation_region(&self) -> Option<Region> {
|
pub fn get_annotation_region(&self) -> Option<Region> {
|
||||||
match self {
|
match self {
|
||||||
Expected::FromAnnotation(_, _, ann_source, _) => Some(ann_source.region()),
|
Expected::FromAnnotation(_, _, AnnotationSource::TypedBody { region }, _) => {
|
||||||
|
Some(*region)
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace<U>(self, new: U) -> Expected<U, Annot> {
|
pub fn replace<U>(self, new: U) -> Expected<U> {
|
||||||
match self {
|
match self {
|
||||||
Expected::NoExpectation(_val) => Expected::NoExpectation(new),
|
Expected::NoExpectation(_val) => Expected::NoExpectation(new),
|
||||||
Expected::ForReason(reason, _val, region) => Expected::ForReason(reason, new, region),
|
Expected::ForReason(reason, _val, region) => Expected::ForReason(reason, new, region),
|
||||||
|
@ -88,34 +90,15 @@ impl<T, Annot> Expected<T, Annot> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_ref<U>(&self, new: U) -> Expected<U, Annot>
|
pub fn replace_ref<U>(&self, new: U) -> Expected<U> {
|
||||||
where
|
|
||||||
Annot: Clone,
|
|
||||||
{
|
|
||||||
match self {
|
match self {
|
||||||
Expected::NoExpectation(_val) => Expected::NoExpectation(new),
|
Expected::NoExpectation(_val) => Expected::NoExpectation(new),
|
||||||
Expected::ForReason(reason, _val, region) => {
|
Expected::ForReason(reason, _val, region) => {
|
||||||
Expected::ForReason(reason.clone(), new, *region)
|
Expected::ForReason(reason.clone(), new, *region)
|
||||||
}
|
}
|
||||||
Expected::FromAnnotation(pattern, size, source, _val) => {
|
Expected::FromAnnotation(pattern, size, source, _val) => {
|
||||||
Expected::FromAnnotation(pattern.clone(), *size, source.clone(), new)
|
Expected::FromAnnotation(pattern.clone(), *size, *source, new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_annotation_with<Annot2, F>(self, create_new_annotation: F) -> Expected<T, Annot2>
|
|
||||||
where
|
|
||||||
F: FnOnce(Annot) -> Annot2,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
Expected::NoExpectation(val) => Expected::NoExpectation(val),
|
|
||||||
Expected::ForReason(reason, val, region) => Expected::ForReason(reason, val, region),
|
|
||||||
Expected::FromAnnotation(pattern, size, ann_source, val) => Expected::FromAnnotation(
|
|
||||||
pattern,
|
|
||||||
size,
|
|
||||||
ann_source.replace_with(create_new_annotation),
|
|
||||||
val,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use roc_types::types::Type::{self, *};
|
||||||
pub fn int_literal(
|
pub fn int_literal(
|
||||||
num_var: Variable,
|
num_var: Variable,
|
||||||
precision_var: Variable,
|
precision_var: Variable,
|
||||||
expected: Expected<Type, Variable>,
|
expected: Expected<Type>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
|
@ -38,7 +38,7 @@ pub fn int_literal(
|
||||||
pub fn float_literal(
|
pub fn float_literal(
|
||||||
num_var: Variable,
|
num_var: Variable,
|
||||||
precision_var: Variable,
|
precision_var: Variable,
|
||||||
expected: Expected<Type, Variable>,
|
expected: Expected<Type>,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let num_type = Variable(num_var);
|
let num_type = Variable(num_var);
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub fn constrain_expr(
|
||||||
env: &Env,
|
env: &Env,
|
||||||
region: Region,
|
region: Region,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
expected: Expected<Type, Variable>,
|
expected: Expected<Type>,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
match expr {
|
match expr {
|
||||||
Int(var, precision, _, _) => int_literal(*var, *precision, expected, region),
|
Int(var, precision, _, _) => int_literal(*var, *precision, expected, region),
|
||||||
|
@ -468,7 +468,7 @@ pub fn constrain_expr(
|
||||||
AnnotationSource::TypedIfBranch {
|
AnnotationSource::TypedIfBranch {
|
||||||
index: Index::zero_based(index),
|
index: Index::zero_based(index),
|
||||||
num_branches,
|
num_branches,
|
||||||
annotation: *ann_source.annotation(),
|
region: ann_source.region(),
|
||||||
},
|
},
|
||||||
tipe.clone(),
|
tipe.clone(),
|
||||||
),
|
),
|
||||||
|
@ -488,7 +488,7 @@ pub fn constrain_expr(
|
||||||
AnnotationSource::TypedIfBranch {
|
AnnotationSource::TypedIfBranch {
|
||||||
index: Index::zero_based(branches.len()),
|
index: Index::zero_based(branches.len()),
|
||||||
num_branches,
|
num_branches,
|
||||||
annotation: *ann_source.annotation(),
|
region: ann_source.region(),
|
||||||
},
|
},
|
||||||
tipe.clone(),
|
tipe.clone(),
|
||||||
),
|
),
|
||||||
|
@ -606,7 +606,7 @@ pub fn constrain_expr(
|
||||||
*arity,
|
*arity,
|
||||||
TypedWhenBranch {
|
TypedWhenBranch {
|
||||||
index: Index::zero_based(index),
|
index: Index::zero_based(index),
|
||||||
annotation: *ann_source.annotation(),
|
region: ann_source.region(),
|
||||||
},
|
},
|
||||||
typ.clone(),
|
typ.clone(),
|
||||||
),
|
),
|
||||||
|
@ -1021,7 +1021,7 @@ fn constrain_when_branch(
|
||||||
region: Region,
|
region: Region,
|
||||||
when_branch: &WhenBranch,
|
when_branch: &WhenBranch,
|
||||||
pattern_expected: PExpected<Type>,
|
pattern_expected: PExpected<Type>,
|
||||||
expr_expected: Expected<Type, Variable>,
|
expr_expected: Expected<Type>,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let ret_constraint = constrain_expr(env, region, &when_branch.value.value, expr_expected);
|
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)]
|
#[inline(always)]
|
||||||
fn constrain_empty_record(region: Region, expected: Expected<Type, Variable>) -> Constraint {
|
fn constrain_empty_record(region: Region, expected: Expected<Type>) -> Constraint {
|
||||||
Eq(EmptyRec, expected, Category::Record, region)
|
Eq(EmptyRec, expected, Category::Record, region)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,15 +1182,15 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
||||||
rigids: ftv,
|
rigids: ftv,
|
||||||
};
|
};
|
||||||
|
|
||||||
let annotation_ty = Located::at(annotation.region, annotation.annotation_var);
|
|
||||||
let annotation_expected = FromAnnotation(
|
let annotation_expected = FromAnnotation(
|
||||||
def.loc_pattern.clone(),
|
def.loc_pattern.clone(),
|
||||||
arity,
|
arity,
|
||||||
AnnotationSource::TypedBody {
|
AnnotationSource::TypedBody {
|
||||||
annotation: annotation_ty,
|
region: annotation.region,
|
||||||
},
|
},
|
||||||
signature.clone(),
|
signature.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
def_pattern_state.constraints.push(Eq(
|
def_pattern_state.constraints.push(Eq(
|
||||||
expr_type,
|
expr_type,
|
||||||
annotation_expected.clone(),
|
annotation_expected.clone(),
|
||||||
|
@ -1198,16 +1198,6 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
||||||
Region::span_across(&annotation.region, &def.loc_expr.region),
|
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
|
// when a def is annotated, and it's body is a closure, treat this
|
||||||
// as a named function (in elm terms) for error messages.
|
// as a named function (in elm terms) for error messages.
|
||||||
//
|
//
|
||||||
|
@ -1310,7 +1300,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
||||||
def.loc_pattern.clone(),
|
def.loc_pattern.clone(),
|
||||||
arguments.len(),
|
arguments.len(),
|
||||||
AnnotationSource::TypedBody {
|
AnnotationSource::TypedBody {
|
||||||
annotation: annotation_ty,
|
region: annotation.region,
|
||||||
},
|
},
|
||||||
ret_type.clone(),
|
ret_type.clone(),
|
||||||
);
|
);
|
||||||
|
@ -1337,7 +1327,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
||||||
def.loc_pattern.clone(),
|
def.loc_pattern.clone(),
|
||||||
arity,
|
arity,
|
||||||
AnnotationSource::TypedBody {
|
AnnotationSource::TypedBody {
|
||||||
annotation: annotation_ty,
|
region: annotation.region,
|
||||||
},
|
},
|
||||||
*signature_closure_type.clone(),
|
*signature_closure_type.clone(),
|
||||||
),
|
),
|
||||||
|
@ -1569,19 +1559,10 @@ pub fn rec_defs_help(
|
||||||
def.loc_pattern.clone(),
|
def.loc_pattern.clone(),
|
||||||
arity,
|
arity,
|
||||||
AnnotationSource::TypedBody {
|
AnnotationSource::TypedBody {
|
||||||
annotation: Located::at(annotation.region, annotation.annotation_var),
|
region: annotation.region,
|
||||||
},
|
},
|
||||||
signature.clone(),
|
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
|
// when a def is annotated, and it's body is a closure, treat this
|
||||||
// as a named function (in elm terms) for error messages.
|
// as a named function (in elm terms) for error messages.
|
||||||
|
@ -1714,7 +1695,6 @@ pub fn rec_defs_help(
|
||||||
Store(signature, expr_var, std::file!(), std::line!()),
|
Store(signature, expr_var, std::file!(), std::line!()),
|
||||||
Store(ret_type, ret_var, std::file!(), std::line!()),
|
Store(ret_type, ret_var, std::file!(), std::line!()),
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
annotation_constr,
|
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1745,7 +1725,6 @@ pub fn rec_defs_help(
|
||||||
})),
|
})),
|
||||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||||
Store(signature, expr_var, std::file!(), std::line!()),
|
Store(signature, expr_var, std::file!(), std::line!()),
|
||||||
annotation_constr,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
rigid_info.vars.extend(&new_rigids);
|
rigid_info.vars.extend(&new_rigids);
|
||||||
|
|
|
@ -191,7 +191,6 @@ fn build_effect_always(
|
||||||
let def_annotation = roc_can::def::Annotation {
|
let def_annotation = roc_can::def::Annotation {
|
||||||
signature,
|
signature,
|
||||||
introduced_variables,
|
introduced_variables,
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
aliases: SendMap::default(),
|
aliases: SendMap::default(),
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
};
|
};
|
||||||
|
@ -404,7 +403,6 @@ fn build_effect_map(
|
||||||
let def_annotation = roc_can::def::Annotation {
|
let def_annotation = roc_can::def::Annotation {
|
||||||
signature,
|
signature,
|
||||||
introduced_variables,
|
introduced_variables,
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
aliases: SendMap::default(),
|
aliases: SendMap::default(),
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
};
|
};
|
||||||
|
@ -572,7 +570,6 @@ fn build_effect_after(
|
||||||
let def_annotation = roc_can::def::Annotation {
|
let def_annotation = roc_can::def::Annotation {
|
||||||
signature,
|
signature,
|
||||||
introduced_variables,
|
introduced_variables,
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
aliases: SendMap::default(),
|
aliases: SendMap::default(),
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
};
|
};
|
||||||
|
@ -745,7 +742,6 @@ pub fn build_host_exposed_def(
|
||||||
let def_annotation = roc_can::def::Annotation {
|
let def_annotation = roc_can::def::Annotation {
|
||||||
signature: annotation.typ,
|
signature: annotation.typ,
|
||||||
introduced_variables: annotation.introduced_variables,
|
introduced_variables: annotation.introduced_variables,
|
||||||
annotation_var: var_store.fresh(),
|
|
||||||
aliases: annotation.aliases,
|
aliases: annotation.aliases,
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -211,16 +211,6 @@ impl<T> Located<T> {
|
||||||
value: transform(&self.value),
|
value: transform(&self.value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_in_place<U, F>(self, transform: F) -> Located<U>
|
|
||||||
where
|
|
||||||
F: (FnOnce(T) -> U),
|
|
||||||
{
|
|
||||||
Located {
|
|
||||||
region: self.region,
|
|
||||||
value: transform(self.value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Debug for Located<T>
|
impl<T> fmt::Debug for Located<T>
|
||||||
|
|
|
@ -11,7 +11,7 @@ use roc_types::subs::{
|
||||||
};
|
};
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
use roc_types::types::{gather_fields_unsorted_iter, Alias, Category, ErrorType, PatternCategory};
|
use roc_types::types::{gather_fields_unsorted_iter, Alias, Category, ErrorType, PatternCategory};
|
||||||
use roc_unify::unify::{unify, unify_without_error_compaction, Unified::*};
|
use roc_unify::unify::{unify, Unified::*};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
// Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed
|
// Type checking system adapted from Elm by Evan Czaplicki, BSD-3-Clause Licensed
|
||||||
|
@ -66,7 +66,7 @@ use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum TypeError {
|
pub enum TypeError {
|
||||||
BadExpr(Region, Category, ErrorType, Expected<ErrorType, ErrorType>),
|
BadExpr(Region, Category, ErrorType, Expected<ErrorType>),
|
||||||
BadPattern(Region, PatternCategory, ErrorType, PExpected<ErrorType>),
|
BadPattern(Region, PatternCategory, ErrorType, PExpected<ErrorType>),
|
||||||
CircularType(Region, Symbol, ErrorType),
|
CircularType(Region, Symbol, ErrorType),
|
||||||
BadType(roc_types::types::Problem),
|
BadType(roc_types::types::Problem),
|
||||||
|
@ -205,9 +205,7 @@ fn solve(
|
||||||
expectation.get_type_ref(),
|
expectation.get_type_ref(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Don't transform bad types into errors in case we want to grab other types'
|
match unify(subs, actual, expected) {
|
||||||
// original contents during a failure.
|
|
||||||
match unify_without_error_compaction(subs, actual, expected) {
|
|
||||||
Success(vars) => {
|
Success(vars) => {
|
||||||
introduce(subs, rank, pools, &vars);
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
@ -220,12 +218,7 @@ fn solve(
|
||||||
*region,
|
*region,
|
||||||
category.clone(),
|
category.clone(),
|
||||||
actual_type,
|
actual_type,
|
||||||
expectation
|
expectation.clone().replace(expected_type),
|
||||||
.clone()
|
|
||||||
.replace(expected_type)
|
|
||||||
.replace_annotation_with(|annot_var: Variable| {
|
|
||||||
subs.var_to_error_type(annot_var).0
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
problems.push(problem);
|
problems.push(problem);
|
||||||
|
@ -301,9 +294,7 @@ fn solve(
|
||||||
cached_aliases,
|
cached_aliases,
|
||||||
expectation.get_type_ref(),
|
expectation.get_type_ref(),
|
||||||
);
|
);
|
||||||
// Don't transform bad types into errors in case we want to grab other types'
|
match unify(subs, actual, expected) {
|
||||||
// original contents during a failure.
|
|
||||||
match unify_without_error_compaction(subs, actual, expected) {
|
|
||||||
Success(vars) => {
|
Success(vars) => {
|
||||||
introduce(subs, rank, pools, &vars);
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
@ -317,12 +308,7 @@ fn solve(
|
||||||
*region,
|
*region,
|
||||||
Category::Lookup(*symbol),
|
Category::Lookup(*symbol),
|
||||||
actual_type,
|
actual_type,
|
||||||
expectation
|
expectation.clone().replace(expected_type),
|
||||||
.clone()
|
|
||||||
.replace(expected_type)
|
|
||||||
.replace_annotation_with(|annot_var: Variable| {
|
|
||||||
subs.var_to_error_type(annot_var).0
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
problems.push(problem);
|
problems.push(problem);
|
||||||
|
|
|
@ -1107,61 +1107,28 @@ pub enum PReason {
|
||||||
OptionalField,
|
OptionalField,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum AnnotationSource<Annot> {
|
pub enum AnnotationSource {
|
||||||
TypedIfBranch {
|
TypedIfBranch {
|
||||||
index: Index,
|
index: Index,
|
||||||
num_branches: usize,
|
num_branches: usize,
|
||||||
annotation: Located<Annot>,
|
region: Region,
|
||||||
},
|
},
|
||||||
TypedWhenBranch {
|
TypedWhenBranch {
|
||||||
index: Index,
|
index: Index,
|
||||||
annotation: Located<Annot>,
|
region: Region,
|
||||||
},
|
},
|
||||||
TypedBody {
|
TypedBody {
|
||||||
annotation: Located<Annot>,
|
region: Region,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Annot> AnnotationSource<Annot> {
|
impl AnnotationSource {
|
||||||
pub fn region(&self) -> Region {
|
pub fn region(&self) -> Region {
|
||||||
match self {
|
match self {
|
||||||
Self::TypedIfBranch { annotation, .. }
|
&Self::TypedIfBranch { region, .. }
|
||||||
| Self::TypedWhenBranch { annotation, .. }
|
| &Self::TypedWhenBranch { region, .. }
|
||||||
| Self::TypedBody { annotation, .. } => annotation.region,
|
| &Self::TypedBody { region, .. } => region,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn annotation(&self) -> &Located<Annot> {
|
|
||||||
match self {
|
|
||||||
Self::TypedIfBranch { annotation, .. }
|
|
||||||
| Self::TypedWhenBranch { annotation, .. }
|
|
||||||
| Self::TypedBody { annotation, .. } => annotation,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn replace_with<Annot2, F>(self, create_new_annotation: F) -> AnnotationSource<Annot2>
|
|
||||||
where
|
|
||||||
F: FnOnce(Annot) -> Annot2,
|
|
||||||
{
|
|
||||||
use AnnotationSource::*;
|
|
||||||
match self {
|
|
||||||
TypedIfBranch {
|
|
||||||
index,
|
|
||||||
num_branches,
|
|
||||||
annotation,
|
|
||||||
} => TypedIfBranch {
|
|
||||||
index,
|
|
||||||
num_branches,
|
|
||||||
annotation: annotation.map_in_place(create_new_annotation),
|
|
||||||
},
|
|
||||||
TypedWhenBranch { index, annotation } => TypedWhenBranch {
|
|
||||||
index,
|
|
||||||
annotation: annotation.map_in_place(create_new_annotation),
|
|
||||||
},
|
|
||||||
TypedBody { annotation } => TypedBody {
|
|
||||||
annotation: annotation.map_in_place(create_new_annotation),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,16 +82,6 @@ type Outcome = Vec<Mismatch>;
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn unify(subs: &mut Subs, var1: Variable, var2: Variable) -> Unified {
|
pub fn unify(subs: &mut Subs, var1: Variable, var2: Variable) -> Unified {
|
||||||
unify_help(subs, var1, var2, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn unify_without_error_compaction(subs: &mut Subs, var1: Variable, var2: Variable) -> Unified {
|
|
||||||
unify_help(subs, var1, var2, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn unify_help(subs: &mut Subs, var1: Variable, var2: Variable, compact_errors: bool) -> Unified {
|
|
||||||
let mut vars = Vec::new();
|
let mut vars = Vec::new();
|
||||||
let mismatches = unify_pool(subs, &mut vars, var1, var2);
|
let mismatches = unify_pool(subs, &mut vars, var1, var2);
|
||||||
|
|
||||||
|
@ -103,9 +93,7 @@ fn unify_help(subs: &mut Subs, var1: Variable, var2: Variable, compact_errors: b
|
||||||
|
|
||||||
problems.extend(problems2);
|
problems.extend(problems2);
|
||||||
|
|
||||||
if compact_errors {
|
|
||||||
subs.union(var1, var2, Content::Error.into());
|
subs.union(var1, var2, Content::Error.into());
|
||||||
}
|
|
||||||
|
|
||||||
if !problems.is_empty() {
|
if !problems.is_empty() {
|
||||||
Unified::BadType(vars, problems.remove(0))
|
Unified::BadType(vars, problems.remove(0))
|
||||||
|
|
|
@ -6,9 +6,7 @@ use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
use roc_solve::solve;
|
use roc_solve::solve;
|
||||||
use roc_types::pretty_print::{Parens, WILDCARD};
|
use roc_types::pretty_print::{Parens, WILDCARD};
|
||||||
use roc_types::types::{
|
use roc_types::types::{Category, ErrorType, PatternCategory, Reason, RecordField, TypeExt};
|
||||||
name_type_var, Category, ErrorType, PatternCategory, Reason, RecordField, TypeExt,
|
|
||||||
};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::internal_error;
|
use crate::internal_error;
|
||||||
|
@ -291,7 +289,7 @@ fn to_expr_report<'b>(
|
||||||
expr_region: roc_region::all::Region,
|
expr_region: roc_region::all::Region,
|
||||||
category: Category,
|
category: Category,
|
||||||
found: ErrorType,
|
found: ErrorType,
|
||||||
expected: Expected<ErrorType, ErrorType>,
|
expected: Expected<ErrorType>,
|
||||||
) -> Report<'b> {
|
) -> Report<'b> {
|
||||||
match expected {
|
match expected {
|
||||||
Expected::NoExpectation(expected_type) => {
|
Expected::NoExpectation(expected_type) => {
|
||||||
|
@ -371,7 +369,6 @@ fn to_expr_report<'b>(
|
||||||
|
|
||||||
let expectation_context = ExpectationContext::Annotation {
|
let expectation_context = ExpectationContext::Annotation {
|
||||||
on: on_name_text.clone(),
|
on: on_name_text.clone(),
|
||||||
signature: annotation_source.annotation().value.clone(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let comparison = if diff_is_wildcard_comparison(
|
let comparison = if diff_is_wildcard_comparison(
|
||||||
|
@ -953,10 +950,7 @@ fn count_arguments(tipe: &ErrorType) -> usize {
|
||||||
enum ExpectationContext<'a> {
|
enum ExpectationContext<'a> {
|
||||||
/// An expected type was discovered from a type annotation. Corresponds to
|
/// An expected type was discovered from a type annotation. Corresponds to
|
||||||
/// [`Expected::FromAnnotation`](Expected::FromAnnotation).
|
/// [`Expected::FromAnnotation`](Expected::FromAnnotation).
|
||||||
Annotation {
|
Annotation { on: RocDocBuilder<'a> },
|
||||||
on: RocDocBuilder<'a>,
|
|
||||||
signature: ErrorType,
|
|
||||||
},
|
|
||||||
/// When we don't know the context, or it's not relevant.
|
/// When we don't know the context, or it's not relevant.
|
||||||
Arbitrary,
|
Arbitrary,
|
||||||
}
|
}
|
||||||
|
@ -2698,7 +2692,7 @@ fn type_problem_to_pretty<'b>(
|
||||||
alloc.tip().append(line)
|
alloc.tip().append(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
(BadRigidVar(x, tipe), ExpectationContext::Annotation { on, signature }) => {
|
(BadRigidVar(x, tipe), ExpectationContext::Annotation { on }) => {
|
||||||
use ErrorType::*;
|
use ErrorType::*;
|
||||||
|
|
||||||
let bad_rigid_var = |name: Lowercase, a_thing| {
|
let bad_rigid_var = |name: Lowercase, a_thing| {
|
||||||
|
@ -2712,10 +2706,6 @@ fn type_problem_to_pretty<'b>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let bad_double_wildcard = || {
|
let bad_double_wildcard = || {
|
||||||
let mut taken_names = MutSet::default();
|
|
||||||
signature.add_names(&mut taken_names);
|
|
||||||
let (named_var_suggest, _) = name_type_var(0, &mut taken_names);
|
|
||||||
|
|
||||||
alloc.tip().append(alloc.concat(vec![
|
alloc.tip().append(alloc.concat(vec![
|
||||||
alloc.reflow(
|
alloc.reflow(
|
||||||
"Any connection between types must use a named type variable, not a ",
|
"Any connection between types must use a named type variable, not a ",
|
||||||
|
@ -2723,9 +2713,7 @@ fn type_problem_to_pretty<'b>(
|
||||||
alloc.type_variable(WILDCARD.into()),
|
alloc.type_variable(WILDCARD.into()),
|
||||||
alloc.reflow("! Maybe the annotation "),
|
alloc.reflow("! Maybe the annotation "),
|
||||||
on,
|
on,
|
||||||
alloc.reflow(" should have a named type variable, like "),
|
alloc.reflow(" should have a named type variable in place of the "),
|
||||||
alloc.type_variable(named_var_suggest),
|
|
||||||
alloc.reflow(" in place of the "),
|
|
||||||
alloc.type_variable(WILDCARD.into()),
|
alloc.type_variable(WILDCARD.into()),
|
||||||
alloc.reflow("?"),
|
alloc.reflow("?"),
|
||||||
]))
|
]))
|
||||||
|
|
|
@ -6797,8 +6797,8 @@ I need all branches in an `if` to have the same type!
|
||||||
way that isn't reflected in this annotation.
|
way that isn't reflected in this annotation.
|
||||||
|
|
||||||
Tip: Any connection between types must use a named type variable, not
|
Tip: Any connection between types must use a named type variable, not
|
||||||
a `*`! Maybe the annotation on `f` should have a named type variable,
|
a `*`! Maybe the annotation on `f` should have a named type variable in
|
||||||
like `b` in place of the `*`?
|
place of the `*`?
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -6834,8 +6834,8 @@ I need all branches in an `if` to have the same type!
|
||||||
in a way that isn't reflected in this annotation.
|
in a way that isn't reflected in this annotation.
|
||||||
|
|
||||||
Tip: Any connection between types must use a named type variable, not
|
Tip: Any connection between types must use a named type variable, not
|
||||||
a `*`! Maybe the annotation on `f` should have a named type variable,
|
a `*`! Maybe the annotation on `f` should have a named type variable in
|
||||||
like `c` in place of the `*`?
|
place of the `*`?
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -6876,8 +6876,8 @@ I need all branches in an `if` to have the same type!
|
||||||
way that isn't reflected in this annotation.
|
way that isn't reflected in this annotation.
|
||||||
|
|
||||||
Tip: Any connection between types must use a named type variable, not
|
Tip: Any connection between types must use a named type variable, not
|
||||||
a `*`! Maybe the annotation on `f` should have a named type variable,
|
a `*`! Maybe the annotation on `f` should have a named type variable in
|
||||||
like `c` in place of the `*`?
|
place of the `*`?
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue