diff --git a/compiler/can/src/annotation.rs b/compiler/can/src/annotation.rs index e0528d9aa8..64d9fe7f60 100644 --- a/compiler/can/src/annotation.rs +++ b/compiler/can/src/annotation.rs @@ -195,6 +195,18 @@ fn can_annotation_help( vars.push((name.clone(), arg_ann)); } + // make sure the recursion variable is freshly instantiated + if let Type::RecursiveTagUnion(rvar, _, _) = &mut actual { + let new = var_store.fresh(); + substitutions.insert(*rvar, Type::Variable(new)); + *rvar = new; + } + + // make sure hidden variables are freshly instantiated + for var in alias.hidden_variables.iter() { + substitutions.insert(*var, Type::Variable(var_store.fresh())); + } + // instantiate variables actual.substitute(&substitutions); @@ -320,9 +332,17 @@ fn can_annotation_help( inner_type }; + let mut hidden_variables = MutSet::default(); + hidden_variables.extend(alias_actual.variables()); + + for loc_var in lowercase_vars.iter() { + hidden_variables.remove(&loc_var.value.1); + } + let alias = Alias { region, vars: lowercase_vars, + hidden_variables, uniqueness: None, typ: alias_actual, }; diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index fe82944005..a3b270f231 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -281,15 +281,8 @@ pub fn canonicalize_defs<'a>( } scope.add_alias(symbol, ann.region, can_vars.clone(), can_ann.typ.clone()); - - let alias = roc_types::types::Alias { - region: ann.region, - vars: can_vars, - uniqueness: None, - typ: can_ann.typ, - }; - - aliases.insert(symbol, alias); + let alias = scope.lookup_alias(symbol).expect("alias is added to scope"); + aliases.insert(symbol, alias.clone()); } other => value_defs.push(other), } diff --git a/compiler/can/src/scope.rs b/compiler/can/src/scope.rs index d1817e8141..f4e72085a5 100644 --- a/compiler/can/src/scope.rs +++ b/compiler/can/src/scope.rs @@ -1,4 +1,4 @@ -use roc_collections::all::ImMap; +use roc_collections::all::{ImMap, MutSet}; use roc_module::ident::{Ident, Lowercase}; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_problem::can::RuntimeError; @@ -146,14 +146,21 @@ impl Scope { vars: Vec>, typ: Type, ) { - self.aliases.insert( - name, - Alias { - region, - vars, - uniqueness: None, - typ, - }, - ); + let mut hidden_variables = MutSet::default(); + hidden_variables.extend(typ.variables()); + + for loc_var in vars.iter() { + hidden_variables.remove(&loc_var.value.1); + } + + let alias = Alias { + region, + vars, + hidden_variables, + uniqueness: None, + typ, + }; + + self.aliases.insert(name, alias); } } diff --git a/compiler/constrain/src/module.rs b/compiler/constrain/src/module.rs index ffccbc61de..89def9bdb0 100644 --- a/compiler/constrain/src/module.rs +++ b/compiler/constrain/src/module.rs @@ -150,8 +150,16 @@ where )); } + let mut hidden_variables = MutSet::default(); + hidden_variables.extend(actual.variables()); + + for loc_var in vars.iter() { + hidden_variables.remove(&loc_var.value.1); + } + let alias = Alias { vars, + hidden_variables, region: builtin_alias.region, uniqueness: None, typ: actual, @@ -196,8 +204,16 @@ pub fn constrain_imported_aliases( actual.substitute(&substitution); + let mut hidden_variables = MutSet::default(); + hidden_variables.extend(actual.variables()); + + for loc_var in vars.iter() { + hidden_variables.remove(&loc_var.value.1); + } + let alias = Alias { vars, + hidden_variables, region: imported_alias.region, uniqueness: imported_alias.uniqueness, typ: actual, diff --git a/compiler/types/src/types.rs b/compiler/types/src/types.rs index 0db34cb709..d3c43d6b25 100644 --- a/compiler/types/src/types.rs +++ b/compiler/types/src/types.rs @@ -984,6 +984,10 @@ pub enum PatternCategory { pub struct Alias { pub region: Region, pub vars: Vec>, + + /// hidden type variables, like the closure variable in `a -> b` + pub hidden_variables: MutSet, + pub uniqueness: Option, pub typ: Type, }