From 5c81b46d1c8077db5a6a815d5a538ef097a0699d Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 2 Jul 2020 23:22:55 +0200 Subject: [PATCH 1/3] remove clone --- compiler/types/src/pretty_print.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/types/src/pretty_print.rs b/compiler/types/src/pretty_print.rs index 6482090a43..bf8b018285 100644 --- a/compiler/types/src/pretty_print.rs +++ b/compiler/types/src/pretty_print.rs @@ -211,7 +211,7 @@ pub fn name_all_type_vars(variable: Variable, subs: &mut Subs) { for root in roots { // show the type variable number instead of `*`. useful for debugging - // set_root_name(root, &(format!("<{:?}>", root).into()), subs); + // set_root_name(root, (format!("<{:?}>", root).into()), subs); if let Some(Appearances::Multiple) = appearances.get(&root) { letters_used = name_root(letters_used, root, subs, &mut taken); } @@ -226,21 +226,19 @@ fn name_root( ) -> u32 { let (generated_name, new_letters_used) = name_type_var(letters_used, taken); - set_root_name(root, &generated_name, subs); + set_root_name(root, generated_name, subs); new_letters_used } -fn set_root_name(root: Variable, name: &Lowercase, subs: &mut Subs) { +fn set_root_name(root: Variable, name: Lowercase, subs: &mut Subs) { use crate::subs::Content::*; let mut descriptor = subs.get_without_compacting(root); match descriptor.content { FlexVar(None) => { - descriptor.content = FlexVar(Some(name.clone())); - - // TODO is this necessary, or was mutating descriptor in place sufficient? + descriptor.content = FlexVar(Some(name)); subs.set(root, descriptor); } FlexVar(Some(_existing)) => { From 0cfb16c7d52175f14e435ecf4cf928c38543b081 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 2 Jul 2020 23:24:10 +0200 Subject: [PATCH 2/3] implement canonicalization error when signature pattern does not match definition pattern. --- compiler/can/src/def.rs | 10 ++++++- compiler/problem/src/can.rs | 4 +++ compiler/reporting/src/error/canonicalize.rs | 14 ++++++++++ compiler/reporting/tests/test_reporting.rs | 28 ++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index 392974852b..d8194bef68 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -168,7 +168,15 @@ pub fn canonicalize_defs<'a>( pattern_type, ) } else { - panic!("TODO gracefully handle the case where a type annotation appears immediately before a body def, but the patterns are different. This should be an error; put a newline or comment between them!"); + // the pattern of the annotation does not match the pattern of the body directly below it + env.problems.push(Problem::SignatureDefMismatch { + annotation_pattern: pattern.region, + def_pattern: body_pattern.region, + }); + + // both the annotation and definition are skipped! + iter.next(); + continue; } } _ => to_pending_def(env, var_store, &loc_def.value, &mut scope, pattern_type), diff --git a/compiler/problem/src/can.rs b/compiler/problem/src/can.rs index 5f83be28b0..3b37e40645 100644 --- a/compiler/problem/src/can.rs +++ b/compiler/problem/src/can.rs @@ -46,6 +46,10 @@ pub enum Problem { replaced_region: Region, }, RuntimeError(RuntimeError), + SignatureDefMismatch { + annotation_pattern: Region, + def_pattern: Region, + }, } #[derive(Clone, Debug, PartialEq)] diff --git a/compiler/reporting/src/error/canonicalize.rs b/compiler/reporting/src/error/canonicalize.rs index 9710ab32d5..4a97ec2e66 100644 --- a/compiler/reporting/src/error/canonicalize.rs +++ b/compiler/reporting/src/error/canonicalize.rs @@ -1,6 +1,7 @@ use roc_collections::all::MutSet; use roc_problem::can::PrecedenceProblem::BothNonAssociative; use roc_problem::can::{Problem, RuntimeError}; +use roc_region::all::Region; use std::path::PathBuf; use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder}; @@ -238,6 +239,19 @@ pub fn can_problem<'b>( alloc.reflow(" definitions from this tag union type."), ]), ]), + Problem::SignatureDefMismatch { + ref annotation_pattern, + ref def_pattern, + } => alloc.stack(vec![ + alloc.reflow("This annotation does not match the definition immediately following it:"), + 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."), + // TODO add link to this guide section + // alloc.hint().append(alloc.reflow( + // "If you want an unused type parameter (a so-called \"phantom type\"), \ + // read the guide section on phantom data.", + // )), + ]), 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 90f7959672..2fb67fc285 100644 --- a/compiler/reporting/tests/test_reporting.rs +++ b/compiler/reporting/tests/test_reporting.rs @@ -2684,6 +2684,34 @@ mod test_reporting { ) } + #[test] + fn annotation_definition_mismatch() { + report_problem_as( + indoc!( + r#" + bar : Int + foo = \x -> x + + # NOTE: neither bar or foo are defined at this point + 4 + "# + ), + indoc!( + r#" + -- SYNTAX PROBLEM -------------------------------------------------------------- + + This annotation does not match the definition immediately following + it: + + 1 ┆> bar : Int + 2 ┆> foo = \x -> x + + Is it a typo? If not, put either a newline or comment between them. + "# + ), + ) + } + #[test] fn invalid_num() { report_problem_as( From 53c5297aac9b387a9d84b963b43125ab380195f5 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 2 Jul 2020 23:26:24 +0200 Subject: [PATCH 3/3] cleanup comment --- compiler/reporting/src/error/canonicalize.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/reporting/src/error/canonicalize.rs b/compiler/reporting/src/error/canonicalize.rs index 4a97ec2e66..702980fc95 100644 --- a/compiler/reporting/src/error/canonicalize.rs +++ b/compiler/reporting/src/error/canonicalize.rs @@ -246,11 +246,6 @@ pub fn can_problem<'b>( alloc.reflow("This annotation does not match the definition immediately following it:"), 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."), - // TODO add link to this guide section - // alloc.hint().append(alloc.reflow( - // "If you want an unused type parameter (a so-called \"phantom type\"), \ - // read the guide section on phantom data.", - // )), ]), Problem::RuntimeError(runtime_error) => pretty_runtime_error(alloc, runtime_error), };