diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index 3d18978806..aca0206831 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -564,9 +564,17 @@ pub fn canonicalize_defs<'a>( // once we've finished assembling the entire scope. let mut pending_value_defs = Vec::with_capacity(value_defs.len()); for loc_def in value_defs.into_iter() { - match to_pending_value_def(env, var_store, loc_def.value, &mut scope, pattern_type) { + let mut new_output = Output::default(); + match to_pending_value_def( + env, + var_store, + loc_def.value, + &mut scope, + &mut new_output, + pattern_type, + ) { None => { /* skip */ } - Some((new_output, pending_def)) => { + Some(pending_def) => { // store the top-level defs, used to ensure that closures won't capture them if let PatternType::TopLevelDef = pattern_type { match &pending_def { @@ -1806,41 +1814,46 @@ fn to_pending_value_def<'a>( var_store: &mut VarStore, def: &'a ast::ValueDef<'a>, scope: &mut Scope, + output: &mut Output, pattern_type: PatternType, -) -> Option<(Output, PendingValueDef<'a>)> { +) -> Option> { use ast::ValueDef::*; match def { Annotation(loc_pattern, loc_ann) => { // This takes care of checking for shadowing and adding idents to scope. - let (output, loc_can_pattern) = canonicalize_def_header_pattern( + let loc_can_pattern = canonicalize_def_header_pattern( env, var_store, scope, + output, pattern_type, &loc_pattern.value, loc_pattern.region, ); - Some(( - output, - PendingValueDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann), + Some(PendingValueDef::AnnotationOnly( + loc_pattern, + loc_can_pattern, + loc_ann, )) } Body(loc_pattern, loc_expr) => { // This takes care of checking for shadowing and adding idents to scope. - let (output, loc_can_pattern) = canonicalize_def_header_pattern( + let loc_can_pattern = canonicalize_def_header_pattern( env, var_store, scope, + output, pattern_type, &loc_pattern.value, loc_pattern.region, ); - Some(( - output, - PendingValueDef::Body(loc_pattern, loc_can_pattern, loc_expr), + Some(PendingValueDef::Body( + loc_pattern, + loc_can_pattern, + loc_expr, )) } @@ -1859,18 +1872,21 @@ fn to_pending_value_def<'a>( // { x, y ? False } = rec // // This takes care of checking for shadowing and adding idents to scope. - let (output, loc_can_pattern) = canonicalize_def_header_pattern( + let loc_can_pattern = canonicalize_def_header_pattern( env, var_store, scope, + output, pattern_type, &body_pattern.value, body_pattern.region, ); - Some(( - output, - PendingValueDef::TypedBody(body_pattern, loc_can_pattern, ann_type, body_expr), + Some(PendingValueDef::TypedBody( + body_pattern, + loc_can_pattern, + ann_type, + body_expr, )) } else { // the pattern of the annotation does not match the pattern of the body direc diff --git a/compiler/can/src/expr.rs b/compiler/can/src/expr.rs index be8dd26648..10e9479f23 100644 --- a/compiler/can/src/expr.rs +++ b/compiler/can/src/expr.rs @@ -627,25 +627,23 @@ pub fn canonicalize_expr<'a>( let mut can_args = Vec::with_capacity(loc_arg_patterns.len()); let mut output = Output::default(); - let mut bound_by_argument_patterns = MutSet::default(); - for loc_pattern in loc_arg_patterns.iter() { - let (new_output, can_arg) = canonicalize_pattern( + let can_argument_pattern = canonicalize_pattern( env, var_store, &mut scope, + &mut output, FunctionArg, &loc_pattern.value, loc_pattern.region, ); - bound_by_argument_patterns.extend(new_output.references.bound_symbols().copied()); - - output.union(new_output); - - can_args.push((var_store.fresh(), can_arg)); + can_args.push((var_store.fresh(), can_argument_pattern)); } + let bound_by_argument_patterns: Vec<_> = + output.references.bound_symbols().copied().collect(); + let (loc_body_expr, new_output) = canonicalize_expr( env, var_store, @@ -1034,17 +1032,16 @@ fn canonicalize_when_branch<'a>( // TODO report symbols not bound in all patterns for loc_pattern in branch.patterns.iter() { - let (new_output, can_pattern) = canonicalize_pattern( + let can_pattern = canonicalize_pattern( env, var_store, &mut scope, + output, WhenBranch, &loc_pattern.value, loc_pattern.region, ); - output.union(new_output); - patterns.push(can_pattern); } diff --git a/compiler/can/src/pattern.rs b/compiler/can/src/pattern.rs index dc8a11a5b0..9804707b2c 100644 --- a/compiler/can/src/pattern.rs +++ b/compiler/can/src/pattern.rs @@ -156,13 +156,13 @@ pub fn canonicalize_def_header_pattern<'a>( env: &mut Env<'a>, var_store: &mut VarStore, scope: &mut Scope, + output: &mut Output, pattern_type: PatternType, pattern: &ast::Pattern<'a>, region: Region, -) -> (Output, Loc) { +) -> Loc { use roc_parse::ast::Pattern::*; - let mut output = Output::default(); match pattern { // Identifiers that shadow ability members may appear (and may only appear) at the header of a def. Identifier(name) => match scope.introduce_or_shadow_ability_member( @@ -182,7 +182,7 @@ pub fn canonicalize_def_header_pattern<'a>( specializes: ability_member_name, }, }; - (output, Loc::at(region, can_pattern)) + Loc::at(region, can_pattern) } Err((original_region, shadow, new_symbol)) => { env.problem(Problem::RuntimeError(RuntimeError::Shadowing { @@ -193,10 +193,10 @@ pub fn canonicalize_def_header_pattern<'a>( output.references.insert_bound(new_symbol); let can_pattern = Pattern::Shadowed(original_region, shadow, new_symbol); - (output, Loc::at(region, can_pattern)) + Loc::at(region, can_pattern) } }, - _ => canonicalize_pattern(env, var_store, scope, pattern_type, pattern, region), + _ => canonicalize_pattern(env, var_store, scope, output, pattern_type, pattern, region), } } @@ -204,14 +204,14 @@ pub fn canonicalize_pattern<'a>( env: &mut Env<'a>, var_store: &mut VarStore, scope: &mut Scope, + output: &mut Output, pattern_type: PatternType, pattern: &ast::Pattern<'a>, region: Region, -) -> (Output, Loc) { +) -> Loc { use roc_parse::ast::Pattern::*; use PatternType::*; - let mut output = Output::default(); let can_pattern = match pattern { Identifier(name) => match scope.introduce( (*name).into(), @@ -266,17 +266,16 @@ pub fn canonicalize_pattern<'a>( Apply(tag, patterns) => { let mut can_patterns = Vec::with_capacity(patterns.len()); for loc_pattern in *patterns { - let (new_output, can_pattern) = canonicalize_pattern( + let can_pattern = canonicalize_pattern( env, var_store, scope, + output, pattern_type, &loc_pattern.value, loc_pattern.region, ); - output.union(new_output); - can_patterns.push((var_store.fresh(), can_pattern)); } @@ -442,7 +441,15 @@ pub fn canonicalize_pattern<'a>( } SpaceBefore(sub_pattern, _) | SpaceAfter(sub_pattern, _) => { - return canonicalize_pattern(env, var_store, scope, pattern_type, sub_pattern, region) + return canonicalize_pattern( + env, + var_store, + scope, + output, + pattern_type, + sub_pattern, + region, + ) } RecordDestructure(patterns) => { let ext_var = var_store.fresh(); @@ -492,17 +499,16 @@ pub fn canonicalize_pattern<'a>( RequiredField(label, loc_guard) => { // a guard does not introduce the label into scope! let symbol = scope.ignore(label.into(), &mut env.ident_ids); - let (new_output, can_guard) = canonicalize_pattern( + let can_guard = canonicalize_pattern( env, var_store, scope, + output, pattern_type, &loc_guard.value, loc_guard.region, ); - output.union(new_output); - destructs.push(Loc { region: loc_pattern.region, value: RecordDestruct { @@ -597,13 +603,10 @@ pub fn canonicalize_pattern<'a>( } }; - ( - output, - Loc { - region, - value: can_pattern, - }, - ) + Loc { + region, + value: can_pattern, + } } /// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't