elem_in_list

This commit is contained in:
Folkert 2020-04-04 16:38:41 +02:00
parent 200adae507
commit f8b3d5dce7
5 changed files with 63 additions and 8 deletions

View file

@ -202,9 +202,12 @@ pub fn constrain_expr(
let list_elem_type = Type::Variable(*elem_var); let list_elem_type = Type::Variable(*elem_var);
let mut constraints = Vec::with_capacity(1 + loc_elems.len()); let mut constraints = Vec::with_capacity(1 + loc_elems.len());
for loc_elem in loc_elems { for (index, loc_elem) in loc_elems.iter().enumerate() {
let elem_expected = let elem_expected = ForReason(
ForReason(Reason::ElemInList, list_elem_type.clone(), region); Reason::ElemInList { index },
list_elem_type.clone(),
loc_elem.region,
);
let constraint = let constraint =
constrain_expr(env, loc_elem.region, &loc_elem.value, elem_expected); constrain_expr(env, loc_elem.region, &loc_elem.value, elem_expected);

View file

@ -596,9 +596,12 @@ pub fn constrain_expr(
let entry_type = Type::Variable(*elem_var); let entry_type = Type::Variable(*elem_var);
let mut constraints = Vec::with_capacity(1 + loc_elems.len()); let mut constraints = Vec::with_capacity(1 + loc_elems.len());
for loc_elem in loc_elems.iter() { for (index, loc_elem) in loc_elems.iter().enumerate() {
let elem_expected = let elem_expected = Expected::ForReason(
Expected::ForReason(Reason::ElemInList, entry_type.clone(), region); Reason::ElemInList { index },
entry_type.clone(),
region,
);
let constraint = constrain_expr( let constraint = constrain_expr(
env, env,
var_store, var_store,

View file

@ -277,6 +277,27 @@ fn to_expr_report(
]), ]),
) )
} }
Reason::ElemInList { index } => {
// NOTE: is 0-based
let ith = int_to_ordinal(index + 1);
report_mismatch(
filename,
&category,
found,
expected_type,
region,
Some(expr_region),
plain_text(&format!(
"The {} element of this list does not match all the previous elements",
ith
)),
plain_text(&format!("The {} element is ", ith)),
plain_text("but all the previous elements in the list have type"),
plain_text("instead. I need all elements of a list to have the same type!"),
)
}
other => { other => {
// AnonymousFnArg { arg_index: u8 }, // AnonymousFnArg { arg_index: u8 },
// NamedFnArg(String /* function name */, u8 /* arg index */), // NamedFnArg(String /* function name */, u8 /* arg index */),
@ -288,7 +309,6 @@ fn to_expr_report(
// IntLiteral, // IntLiteral,
// NumLiteral, // NumLiteral,
// InterpolatedStringVar, // InterpolatedStringVar,
// ElemInList,
// RecordUpdateValue(Lowercase), // RecordUpdateValue(Lowercase),
// RecordUpdateKeys(Symbol, SendMap<Lowercase, Type>), // RecordUpdateKeys(Symbol, SendMap<Lowercase, Type>),
todo!("I don't have a message yet for reason {:?}", other) todo!("I don't have a message yet for reason {:?}", other)

View file

@ -899,6 +899,35 @@ mod test_reporting {
) )
} }
#[test]
fn elem_in_list() {
report_problem_as(
indoc!(
r#"
[ 1, 3, "foo" ]
"#
),
indoc!(
r#"
The 3rd element of this list does not match all the previous elements
1 [ 1, 3, "foo" ]
^^^^^
The 3rd element is a string of type
Str
but all the previous elements in the list have type
Num a
instead. I need all elements of a list to have the same type!
"#
),
)
}
#[test] #[test]
fn circular_type() { fn circular_type() {
report_problem_as( report_problem_as(

View file

@ -628,7 +628,7 @@ pub enum Reason {
WhenGuard, WhenGuard,
IfCondition, IfCondition,
IfBranch { index: usize, total_branches: usize }, IfBranch { index: usize, total_branches: usize },
ElemInList, ElemInList { index: usize },
RecordUpdateValue(Lowercase), RecordUpdateValue(Lowercase),
RecordUpdateKeys(Symbol, SendMap<Lowercase, Type>), RecordUpdateKeys(Symbol, SendMap<Lowercase, Type>),
} }