Permit binding variables multiple itmes in when branches

This commit is contained in:
Ayaz Hafiz 2022-07-21 11:06:40 -04:00
parent c48c4f3183
commit bf8fc0d0de
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
6 changed files with 78 additions and 31 deletions

View file

@ -227,10 +227,25 @@ pub fn canonicalize_def_header_pattern<'a>(
}
}
}
_ => canonicalize_pattern(env, var_store, scope, output, pattern_type, pattern, region),
_ => canonicalize_pattern(
env,
var_store,
scope,
output,
pattern_type,
pattern,
region,
PermitShadows(false),
),
}
}
/// Allow binding of symbols that appear shadowed.
///
/// For example, in the branch `A x | B x -> ...`, both pattern bind `x`; that's not a shadow!
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct PermitShadows(pub bool);
pub fn canonicalize_pattern<'a>(
env: &mut Env<'a>,
var_store: &mut VarStore,
@ -239,6 +254,7 @@ pub fn canonicalize_pattern<'a>(
pattern_type: PatternType,
pattern: &ast::Pattern<'a>,
region: Region,
permit_shadows: PermitShadows,
) -> Loc<Pattern> {
use roc_parse::ast::Pattern::*;
use PatternType::*;
@ -250,15 +266,21 @@ pub fn canonicalize_pattern<'a>(
Pattern::Identifier(symbol)
}
Err((original_region, shadow, new_symbol)) => {
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
original_region,
shadow: shadow.clone(),
kind: ShadowKind::Variable,
}));
output.references.insert_bound(new_symbol);
Err((shadowed_symbol, shadow, new_symbol)) => {
if permit_shadows.0 {
output.references.insert_bound(shadowed_symbol.value);
Pattern::Shadowed(original_region, shadow, new_symbol)
Pattern::Identifier(shadowed_symbol.value)
} else {
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
original_region: shadowed_symbol.region,
shadow: shadow.clone(),
kind: ShadowKind::Variable,
}));
output.references.insert_bound(new_symbol);
Pattern::Shadowed(shadowed_symbol.region, shadow, new_symbol)
}
}
},
Tag(name) => {
@ -289,6 +311,7 @@ pub fn canonicalize_pattern<'a>(
pattern_type,
&loc_pattern.value,
loc_pattern.region,
permit_shadows,
);
can_patterns.push((var_store.fresh(), can_pattern));
@ -457,6 +480,7 @@ pub fn canonicalize_pattern<'a>(
pattern_type,
sub_pattern,
region,
permit_shadows,
)
}
RecordDestructure(patterns) => {
@ -482,9 +506,9 @@ pub fn canonicalize_pattern<'a>(
},
});
}
Err((original_region, shadow, new_symbol)) => {
Err((shadowed_symbol, shadow, new_symbol)) => {
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
original_region,
original_region: shadowed_symbol.region,
shadow: shadow.clone(),
kind: ShadowKind::Variable,
}));
@ -493,8 +517,11 @@ pub fn canonicalize_pattern<'a>(
// are, we're definitely shadowed and will
// get a runtime exception as soon as we
// encounter the first bad pattern.
opt_erroneous =
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
opt_erroneous = Some(Pattern::Shadowed(
shadowed_symbol.region,
shadow,
new_symbol,
));
}
};
}
@ -511,6 +538,7 @@ pub fn canonicalize_pattern<'a>(
pattern_type,
&loc_guard.value,
loc_guard.region,
permit_shadows,
);
destructs.push(Loc {
@ -550,9 +578,9 @@ pub fn canonicalize_pattern<'a>(
},
});
}
Err((original_region, shadow, new_symbol)) => {
Err((shadowed_symbol, shadow, new_symbol)) => {
env.problem(Problem::RuntimeError(RuntimeError::Shadowing {
original_region,
original_region: shadowed_symbol.region,
shadow: shadow.clone(),
kind: ShadowKind::Variable,
}));
@ -561,8 +589,11 @@ pub fn canonicalize_pattern<'a>(
// are, we're definitely shadowed and will
// get a runtime exception as soon as we
// encounter the first bad pattern.
opt_erroneous =
Some(Pattern::Shadowed(original_region, shadow, new_symbol));
opt_erroneous = Some(Pattern::Shadowed(
shadowed_symbol.region,
shadow,
new_symbol,
));
}
};
}