only introduce rigid once!

This commit is contained in:
Folkert 2021-09-24 21:53:41 +02:00
parent 1fba3702a8
commit 23e8f6c687
2 changed files with 84 additions and 3 deletions

View file

@ -9,7 +9,7 @@ use roc_can::expected::PExpected;
use roc_can::expr::Expr::{self, *}; use roc_can::expr::Expr::{self, *};
use roc_can::expr::{Field, WhenBranch}; use roc_can::expr::{Field, WhenBranch};
use roc_can::pattern::Pattern; use roc_can::pattern::Pattern;
use roc_collections::all::{ImMap, Index, SendMap}; use roc_collections::all::{ImMap, Index, MutSet, SendMap};
use roc_module::ident::{Lowercase, TagName}; use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::{ModuleId, Symbol}; use roc_module::symbol::{ModuleId, Symbol};
use roc_region::all::{Located, Region}; use roc_region::all::{Located, Region};
@ -1438,13 +1438,15 @@ fn instantiate_rigids(
annotation: &Type, annotation: &Type,
introduced_vars: &IntroducedVariables, introduced_vars: &IntroducedVariables,
new_rigids: &mut Vec<Variable>, new_rigids: &mut Vec<Variable>,
ftv: &mut ImMap<Lowercase, Variable>, ftv: &mut ImMap<Lowercase, Variable>, // rigids defined before the current annotation
loc_pattern: &Located<Pattern>, loc_pattern: &Located<Pattern>,
headers: &mut SendMap<Symbol, Located<Type>>, headers: &mut SendMap<Symbol, Located<Type>>,
) -> Type { ) -> Type {
let mut annotation = annotation.clone(); let mut annotation = annotation.clone();
let mut rigid_substitution: ImMap<Variable, Type> = ImMap::default(); let mut rigid_substitution: ImMap<Variable, Type> = ImMap::default();
let outside_rigids: MutSet<Variable> = ftv.values().copied().collect();
for (name, var) in introduced_vars.var_by_name.iter() { for (name, var) in introduced_vars.var_by_name.iter() {
if let Some(existing_rigid) = ftv.get(name) { if let Some(existing_rigid) = ftv.get(name) {
rigid_substitution.insert(*var, Type::Variable(*existing_rigid)); rigid_substitution.insert(*var, Type::Variable(*existing_rigid));
@ -1464,7 +1466,12 @@ fn instantiate_rigids(
&Located::at(loc_pattern.region, annotation.clone()), &Located::at(loc_pattern.region, annotation.clone()),
) { ) {
for (symbol, loc_type) in new_headers { for (symbol, loc_type) in new_headers {
new_rigids.extend(loc_type.value.variables()); for var in loc_type.value.variables() {
// a rigid is only new if this annotation is the first occurence of this rigid
if !outside_rigids.contains(&var) {
new_rigids.push(var);
}
}
headers.insert(symbol, loc_type); headers.insert(symbol, loc_type);
} }
} }

View file

@ -2906,3 +2906,77 @@ fn do_pass_bool_byte_closure_layout() {
RocStr RocStr
); );
} }
#[test]
fn nested_rigid_list() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
foo : List a -> List a
foo = \list ->
p2 : List a
p2 = list
p2
main =
when foo [] is
_ -> "hello world"
"#
),
RocStr::from_slice(b"hello world"),
RocStr
);
}
#[test]
fn nested_rigid_alias() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
Identity a : [ @Identity a ]
foo : Identity a -> Identity a
foo = \list ->
p2 : Identity a
p2 = list
p2
main =
when foo (@Identity "foo") is
_ -> "hello world"
"#
),
RocStr::from_slice(b"hello world"),
RocStr
);
}
#[test]
fn nested_rigid_tag_union() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
foo : [ @Identity a ] -> [ @Identity a ]
foo = \list ->
p2 : [ @Identity a ]
p2 = list
p2
main =
when foo (@Identity "foo") is
_ -> "hello world"
"#
),
RocStr::from_slice(b"hello world"),
RocStr
);
}