From b68192327081e1b61dbc77f538248f42b5c07231 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 21 Mar 2021 22:52:23 +0100 Subject: [PATCH 1/3] report malformed type names in annotations --- compiler/can/src/annotation.rs | 28 +++- compiler/problem/src/can.rs | 1 + compiler/reporting/src/error/canonicalize.rs | 16 ++- compiler/reporting/tests/test_reporting.rs | 134 +++++++++++++------ 4 files changed, 129 insertions(+), 50 deletions(-) diff --git a/compiler/can/src/annotation.rs b/compiler/can/src/annotation.rs index f9db76ab05..f7ec5dd547 100644 --- a/compiler/can/src/annotation.rs +++ b/compiler/can/src/annotation.rs @@ -65,6 +65,13 @@ impl IntroducedVariables { } } +fn malformed(env: &mut Env, region: Region, name: &str) { + use roc_problem::can::RuntimeError::*; + + let problem = MalformedTypeName((*name).into(), region); + env.problem(roc_problem::can::Problem::RuntimeError(problem.clone())); +} + pub fn canonicalize_annotation( env: &mut Env, scope: &mut Scope, @@ -446,7 +453,16 @@ fn can_annotation_help( local_aliases, references, ), - Wildcard | Malformed(_) => { + Wildcard => { + let var = var_store.fresh(); + + introduced_variables.insert_wildcard(var); + + Type::Variable(var) + } + Malformed(string) => { + malformed(env, region, string); + let var = var_store.fresh(); introduced_variables.insert_wildcard(var); @@ -542,8 +558,9 @@ fn can_assigned_fields<'a>( field = nested; continue 'inner; } - Malformed(_) => { - // TODO report this? + Malformed(string) => { + malformed(env, region, string); + // completely skip this element, advance to the next tag continue 'outer; } @@ -645,8 +662,9 @@ fn can_tags<'a>( tag = nested; continue 'inner; } - Tag::Malformed(_) => { - // TODO report this? + Tag::Malformed(string) => { + malformed(env, region, string); + // completely skip this element, advance to the next tag continue 'outer; } diff --git a/compiler/problem/src/can.rs b/compiler/problem/src/can.rs index f28d3b1c5e..6fc5c086aa 100644 --- a/compiler/problem/src/can.rs +++ b/compiler/problem/src/can.rs @@ -134,6 +134,7 @@ pub enum RuntimeError { }, InvalidPrecedence(PrecedenceProblem, Region), MalformedIdentifier(Box, roc_parse::ident::BadIdent, Region), + MalformedTypeName(Box, Region), MalformedClosure(Region), InvalidRecordUpdate { region: Region, diff --git a/compiler/reporting/src/error/canonicalize.rs b/compiler/reporting/src/error/canonicalize.rs index 9ccd46c4c0..452b60e46c 100644 --- a/compiler/reporting/src/error/canonicalize.rs +++ b/compiler/reporting/src/error/canonicalize.rs @@ -776,8 +776,20 @@ fn pretty_runtime_error<'b>( } RuntimeError::MalformedIdentifier(_box_str, bad_ident, surroundings) => { to_bad_ident_expr_report(alloc, bad_ident, surroundings) - - + } + RuntimeError::MalformedTypeName(_box_str, surroundings) => { + alloc.stack(vec![ + alloc.reflow(r"I am confused by this type name:"), + alloc.region(surroundings), + alloc.concat(vec![ + alloc.reflow("Type names start with an uppercase letter, "), + alloc.reflow("and can optionally be qualified by a module name, like "), + alloc.parser_suggestion("Bool"), + alloc.reflow(" or "), + alloc.parser_suggestion("Http.Request.Request"), + alloc.reflow("."), + ]), + ]) } RuntimeError::MalformedClosure(_) => todo!(""), RuntimeError::InvalidFloat(sign @ FloatErrorKind::PositiveInfinity, region, _raw_str) diff --git a/compiler/reporting/tests/test_reporting.rs b/compiler/reporting/tests/test_reporting.rs index f86d7909d4..d6430cab2f 100644 --- a/compiler/reporting/tests/test_reporting.rs +++ b/compiler/reporting/tests/test_reporting.rs @@ -3265,20 +3265,20 @@ mod test_reporting { indoc!( r#" ── TYPE MISMATCH ─────────────────────────────────────────────────────────────── - + Something is off with the body of the `x` definition: - + 4│ x : AList I64 I64 5│ x = ACons 0 (BCons 1 (ACons "foo" BNil )) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - + This `ACons` global tag application has the type: - + [ ACons Num (Integer Signed64) [ BCons (Num a) [ ACons Str [ BNil ]b ]c ]d, ANil ] - + But the type annotation on `x` says it should be: - + [ ACons I64 BList I64 I64, ANil ] "# ), @@ -4155,12 +4155,12 @@ mod test_reporting { indoc!( r#" ── UNKNOWN OPERATOR ──────────────────────────────────────────────────────────── - + This looks like an operator, but it's not one I recognize! - + 1│ f :: I64 ^^ - + I have no specific suggestion for this operator, see TODO for the full list of operators in Roc. "# @@ -4188,12 +4188,12 @@ mod test_reporting { indoc!( r#" ── TOO MANY ARGS ─────────────────────────────────────────────────────────────── - + This value is not a function, but it was given 3 arguments: - + 3│ x == 5 ^ - + Are there any missing commas? Or missing parentheses? "# ), @@ -4476,12 +4476,12 @@ mod test_reporting { indoc!( r#" ── TAB CHARACTER ─────────────────────────────────────────────────────────────── - + I encountered a tab character - - 1│ # comment with a + + 1│ # comment with a ^ - + Tab characters are not allowed. "# ), @@ -4500,9 +4500,9 @@ mod test_reporting { indoc!( r#" ── BAD TYPE VARIABLE ─────────────────────────────────────────────────────────── - + I am expecting a type variable, but I got stuck here: - + 1│ f : ( ^ "# @@ -4545,7 +4545,19 @@ mod test_reporting { f "# ), - indoc!(r#""#), + indoc!( + r#" + ── SYNTAX PROBLEM ────────────────────────────────────────────────────────────── + + I am confused by this type name: + + 1│ f : Foo..Bar + ^^^^^^^^ + + Type names start with an uppercase letter, and can optionally be + qualified by a module name, like Bool or Http.Request.Request. + "# + ), ) // ── DOUBLE DOT ────────────────────────────────────────────────────────────────── @@ -4568,7 +4580,19 @@ mod test_reporting { f "# ), - indoc!(r#""#), + indoc!( + r#" + ── SYNTAX PROBLEM ────────────────────────────────────────────────────────────── + + I am confused by this type name: + + 1│ f : Foo.Bar. + ^^^^^^^^ + + Type names start with an uppercase letter, and can optionally be + qualified by a module name, like Bool or Http.Request.Request. + "# + ), ) // ── TRAILING DOT ──────────────────────────────────────────────────────────────── @@ -4619,7 +4643,19 @@ mod test_reporting { f "# ), - indoc!(r#""#), + indoc!( + r#" + ── SYNTAX PROBLEM ────────────────────────────────────────────────────────────── + + I am confused by this type name: + + 1│ f : Foo.1 + ^^^^^ + + Type names start with an uppercase letter, and can optionally be + qualified by a module name, like Bool or Http.Request.Request. + "# + ), ) // ── WEIRD QUALIFIED NAME ──────────────────────────────────────────────────────── @@ -4643,7 +4679,19 @@ mod test_reporting { f "# ), - indoc!(r#""#), + indoc!( + r#" + ── SYNTAX PROBLEM ────────────────────────────────────────────────────────────── + + I am confused by this type name: + + 1│ f : Foo.foo + ^^^^^^^ + + Type names start with an uppercase letter, and can optionally be + qualified by a module name, like Bool or Http.Request.Request. + "# + ), ) } @@ -4658,19 +4706,19 @@ mod test_reporting { indoc!( r#" ── MISSING FINAL EXPRESSION ──────────────────────────────────────────────────── - + I am partway through parsing a definition's final expression, but I got stuck here: - + 1│ f : Foo.foo ^ - + This definition is missing a final expression. A nested definition must be followed by either another definition, or an expression - + x = 4 y = 2 - + x + y "# ), @@ -4973,13 +5021,13 @@ mod test_reporting { indoc!( r#" ── MISSING EXPRESSION ────────────────────────────────────────────────────────── - + I am partway through parsing a definition, but I got stuck here: - + 1│ when Just 4 is 2│ Just when -> ^ - + I was expecting to see an expression like 42 or "hello". "# ), @@ -5646,14 +5694,14 @@ mod test_reporting { indoc!( r#" ── SYNTAX PROBLEM ────────────────────────────────────────────────────────────── - + I cannot find a `bar` value - + 1│ [ "foo", bar("") ] ^^^ - + these names seem close though: - + Nat Str U8 @@ -5729,16 +5777,16 @@ mod test_reporting { indoc!( r#" ── UNKNOWN OPERATOR ──────────────────────────────────────────────────────────── - + This looks like an operator, but it's not one I recognize! - + 1│ main = 2│ (\x -> x) : I64 ^ - + The has-type operator : can only occur in a definition's type signature, like - + increment : I64 -> I64 increment = \x -> x + 1 "# @@ -5759,19 +5807,19 @@ mod test_reporting { indoc!( r#" ── MISSING FINAL EXPRESSION ──────────────────────────────────────────────────── - + I am partway through parsing a definition's final expression, but I got stuck here: - + 1│ main = 5 -> 3 ^ - + This definition is missing a final expression. A nested definition must be followed by either another definition, or an expression - + x = 4 y = 2 - + x + y "# ), From 03a90faa37a399a60bfec710a827ef64e115bb1c Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 21 Mar 2021 22:53:05 +0100 Subject: [PATCH 2/3] clippy --- compiler/can/src/annotation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/can/src/annotation.rs b/compiler/can/src/annotation.rs index f7ec5dd547..1dae84e6c9 100644 --- a/compiler/can/src/annotation.rs +++ b/compiler/can/src/annotation.rs @@ -69,7 +69,7 @@ fn malformed(env: &mut Env, region: Region, name: &str) { use roc_problem::can::RuntimeError::*; let problem = MalformedTypeName((*name).into(), region); - env.problem(roc_problem::can::Problem::RuntimeError(problem.clone())); + env.problem(roc_problem::can::Problem::RuntimeError(problem)); } pub fn canonicalize_annotation( From 5bbea3510f0e6b158a26722a4b5e60d7c4270bcd Mon Sep 17 00:00:00 2001 From: Folkert Date: Sun, 21 Mar 2021 23:42:34 +0100 Subject: [PATCH 3/3] fix tab case --- compiler/reporting/tests/test_reporting.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/reporting/tests/test_reporting.rs b/compiler/reporting/tests/test_reporting.rs index d6430cab2f..ee2af9e6bf 100644 --- a/compiler/reporting/tests/test_reporting.rs +++ b/compiler/reporting/tests/test_reporting.rs @@ -4474,16 +4474,16 @@ mod test_reporting { report_problem_as( "# comment with a \t\n4", indoc!( - r#" + " ── TAB CHARACTER ─────────────────────────────────────────────────────────────── I encountered a tab character - 1│ # comment with a + 1│ # comment with a \t ^ Tab characters are not allowed. - "# + " ), ) }