Count default exprs as having used things

This commit is contained in:
Richard Feldman 2020-07-20 21:56:16 -04:00
parent 81a1111cae
commit 71f929aba2
3 changed files with 75 additions and 43 deletions

View file

@ -148,7 +148,7 @@ pub fn canonicalize_defs<'a>(
// Any time we have an Annotation followed immediately by a Body, // Any time we have an Annotation followed immediately by a Body,
// check to see if their patterns are equivalent. If they are, // check to see if their patterns are equivalent. If they are,
// turn it into a TypedBody. Otherwise, give an error. // turn it into a TypedBody. Otherwise, give an error.
let pending_def = match &loc_def.value { let (new_output, pending_def) = match &loc_def.value {
Annotation(pattern, annotation) | Nested(Annotation(pattern, annotation)) => { Annotation(pattern, annotation) | Nested(Annotation(pattern, annotation)) => {
match iter.peek() { match iter.peek() {
Some(Located { Some(Located {
@ -189,6 +189,8 @@ pub fn canonicalize_defs<'a>(
_ => to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type), _ => to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type),
}; };
output.union(new_output);
// Record the ast::Expr for later. We'll do another pass through these // Record the ast::Expr for later. We'll do another pass through these
// once we have the entire scope assembled. If we were to canonicalize // once we have the entire scope assembled. If we were to canonicalize
// the exprs right now, they wouldn't have symbols in scope from defs // the exprs right now, they wouldn't have symbols in scope from defs
@ -212,8 +214,8 @@ pub fn canonicalize_defs<'a>(
let mut can_vars: Vec<Located<(Lowercase, Variable)>> = let mut can_vars: Vec<Located<(Lowercase, Variable)>> =
Vec::with_capacity(vars.len()); Vec::with_capacity(vars.len());
let mut is_phantom = false; let mut is_phantom = false;
for loc_lowercase in vars { for loc_lowercase in vars {
if let Some(var) = can_ann if let Some(var) = can_ann
.introduced_variables .introduced_variables
@ -1288,13 +1290,13 @@ fn to_pending_def<'a>(
def: &'a ast::Def<'a>, def: &'a ast::Def<'a>,
scope: &mut Scope, scope: &mut Scope,
pattern_type: PatternType, pattern_type: PatternType,
) -> PendingDef<'a> { ) -> (Output, PendingDef<'a>) {
use roc_parse::ast::Def::*; use roc_parse::ast::Def::*;
match def { match def {
Annotation(loc_pattern, loc_ann) => { Annotation(loc_pattern, loc_ann) => {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let loc_can_pattern = canonicalize_pattern( let (output, loc_can_pattern) = canonicalize_pattern(
env, env,
var_store, var_store,
scope, scope,
@ -1303,11 +1305,14 @@ fn to_pending_def<'a>(
loc_pattern.region, loc_pattern.region,
); );
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann) (
output,
PendingDef::AnnotationOnly(loc_pattern, loc_can_pattern, loc_ann),
)
} }
Body(loc_pattern, loc_expr) => { Body(loc_pattern, loc_expr) => {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let loc_can_pattern = canonicalize_pattern( let (output, loc_can_pattern) = canonicalize_pattern(
env, env,
var_store, var_store,
scope, scope,
@ -1316,7 +1321,10 @@ fn to_pending_def<'a>(
loc_pattern.region, loc_pattern.region,
); );
PendingDef::Body(loc_pattern, loc_can_pattern, loc_expr) (
output,
PendingDef::Body(loc_pattern, loc_can_pattern, loc_expr),
)
} }
TypedBody(loc_pattern, loc_ann, loc_expr) => pending_typed_body( TypedBody(loc_pattern, loc_ann, loc_expr) => pending_typed_body(
env, env,
@ -1358,19 +1366,22 @@ fn to_pending_def<'a>(
region: loc_var.region, region: loc_var.region,
}); });
return PendingDef::InvalidAlias; return (Output::default(), PendingDef::InvalidAlias);
} }
} }
} }
PendingDef::Alias { (
name: Located { Output::default(),
region: name.region, PendingDef::Alias {
value: symbol, name: Located {
region: name.region,
value: symbol,
},
vars: can_rigids,
ann,
}, },
vars: can_rigids, )
ann,
}
} }
Err((original_region, loc_shadowed_symbol)) => { Err((original_region, loc_shadowed_symbol)) => {
@ -1379,7 +1390,7 @@ fn to_pending_def<'a>(
shadow: loc_shadowed_symbol, shadow: loc_shadowed_symbol,
}); });
PendingDef::InvalidAlias (Output::default(), PendingDef::InvalidAlias)
} }
} }
} }
@ -1398,9 +1409,9 @@ fn pending_typed_body<'a>(
var_store: &mut VarStore, var_store: &mut VarStore,
scope: &mut Scope, scope: &mut Scope,
pattern_type: PatternType, pattern_type: PatternType,
) -> PendingDef<'a> { ) -> (Output, PendingDef<'a>) {
// This takes care of checking for shadowing and adding idents to scope. // This takes care of checking for shadowing and adding idents to scope.
let loc_can_pattern = canonicalize_pattern( let (output, loc_can_pattern) = canonicalize_pattern(
env, env,
var_store, var_store,
scope, scope,
@ -1409,7 +1420,10 @@ fn pending_typed_body<'a>(
loc_pattern.region, loc_pattern.region,
); );
PendingDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr) (
output,
PendingDef::TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr),
)
} }
/// Make aliases recursive /// Make aliases recursive

View file

@ -427,9 +427,10 @@ pub fn canonicalize_expr<'a>(
let original_scope = scope; let original_scope = scope;
let mut scope = original_scope.clone(); let mut scope = original_scope.clone();
let mut can_args = Vec::with_capacity(loc_arg_patterns.len()); let mut can_args = Vec::with_capacity(loc_arg_patterns.len());
let mut output = Output::default();
for loc_pattern in loc_arg_patterns.into_iter() { for loc_pattern in loc_arg_patterns.into_iter() {
let can_arg = canonicalize_pattern( let (new_output, can_arg) = canonicalize_pattern(
env, env,
var_store, var_store,
&mut scope, &mut scope,
@ -438,16 +439,21 @@ pub fn canonicalize_expr<'a>(
loc_pattern.region, loc_pattern.region,
); );
output.union(new_output);
can_args.push((var_store.fresh(), can_arg)); can_args.push((var_store.fresh(), can_arg));
} }
let (loc_body_expr, mut output) = canonicalize_expr( let (loc_body_expr, new_output) = canonicalize_expr(
env, env,
var_store, var_store,
&mut scope, &mut scope,
loc_body_expr.region, loc_body_expr.region,
&loc_body_expr.value, &loc_body_expr.value,
); );
output.union(new_output);
// Now that we've collected all the references, check to see if any of the args we defined // Now that we've collected all the references, check to see if any of the args we defined
// went unreferenced. If any did, report them as unused arguments. // went unreferenced. If any did, report them as unused arguments.
for (sub_symbol, region) in scope.symbols() { for (sub_symbol, region) in scope.symbols() {
@ -713,14 +719,18 @@ fn canonicalize_when_branch<'a>(
// TODO report symbols not bound in all patterns // TODO report symbols not bound in all patterns
for loc_pattern in &branch.patterns { for loc_pattern in &branch.patterns {
patterns.push(canonicalize_pattern( let (new_output, can_pattern) = canonicalize_pattern(
env, env,
var_store, var_store,
&mut scope, &mut scope,
WhenBranch, WhenBranch,
&loc_pattern.value, &loc_pattern.value,
loc_pattern.region, loc_pattern.region,
)); );
output.union(new_output);
patterns.push(can_pattern);
} }
let (value, mut branch_output) = canonicalize_expr( let (value, mut branch_output) = canonicalize_expr(

View file

@ -1,5 +1,5 @@
use crate::env::Env; use crate::env::Env;
use crate::expr::{canonicalize_expr, Expr}; use crate::expr::{canonicalize_expr, Expr, Output};
use crate::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int}; use crate::num::{finish_parsing_base, finish_parsing_float, finish_parsing_int};
use crate::scope::Scope; use crate::scope::Scope;
use roc_module::ident::{Ident, Lowercase, TagName}; use roc_module::ident::{Ident, Lowercase, TagName};
@ -100,10 +100,11 @@ pub fn canonicalize_pattern<'a>(
pattern_type: PatternType, pattern_type: PatternType,
pattern: &ast::Pattern<'a>, pattern: &ast::Pattern<'a>,
region: Region, region: Region,
) -> Located<Pattern> { ) -> (Output, Located<Pattern>) {
use roc_parse::ast::Pattern::*; use roc_parse::ast::Pattern::*;
use PatternType::*; use PatternType::*;
let mut output = Output::default();
let can_pattern = match pattern { let can_pattern = match pattern {
Identifier(name) => match scope.introduce( Identifier(name) => match scope.introduce(
(*name).into(), (*name).into(),
@ -154,17 +155,18 @@ pub fn canonicalize_pattern<'a>(
let mut can_patterns = Vec::with_capacity(patterns.len()); let mut can_patterns = Vec::with_capacity(patterns.len());
for loc_pattern in *patterns { for loc_pattern in *patterns {
can_patterns.push(( let (new_output, can_pattern) = canonicalize_pattern(
var_store.fresh(), env,
canonicalize_pattern( var_store,
env, scope,
var_store, pattern_type,
scope, &loc_pattern.value,
pattern_type, loc_pattern.region,
&loc_pattern.value, );
loc_pattern.region,
), output.union(new_output);
));
can_patterns.push((var_store.fresh(), can_pattern));
} }
Pattern::AppliedTag { Pattern::AppliedTag {
@ -283,7 +285,7 @@ pub fn canonicalize_pattern<'a>(
RequiredField(label, loc_guard) => { RequiredField(label, loc_guard) => {
// a guard does not introduce the label into scope! // a guard does not introduce the label into scope!
let symbol = scope.ignore(label.into(), &mut env.ident_ids); let symbol = scope.ignore(label.into(), &mut env.ident_ids);
let can_guard = canonicalize_pattern( let (new_output, can_guard) = canonicalize_pattern(
env, env,
var_store, var_store,
scope, scope,
@ -292,6 +294,8 @@ pub fn canonicalize_pattern<'a>(
loc_guard.region, loc_guard.region,
); );
output.union(new_output);
destructs.push(Located { destructs.push(Located {
region: loc_pattern.region, region: loc_pattern.region,
value: RecordDestruct { value: RecordDestruct {
@ -311,8 +315,7 @@ pub fn canonicalize_pattern<'a>(
region, region,
) { ) {
Ok(symbol) => { Ok(symbol) => {
// TODO use output? let (can_default, expr_output) = canonicalize_expr(
let (can_default, _output) = canonicalize_expr(
env, env,
var_store, var_store,
scope, scope,
@ -320,6 +323,8 @@ pub fn canonicalize_pattern<'a>(
&loc_default.value, &loc_default.value,
); );
output.union(expr_output);
destructs.push(Located { destructs.push(Located {
region: loc_pattern.region, region: loc_pattern.region,
value: RecordDestruct { value: RecordDestruct {
@ -375,10 +380,13 @@ pub fn canonicalize_pattern<'a>(
} }
}; };
Located { (
region, output,
value: can_pattern, Located {
} region,
value: can_pattern,
},
)
} }
/// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't /// When we detect an unsupported pattern type (e.g. 5 = 1 + 2 is unsupported because you can't