mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
parent
8f1878bc42
commit
817bb22f9e
3 changed files with 86 additions and 16 deletions
|
@ -4,7 +4,7 @@ use roc_collections::all::{MutMap, MutSet};
|
|||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
|
||||
static WILDCARD: &str = "*";
|
||||
pub static WILDCARD: &str = "*";
|
||||
static EMPTY_RECORD: &str = "{}";
|
||||
static EMPTY_TAG_UNION: &str = "[]";
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use roc_module::ident::{Ident, IdentStr, Lowercase, TagName};
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_solve::solve;
|
||||
use roc_types::pretty_print::Parens;
|
||||
use roc_types::pretty_print::{Parens, WILDCARD};
|
||||
use roc_types::types::{Category, ErrorType, PatternCategory, Reason, RecordField, TypeExt};
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
@ -355,18 +355,44 @@ fn to_expr_report<'b>(
|
|||
TypedBody { .. } => "The body is".into(),
|
||||
};
|
||||
|
||||
let comparison = type_comparison(
|
||||
let i_am_seeing = add_category(alloc, alloc.text(it_is), &category);
|
||||
|
||||
// TODO: can comparisons between wildcards happen outside the context of an annotation?
|
||||
let comparison = if is_wildcards_comparison(&found, &expected_type) {
|
||||
alloc.stack(vec![
|
||||
i_am_seeing,
|
||||
alloc.type_block(to_doc(alloc, Parens::Unnecessary, found)),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("But the type annotation on "),
|
||||
on_name_text,
|
||||
alloc.reflow(" says it should be a "),
|
||||
alloc.type_str(WILDCARD),
|
||||
alloc.reflow(" too! This tells me that the type is connected in a way that doesn't require a wildcard."),
|
||||
]),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("Since the type has to be the same in both places, the type can be more specific than "),
|
||||
alloc.type_str(WILDCARD),
|
||||
alloc.reflow(". You can change the "),
|
||||
alloc.type_str(WILDCARD),
|
||||
alloc.reflow(" to a named type variable like "),
|
||||
alloc.type_variable("a".into()),
|
||||
alloc.reflow(" to reflect the connection.")
|
||||
]),
|
||||
])
|
||||
} else {
|
||||
type_comparison(
|
||||
alloc,
|
||||
found,
|
||||
expected_type,
|
||||
add_category(alloc, alloc.text(it_is), &category),
|
||||
i_am_seeing,
|
||||
alloc.concat(vec![
|
||||
alloc.text("But the type annotation"),
|
||||
on_name_text,
|
||||
alloc.text(" says it should be:"),
|
||||
]),
|
||||
None,
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
Report {
|
||||
title: "TYPE MISMATCH".to_string(),
|
||||
|
@ -891,6 +917,14 @@ fn to_expr_report<'b>(
|
|||
}
|
||||
}
|
||||
|
||||
fn is_wildcards_comparison(type1: &ErrorType, type2: &ErrorType) -> bool {
|
||||
use ErrorType::*;
|
||||
match (type1, type2) {
|
||||
(RigidVar(v1), RigidVar(v2)) if v1.as_str() == WILDCARD && v2.as_str() == WILDCARD => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn count_arguments(tipe: &ErrorType) -> usize {
|
||||
use ErrorType::*;
|
||||
|
||||
|
|
|
@ -6761,8 +6761,44 @@ I need all branches in an `if` to have the same type!
|
|||
|
||||
Tip: Your type annotation uses `a` and `b` as separate type variables.
|
||||
Your code seems to be saying they are the same though. Maybe they
|
||||
should be the same your type annotation? Maybe your code uses them in
|
||||
a weird way?
|
||||
should be the same in your type annotation? Maybe your code uses them
|
||||
in a weird way?
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn error_wildcards_are_related() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
f : * -> *
|
||||
f = \x -> x
|
||||
|
||||
f
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||
|
||||
Something is off with the body of the `f` definition:
|
||||
|
||||
1│ f : * -> *
|
||||
2│ f = \x -> x
|
||||
^
|
||||
|
||||
This `x` value is a:
|
||||
|
||||
*
|
||||
|
||||
But the type annotation on on `f` says it should be a * too! This tells
|
||||
me that the type is connected in a way that doesn't require a
|
||||
wildcard.
|
||||
|
||||
Since the type has to be the same in both places, the type can be more
|
||||
specific than *. You can change the * to a named type variable like `a`
|
||||
to reflect the connection.
|
||||
"#
|
||||
),
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue