From 667233a00d91ce713b98240efc0537639c530f3d Mon Sep 17 00:00:00 2001 From: Folkert Date: Fri, 3 Jul 2020 16:54:28 +0200 Subject: [PATCH] report error for invalid alias argument patterns --- compiler/can/src/def.rs | 20 +++++++---- compiler/problem/src/can.rs | 4 +++ compiler/reporting/src/error/canonicalize.rs | 15 +++++++++ compiler/reporting/tests/test_reporting.rs | 35 ++++++++++++++++++++ 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index d8194bef68..ce601ab80b 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -79,7 +79,10 @@ enum PendingDef<'a> { ann: &'a Located>, }, - ShadowedAlias, + /// An invalid alias, that is ignored in the rest of the pipeline + /// e.g. a shadowed alias, or a definition like `MyAlias 1 : Int` + /// with an incorrect pattern + InvalidAlias, } #[derive(Clone, Debug, PartialEq)] @@ -899,9 +902,8 @@ fn canonicalize_pending_def<'a>( .union(&can_ann.introduced_variables); } - ShadowedAlias => { - // Since this alias was shadowed, it gets ignored and has no - // effect on the output. + InvalidAlias => { + // invalid aliases (shadowed, incorrect patterns) get ignored } TypedBody(loc_pattern, loc_can_pattern, loc_ann, loc_expr) => { let ann = @@ -1365,7 +1367,13 @@ fn to_pending_def<'a>( }); } _ => { - panic!("TODO gracefully handle an invalid pattern appearing where a type alias rigid var should be."); + // any other pattern in this position is a syntax error. + env.problems.push(Problem::InvalidAliasRigid { + alias_name: symbol, + region: loc_var.region, + }); + + return PendingDef::InvalidAlias; } } } @@ -1386,7 +1394,7 @@ fn to_pending_def<'a>( shadow: loc_shadowed_symbol, }); - PendingDef::ShadowedAlias + PendingDef::InvalidAlias } } } diff --git a/compiler/problem/src/can.rs b/compiler/problem/src/can.rs index 3b37e40645..ca9d8cc9c8 100644 --- a/compiler/problem/src/can.rs +++ b/compiler/problem/src/can.rs @@ -50,6 +50,10 @@ pub enum Problem { annotation_pattern: Region, def_pattern: Region, }, + InvalidAliasRigid { + alias_name: Symbol, + region: Region, + }, } #[derive(Clone, Debug, PartialEq)] diff --git a/compiler/reporting/src/error/canonicalize.rs b/compiler/reporting/src/error/canonicalize.rs index 702980fc95..6979d64a75 100644 --- a/compiler/reporting/src/error/canonicalize.rs +++ b/compiler/reporting/src/error/canonicalize.rs @@ -247,6 +247,21 @@ pub fn can_problem<'b>( alloc.region(Region::span_across(annotation_pattern, def_pattern)), alloc.reflow("Is it a typo? If not, put either a newline or comment between them."), ]), + Problem::InvalidAliasRigid { alias_name, region } => alloc.stack(vec![ + alloc.concat(vec![ + alloc.reflow("This pattern in the definition of "), + alloc.symbol_unqualified(alias_name), + alloc.reflow(" is not what I expect:"), + ]), + alloc.region(region), + alloc.concat(vec![ + alloc.reflow("Only type variables like "), + alloc.type_variable("a".into()), + alloc.reflow(" or "), + alloc.type_variable("value".into()), + alloc.reflow(" can occur in this position."), + ]), + ]), Problem::RuntimeError(runtime_error) => pretty_runtime_error(alloc, runtime_error), }; diff --git a/compiler/reporting/tests/test_reporting.rs b/compiler/reporting/tests/test_reporting.rs index a1e6e182b4..df308521c7 100644 --- a/compiler/reporting/tests/test_reporting.rs +++ b/compiler/reporting/tests/test_reporting.rs @@ -2714,6 +2714,41 @@ mod test_reporting { ) } + #[test] + fn invalid_alias_rigid_var_pattern() { + report_problem_as( + indoc!( + r#" + MyAlias 1 : Int + + 4 + "# + ), + indoc!( + r#" + -- SYNTAX PROBLEM -------------------------------------------------------------- + + This pattern in the definition of `MyAlias` is not what I expect: + + 1 ┆ MyAlias 1 : Int + ┆ ^ + + Only type variables like `a` or `value` can occur in this position. + + -- SYNTAX PROBLEM -------------------------------------------------------------- + + `MyAlias` is not used anywhere in your code. + + 1 ┆ MyAlias 1 : Int + ┆ ^^^^^^^^^^^^^^^ + + If you didn't intend on using `MyAlias` then remove it so future readers + of your code don't wonder why it is there. + "# + ), + ) + } + #[test] fn invalid_num() { report_problem_as(