mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
remove Shadowed variant from mono pattern
This commit is contained in:
parent
4cdde12823
commit
794f8c4d41
4 changed files with 90 additions and 52 deletions
|
@ -1750,7 +1750,9 @@ mod gen_primitives {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "shadowed")]
|
#[should_panic(
|
||||||
|
expected = "Roc failed with message: \"Shadowing { original_region: |L 3-3, C 4-5|, shadow: |L 6-6, C 8-9| Ident(\\\"x\\\") }\""
|
||||||
|
)]
|
||||||
fn pattern_shadowing() {
|
fn pattern_shadowing() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -1768,7 +1770,7 @@ mod gen_primitives {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
#[should_panic(expected = "shadowed")]
|
#[should_panic(expected = "foo")]
|
||||||
fn unsupported_pattern_tag() {
|
fn unsupported_pattern_tag() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -379,7 +379,7 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
// TODO use guard!
|
// TODO use guard!
|
||||||
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => {
|
Identifier(_) | Underscore | UnsupportedPattern(_) => {
|
||||||
if let Guard::Guard { symbol, id, stmt } = guard {
|
if let Guard::Guard { symbol, id, stmt } = guard {
|
||||||
all_tests.push(Guarded {
|
all_tests.push(Guarded {
|
||||||
opt_test: None,
|
opt_test: None,
|
||||||
|
@ -531,7 +531,7 @@ fn to_relevant_branch_help<'a>(
|
||||||
use Test::*;
|
use Test::*;
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => Some(branch.clone()),
|
Identifier(_) | Underscore | UnsupportedPattern(_) => Some(branch.clone()),
|
||||||
|
|
||||||
RecordDestructure(destructs, _) => match test {
|
RecordDestructure(destructs, _) => match test {
|
||||||
IsCtor {
|
IsCtor {
|
||||||
|
@ -742,7 +742,7 @@ fn needs_tests<'a>(pattern: &Pattern<'a>) -> bool {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
|
|
||||||
match pattern {
|
match pattern {
|
||||||
Identifier(_) | Underscore | Shadowed(_, _) | UnsupportedPattern(_) => false,
|
Identifier(_) | Underscore | UnsupportedPattern(_) => false,
|
||||||
|
|
||||||
RecordDestructure(_, _)
|
RecordDestructure(_, _)
|
||||||
| AppliedTag { .. }
|
| AppliedTag { .. }
|
||||||
|
|
|
@ -84,11 +84,6 @@ fn simplify<'a>(pattern: &crate::ir::Pattern<'a>) -> Pattern {
|
||||||
Ctor(union, tag_id, patterns)
|
Ctor(union, tag_id, patterns)
|
||||||
}
|
}
|
||||||
|
|
||||||
Shadowed(_region, _ident) => {
|
|
||||||
// Treat as an Anything
|
|
||||||
// code-gen will make a runtime error out of the branch
|
|
||||||
Anything
|
|
||||||
}
|
|
||||||
UnsupportedPattern(_region) => {
|
UnsupportedPattern(_region) => {
|
||||||
// Treat as an Anything
|
// Treat as an Anything
|
||||||
// code-gen will make a runtime error out of the branch
|
// code-gen will make a runtime error out of the branch
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
||||||
use roc_module::ident::{ForeignSymbol, Ident, Lowercase, TagName};
|
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||||
use roc_problem::can::RuntimeError;
|
use roc_problem::can::RuntimeError;
|
||||||
|
@ -1264,7 +1264,22 @@ fn patterns_to_when<'a>(
|
||||||
// this must be fixed when moving exhaustiveness checking to the new canonical AST
|
// this must be fixed when moving exhaustiveness checking to the new canonical AST
|
||||||
for (pattern_var, pattern) in patterns.into_iter() {
|
for (pattern_var, pattern) in patterns.into_iter() {
|
||||||
let context = crate::exhaustive::Context::BadArg;
|
let context = crate::exhaustive::Context::BadArg;
|
||||||
let mono_pattern = from_can_pattern(env, layout_cache, &pattern.value);
|
let mono_pattern = match from_can_pattern(env, layout_cache, &pattern.value) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(runtime_error) => {
|
||||||
|
// Even if the body was Ok, replace it with this Err.
|
||||||
|
// If it was already an Err, leave it at that Err, so the first
|
||||||
|
// RuntimeError we encountered remains the first.
|
||||||
|
body = body.and({
|
||||||
|
Err(Located {
|
||||||
|
region: pattern.region,
|
||||||
|
value: runtime_error,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match crate::exhaustive::check(
|
match crate::exhaustive::check(
|
||||||
pattern.region,
|
pattern.region,
|
||||||
|
@ -2392,7 +2407,14 @@ pub fn with_hole<'a>(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this may be a destructure pattern
|
// this may be a destructure pattern
|
||||||
let mono_pattern = from_can_pattern(env, layout_cache, &def.loc_pattern.value);
|
let mono_pattern = match from_can_pattern(env, layout_cache, &def.loc_pattern.value)
|
||||||
|
{
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_runtime_error) => {
|
||||||
|
// todo
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let context = crate::exhaustive::Context::BadDestruct;
|
let context = crate::exhaustive::Context::BadDestruct;
|
||||||
match crate::exhaustive::check(
|
match crate::exhaustive::check(
|
||||||
|
@ -3923,7 +3945,10 @@ pub fn from_can<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
// this may be a destructure pattern
|
// this may be a destructure pattern
|
||||||
let mono_pattern = from_can_pattern(env, layout_cache, &def.loc_pattern.value);
|
let mono_pattern = match from_can_pattern(env, layout_cache, &def.loc_pattern.value) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
if let Pattern::Identifier(symbol) = mono_pattern {
|
if let Pattern::Identifier(symbol) = mono_pattern {
|
||||||
let hole =
|
let hole =
|
||||||
|
@ -4015,8 +4040,8 @@ fn to_opt_branches<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
for loc_pattern in when_branch.patterns {
|
for loc_pattern in when_branch.patterns {
|
||||||
let mono_pattern = from_can_pattern(env, layout_cache, &loc_pattern.value);
|
match from_can_pattern(env, layout_cache, &loc_pattern.value) {
|
||||||
|
Ok(mono_pattern) => {
|
||||||
loc_branches.push((
|
loc_branches.push((
|
||||||
Located::at(loc_pattern.region, mono_pattern.clone()),
|
Located::at(loc_pattern.region, mono_pattern.clone()),
|
||||||
exhaustive_guard.clone(),
|
exhaustive_guard.clone(),
|
||||||
|
@ -4029,6 +4054,21 @@ fn to_opt_branches<'a>(
|
||||||
when_branch.value.value.clone(),
|
when_branch.value.value.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
Err(runtime_error) => {
|
||||||
|
loc_branches.push((
|
||||||
|
Located::at(loc_pattern.region, Pattern::Underscore),
|
||||||
|
exhaustive_guard.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
|
// TODO remove clone?
|
||||||
|
opt_branches.push((
|
||||||
|
Pattern::Underscore,
|
||||||
|
when_branch.guard.clone(),
|
||||||
|
roc_can::expr::Expr::RuntimeError(runtime_error),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE exhaustiveness is checked after the construction of all the branches
|
// NOTE exhaustiveness is checked after the construction of all the branches
|
||||||
|
@ -4659,10 +4699,6 @@ fn store_pattern<'a>(
|
||||||
unreachable!("a record destructure must always occur on a struct layout");
|
unreachable!("a record destructure must always occur on a struct layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
Shadowed(_region, _ident) => {
|
|
||||||
return Err(&"shadowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
UnsupportedPattern(_region) => {
|
UnsupportedPattern(_region) => {
|
||||||
return Err(&"unsupported pattern");
|
return Err(&"unsupported pattern");
|
||||||
}
|
}
|
||||||
|
@ -5431,7 +5467,7 @@ pub enum Pattern<'a> {
|
||||||
},
|
},
|
||||||
|
|
||||||
// Runtime Exceptions
|
// Runtime Exceptions
|
||||||
Shadowed(Region, Located<Ident>),
|
// Shadowed(Region, Located<Ident>),
|
||||||
// Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments!
|
// Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments!
|
||||||
UnsupportedPattern(Region),
|
UnsupportedPattern(Region),
|
||||||
}
|
}
|
||||||
|
@ -5463,23 +5499,26 @@ pub fn from_can_pattern<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
can_pattern: &roc_can::pattern::Pattern,
|
can_pattern: &roc_can::pattern::Pattern,
|
||||||
) -> Pattern<'a> {
|
) -> Result<Pattern<'a>, RuntimeError> {
|
||||||
use roc_can::pattern::Pattern::*;
|
use roc_can::pattern::Pattern::*;
|
||||||
match can_pattern {
|
match can_pattern {
|
||||||
Underscore => Pattern::Underscore,
|
Underscore => Ok(Pattern::Underscore),
|
||||||
Identifier(symbol) => Pattern::Identifier(*symbol),
|
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||||
IntLiteral(v) => Pattern::IntLiteral(*v),
|
IntLiteral(v) => Ok(Pattern::IntLiteral(*v)),
|
||||||
FloatLiteral(v) => Pattern::FloatLiteral(f64::to_bits(*v)),
|
FloatLiteral(v) => Ok(Pattern::FloatLiteral(f64::to_bits(*v))),
|
||||||
StrLiteral(v) => Pattern::StrLiteral(v.clone()),
|
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
|
||||||
Shadowed(region, ident) => Pattern::Shadowed(*region, ident.clone()),
|
Shadowed(region, ident) => Err(RuntimeError::Shadowing {
|
||||||
UnsupportedPattern(region) => Pattern::UnsupportedPattern(*region),
|
original_region: *region,
|
||||||
|
shadow: ident.clone(),
|
||||||
|
}),
|
||||||
|
UnsupportedPattern(region) => Ok(Pattern::UnsupportedPattern(*region)),
|
||||||
MalformedPattern(_problem, region) => {
|
MalformedPattern(_problem, region) => {
|
||||||
// TODO preserve malformed problem information here?
|
// TODO preserve malformed problem information here?
|
||||||
Pattern::UnsupportedPattern(*region)
|
Ok(Pattern::UnsupportedPattern(*region))
|
||||||
}
|
}
|
||||||
NumLiteral(var, num) => match num_argument_to_int_or_float(env.subs, *var) {
|
NumLiteral(var, num) => match num_argument_to_int_or_float(env.subs, *var) {
|
||||||
IntOrFloat::IntType => Pattern::IntLiteral(*num),
|
IntOrFloat::IntType => Ok(Pattern::IntLiteral(*num)),
|
||||||
IntOrFloat::FloatType => Pattern::FloatLiteral(*num as u64),
|
IntOrFloat::FloatType => Ok(Pattern::FloatLiteral(*num as u64)),
|
||||||
},
|
},
|
||||||
|
|
||||||
AppliedTag {
|
AppliedTag {
|
||||||
|
@ -5493,7 +5532,7 @@ pub fn from_can_pattern<'a>(
|
||||||
|
|
||||||
let variant = crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs);
|
let variant = crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs);
|
||||||
|
|
||||||
match variant {
|
let result = match variant {
|
||||||
Never => unreachable!(
|
Never => unreachable!(
|
||||||
"there is no pattern of type `[]`, union var {:?}",
|
"there is no pattern of type `[]`, union var {:?}",
|
||||||
*whole_var
|
*whole_var
|
||||||
|
@ -5582,7 +5621,7 @@ pub fn from_can_pattern<'a>(
|
||||||
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
for ((_, loc_pat), layout) in arguments.iter().zip(field_layouts.iter()) {
|
for ((_, loc_pat), layout) in arguments.iter().zip(field_layouts.iter()) {
|
||||||
mono_args.push((
|
mono_args.push((
|
||||||
from_can_pattern(env, layout_cache, &loc_pat.value),
|
from_can_pattern(env, layout_cache, &loc_pat.value)?,
|
||||||
layout.clone(),
|
layout.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -5642,7 +5681,7 @@ pub fn from_can_pattern<'a>(
|
||||||
let it = argument_layouts[1..].iter();
|
let it = argument_layouts[1..].iter();
|
||||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||||
mono_args.push((
|
mono_args.push((
|
||||||
from_can_pattern(env, layout_cache, &loc_pat.value),
|
from_can_pattern(env, layout_cache, &loc_pat.value)?,
|
||||||
layout.clone(),
|
layout.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -5664,7 +5703,9 @@ pub fn from_can_pattern<'a>(
|
||||||
layout,
|
layout,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDestructure {
|
RecordDestructure {
|
||||||
|
@ -5704,7 +5745,7 @@ pub fn from_can_pattern<'a>(
|
||||||
layout_cache,
|
layout_cache,
|
||||||
&destruct.value,
|
&destruct.value,
|
||||||
field_layout.clone(),
|
field_layout.clone(),
|
||||||
));
|
)?);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// this field is not destructured by the pattern
|
// this field is not destructured by the pattern
|
||||||
|
@ -5783,10 +5824,10 @@ pub fn from_can_pattern<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern::RecordDestructure(
|
Ok(Pattern::RecordDestructure(
|
||||||
mono_destructs,
|
mono_destructs,
|
||||||
Layout::Struct(field_layouts.into_bump_slice()),
|
Layout::Struct(field_layouts.into_bump_slice()),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5796,8 +5837,8 @@ fn from_can_record_destruct<'a>(
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
can_rd: &roc_can::pattern::RecordDestruct,
|
can_rd: &roc_can::pattern::RecordDestruct,
|
||||||
field_layout: Layout<'a>,
|
field_layout: Layout<'a>,
|
||||||
) -> RecordDestruct<'a> {
|
) -> Result<RecordDestruct<'a>, RuntimeError> {
|
||||||
RecordDestruct {
|
Ok(RecordDestruct {
|
||||||
label: can_rd.label.clone(),
|
label: can_rd.label.clone(),
|
||||||
symbol: can_rd.symbol,
|
symbol: can_rd.symbol,
|
||||||
variable: can_rd.var,
|
variable: can_rd.var,
|
||||||
|
@ -5810,10 +5851,10 @@ fn from_can_record_destruct<'a>(
|
||||||
DestructType::Required
|
DestructType::Required
|
||||||
}
|
}
|
||||||
roc_can::pattern::DestructType::Guard(_, loc_pattern) => {
|
roc_can::pattern::DestructType::Guard(_, loc_pattern) => {
|
||||||
DestructType::Guard(from_can_pattern(env, layout_cache, &loc_pattern.value))
|
DestructType::Guard(from_can_pattern(env, layout_cache, &loc_pattern.value)?)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Potentially translate LowLevel operations into more efficient ones based on
|
/// Potentially translate LowLevel operations into more efficient ones based on
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue