diff --git a/compiler/constrain/src/expr.rs b/compiler/constrain/src/expr.rs index 51ca5b1cbc..cbce2021ce 100644 --- a/compiler/constrain/src/expr.rs +++ b/compiler/constrain/src/expr.rs @@ -718,7 +718,7 @@ pub fn constrain_expr( Box::new(Type::Variable(*ext_var)), ), expected.clone(), - Category::TagUnion, + Category::TagApply(name.clone()), region, ); let ast_con = Eq( diff --git a/compiler/constrain/src/uniq.rs b/compiler/constrain/src/uniq.rs index 77cc1fc790..38bdf328ab 100644 --- a/compiler/constrain/src/uniq.rs +++ b/compiler/constrain/src/uniq.rs @@ -559,11 +559,16 @@ pub fn constrain_expr( ), ); - let union_con = Eq(union_type, expected.clone(), Category::TagUnion, region); + let union_con = Eq( + union_type, + expected.clone(), + Category::TagApply(name.clone()), + region, + ); let ast_con = Eq( Type::Variable(*variant_var), expected, - Category::TagUnion, + Category::TagApply(name.clone()), region, ); diff --git a/compiler/reporting/src/report.rs b/compiler/reporting/src/report.rs index 7b8c853f16..9ecefc7ff8 100644 --- a/compiler/reporting/src/report.rs +++ b/compiler/reporting/src/report.rs @@ -174,6 +174,12 @@ pub enum ReportText { /// A global tag rendered as code (e.g. a monospace font, or with backticks around it). GlobalTag(Box), + /// A private tag rendered as code (e.g. a monospace font, or with backticks around it). + PrivateTag(Symbol), + + /// A record field name rendered as code (e.g. a monospace font, or with backticks around it). + RecordField(Box), + /// A language keyword like `if`, rendered as code (e.g. a monospace font, or with backticks around it). Keyword(Box), @@ -205,10 +211,18 @@ pub fn em_text(str: &str) -> ReportText { ReportText::EmText(Box::from(str)) } +pub fn private_tag_text(symbol: Symbol) -> ReportText { + ReportText::PrivateTag(symbol) +} + pub fn global_tag_text(str: &str) -> ReportText { ReportText::GlobalTag(Box::from(str)) } +pub fn record_field_text(str: &str) -> ReportText { + ReportText::RecordField(Box::from(str)) +} + pub fn keyword_text(str: &str) -> ReportText { ReportText::Keyword(Box::from(str)) } @@ -323,12 +337,19 @@ impl ReportText { buf.push_str(&string); buf.push('`'); } + RecordField(string) => { + // Since this is CI, the best we can do for code text is backticks. + buf.push('`'); + buf.push('.'); + buf.push_str(&string); + buf.push('`'); + } Url(url) => { buf.push('<'); buf.push_str(&url); buf.push('>'); } - Value(symbol) => { + PrivateTag(symbol) | Value(symbol) => { if symbol.module_id() == env.home { // Render it unqualified if it's in the current module. buf.push_str(symbol.ident_string(env.interns)); diff --git a/compiler/reporting/src/type_error.rs b/compiler/reporting/src/type_error.rs index e13d98e495..9f53f175b0 100644 --- a/compiler/reporting/src/type_error.rs +++ b/compiler/reporting/src/type_error.rs @@ -1,4 +1,7 @@ -use crate::report::{global_tag_text, keyword_text, plain_text, with_indent, Report, ReportText}; +use crate::report::{ + global_tag_text, keyword_text, plain_text, private_tag_text, record_field_text, with_indent, + Report, ReportText, +}; use roc_can::expected::{Expected, PExpected}; use roc_module::symbol::Symbol; use roc_solve::solve; @@ -275,13 +278,72 @@ fn lone_type( } fn add_category(this_is: ReportText, category: &Category) -> ReportText { + use roc_module::ident::TagName; use Category::*; use ReportText::*; match category { + Lookup(name) => Concat(vec![ + plain_text("This "), + Value(*name), + plain_text(" value is a"), + ]), + + If => Concat(vec![ + plain_text("This "), + keyword_text("if"), + plain_text("expression produces"), + ]), + When => Concat(vec![ + plain_text("This "), + keyword_text("when"), + plain_text("expression produces"), + ]), + + List => Concat(vec![this_is, plain_text("a list of type")]), + Num => Concat(vec![this_is, plain_text("a number of type")]), + Int => Concat(vec![this_is, plain_text("an integer of type")]), + Float => Concat(vec![this_is, plain_text("a float of type")]), Str => Concat(vec![this_is, plain_text(" a string of type")]), + + Lambda => Concat(vec![this_is, plain_text("an anonymous function of type")]), + + TagApply(TagName::Global(name)) => Concat(vec![ + plain_text("This "), + global_tag_text(name.as_str()), + plain_text(" global tag application produces"), + ]), + TagApply(TagName::Private(name)) => Concat(vec![ + plain_text("This "), + private_tag_text(*name), + plain_text(" private tag application produces"), + ]), + + Record => Concat(vec![this_is, plain_text("a record of type")]), + + Accessor(field) => Concat(vec![ + plain_text("This "), + record_field_text(field.as_str()), + plain_text(" value is a"), + ]), + Access(field) => Concat(vec![ + plain_text("The value at "), + record_field_text(field.as_str()), + plain_text(" is a"), + ]), + + CallResult(Some(symbol)) => Concat(vec![ + plain_text("This "), + Value(*symbol), + plain_text(" call produces"), + ]), + CallResult(None) => Concat(vec![this_is]), + + Uniqueness => Concat(vec![ + this_is, + plain_text(" an uniqueness attribute of type"), + ]), Storage => Concat(vec![this_is, plain_text(" a value of type")]), - other => todo!("add_category for {:?}", other), } } diff --git a/compiler/types/src/types.rs b/compiler/types/src/types.rs index 36bd30178e..3ee5bad08c 100644 --- a/compiler/types/src/types.rs +++ b/compiler/types/src/types.rs @@ -637,6 +637,7 @@ pub enum Reason { pub enum Category { Lookup(Symbol), CallResult(Option), + TagApply(TagName), Lambda, Uniqueness, @@ -651,7 +652,6 @@ pub enum Category { Float, Int, Num, - TagUnion, List, Str,