mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 00:09:33 +03:00
Include floats in bounds for unspecified numbers
This commit is contained in:
parent
3fffca48bb
commit
c5d918e68c
@ -76,7 +76,7 @@ pub fn expr_to_expr2<'a>(
|
||||
}
|
||||
Num(string) => {
|
||||
match finish_parsing_num(string) {
|
||||
Ok(ParsedNumResult::UnknownNum(int) | ParsedNumResult::Int(int, _)) => {
|
||||
Ok(ParsedNumResult::UnknownNum(int, _) | ParsedNumResult::Int(int, _)) => {
|
||||
let expr = Expr2::SmallInt {
|
||||
number: IntVal::I64(match int {
|
||||
IntValue::U128(_) => todo!(),
|
||||
|
@ -196,7 +196,7 @@ pub fn to_pattern2<'a>(
|
||||
let problem = MalformedPatternProblem::MalformedInt;
|
||||
malformed_pattern(env, problem, region)
|
||||
}
|
||||
Ok(ParsedNumResult::UnknownNum(int)) => {
|
||||
Ok(ParsedNumResult::UnknownNum(int, _bound)) => {
|
||||
Pattern2::NumLiteral(
|
||||
env.var_store.fresh(),
|
||||
match int {
|
||||
|
@ -17,8 +17,8 @@ pub fn num_expr_from_result(
|
||||
env: &mut Env,
|
||||
) -> Expr {
|
||||
match result {
|
||||
Ok((str, ParsedNumResult::UnknownNum(num))) => {
|
||||
Expr::Num(var_store.fresh(), (*str).into(), num, NumericBound::None)
|
||||
Ok((str, ParsedNumResult::UnknownNum(num, bound))) => {
|
||||
Expr::Num(var_store.fresh(), (*str).into(), num, bound)
|
||||
}
|
||||
Ok((str, ParsedNumResult::Int(num, bound))) => Expr::Int(
|
||||
var_store.fresh(),
|
||||
@ -103,27 +103,14 @@ pub fn float_expr_from_result(
|
||||
pub enum ParsedNumResult {
|
||||
Int(IntValue, IntBound),
|
||||
Float(f64, FloatBound),
|
||||
UnknownNum(IntValue),
|
||||
UnknownNum(IntValue, NumericBound),
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn finish_parsing_num(raw: &str) -> Result<ParsedNumResult, (&str, IntErrorKind)> {
|
||||
// Ignore underscores.
|
||||
let radix = 10;
|
||||
let (num, bound) =
|
||||
from_str_radix(raw.replace("_", "").as_str(), radix).map_err(|e| (raw, e))?;
|
||||
// Let's try to specialize the number
|
||||
Ok(match bound {
|
||||
NumericBound::None => ParsedNumResult::UnknownNum(num),
|
||||
NumericBound::Int(ib) => ParsedNumResult::Int(num, ib),
|
||||
NumericBound::Float(fb) => {
|
||||
let num = match num {
|
||||
IntValue::I128(n) => n as f64,
|
||||
IntValue::U128(n) => n as f64,
|
||||
};
|
||||
ParsedNumResult::Float(num, fb)
|
||||
}
|
||||
})
|
||||
from_str_radix(raw.replace("_", "").as_str(), radix).map_err(|e| (raw, e))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -145,13 +132,13 @@ pub fn finish_parsing_base(
|
||||
} else {
|
||||
from_str_radix(raw.replace("_", "").as_str(), radix)
|
||||
})
|
||||
.and_then(|(n, bound)| {
|
||||
let bound = match bound {
|
||||
NumericBound::None => IntBound::None,
|
||||
NumericBound::Int(ib) => ib,
|
||||
NumericBound::Float(_) => return Err(IntErrorKind::FloatSuffix),
|
||||
};
|
||||
Ok((n, bound))
|
||||
.and_then(|parsed| match parsed {
|
||||
ParsedNumResult::Float(..) => return Err(IntErrorKind::FloatSuffix),
|
||||
ParsedNumResult::Int(val, bound) => Ok((val, bound)),
|
||||
ParsedNumResult::UnknownNum(val, NumericBound::None) => Ok((val, IntBound::None)),
|
||||
ParsedNumResult::UnknownNum(val, NumericBound::AtLeastIntOrFloat { sign, width }) => {
|
||||
Ok((val, IntBound::AtLeast { sign, width }))
|
||||
}
|
||||
})
|
||||
.map_err(|e| (raw, e))
|
||||
}
|
||||
@ -223,7 +210,7 @@ fn parse_literal_suffix(num_str: &str) -> (Option<ParsedWidth>, &str) {
|
||||
/// the LEGAL_DETAILS file in the root directory of this distribution.
|
||||
///
|
||||
/// Thanks to the Rust project and its contributors!
|
||||
fn from_str_radix(src: &str, radix: u32) -> Result<(IntValue, NumericBound), IntErrorKind> {
|
||||
fn from_str_radix(src: &str, radix: u32) -> Result<ParsedNumResult, IntErrorKind> {
|
||||
use self::IntErrorKind::*;
|
||||
|
||||
assert!(
|
||||
@ -273,25 +260,30 @@ fn from_str_radix(src: &str, radix: u32) -> Result<(IntValue, NumericBound), Int
|
||||
} else {
|
||||
SignDemand::NoDemand
|
||||
};
|
||||
Ok((
|
||||
Ok(ParsedNumResult::UnknownNum(
|
||||
result,
|
||||
IntBound::AtLeast {
|
||||
NumericBound::AtLeastIntOrFloat {
|
||||
sign: sign_demand,
|
||||
width: lower_bound,
|
||||
}
|
||||
.into(),
|
||||
},
|
||||
))
|
||||
}
|
||||
Some(ParsedWidth::Float(fw)) => {
|
||||
// For now, assume floats can represent all integers
|
||||
// TODO: this is somewhat incorrect, revisit
|
||||
Ok((result, FloatBound::Exact(fw).into()))
|
||||
Ok(ParsedNumResult::Float(
|
||||
match result {
|
||||
IntValue::I128(n) => n as f64,
|
||||
IntValue::U128(n) => n as f64,
|
||||
},
|
||||
FloatBound::Exact(fw),
|
||||
))
|
||||
}
|
||||
Some(ParsedWidth::Int(exact_width)) => {
|
||||
// We need to check if the exact bound >= lower bound.
|
||||
if exact_width.is_superset(&lower_bound, is_negative) {
|
||||
// Great! Use the exact bound.
|
||||
Ok((result, IntBound::Exact(exact_width).into()))
|
||||
Ok(ParsedNumResult::Int(result, IntBound::Exact(exact_width)))
|
||||
} else {
|
||||
// This is something like 200i8; the lower bound is u8, which holds strictly more
|
||||
// ints on the positive side than i8 does. Report an error depending on which side
|
||||
@ -512,20 +504,9 @@ pub enum FloatBound {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum NumericBound {
|
||||
None,
|
||||
Int(IntBound),
|
||||
Float(FloatBound),
|
||||
}
|
||||
|
||||
impl From<IntBound> for NumericBound {
|
||||
#[inline(always)]
|
||||
fn from(ib: IntBound) -> Self {
|
||||
Self::Int(ib)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FloatBound> for NumericBound {
|
||||
#[inline(always)]
|
||||
fn from(fb: FloatBound) -> Self {
|
||||
Self::Float(fb)
|
||||
}
|
||||
/// Must be an integer of a certain size, or any float.
|
||||
AtLeastIntOrFloat {
|
||||
sign: SignDemand,
|
||||
width: IntWidth,
|
||||
},
|
||||
}
|
||||
|
@ -216,8 +216,8 @@ pub fn canonicalize_pattern<'a>(
|
||||
let problem = MalformedPatternProblem::MalformedInt;
|
||||
malformed_pattern(env, problem, region)
|
||||
}
|
||||
Ok(ParsedNumResult::UnknownNum(int)) => {
|
||||
Pattern::NumLiteral(var_store.fresh(), (str).into(), int, NumericBound::None)
|
||||
Ok(ParsedNumResult::UnknownNum(int, bound)) => {
|
||||
Pattern::NumLiteral(var_store.fresh(), (str).into(), int, bound)
|
||||
}
|
||||
Ok(ParsedNumResult::Int(int, bound)) => Pattern::IntLiteral(
|
||||
var_store.fresh(),
|
||||
|
@ -324,8 +324,11 @@ impl TypedNumericBound for NumericBound {
|
||||
fn bounded_range(&self) -> Vec<Variable> {
|
||||
match self {
|
||||
NumericBound::None => vec![],
|
||||
NumericBound::Int(ib) => ib.bounded_range(),
|
||||
NumericBound::Float(fb) => fb.bounded_range(),
|
||||
&NumericBound::AtLeastIntOrFloat { sign, width } => {
|
||||
let mut range = IntBound::AtLeast { sign, width }.bounded_range();
|
||||
range.extend_from_slice(&[Variable::F32, Variable::F64, Variable::DEC]);
|
||||
range
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ mod solve_expr {
|
||||
|
||||
#[test]
|
||||
fn int_literal() {
|
||||
infer_eq("5", "Int *");
|
||||
infer_eq("5", "Num *");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -334,7 +334,7 @@ mod solve_expr {
|
||||
[42]
|
||||
"#
|
||||
),
|
||||
"List (Int *)",
|
||||
"List (Num *)",
|
||||
);
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ mod solve_expr {
|
||||
[[[ 5 ]]]
|
||||
"#
|
||||
),
|
||||
"List (List (List (Int *)))",
|
||||
"List (List (List (Num *)))",
|
||||
);
|
||||
}
|
||||
|
||||
@ -358,7 +358,7 @@ mod solve_expr {
|
||||
[ 1, 2, 3 ]
|
||||
"#
|
||||
),
|
||||
"List (Int *)",
|
||||
"List (Num *)",
|
||||
);
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ mod solve_expr {
|
||||
[ [ 1 ], [ 2, 3 ] ]
|
||||
"#
|
||||
),
|
||||
"List (List (Int *))",
|
||||
"List (List (Num *))",
|
||||
);
|
||||
}
|
||||
|
||||
@ -518,7 +518,7 @@ mod solve_expr {
|
||||
\_, _ -> 42
|
||||
"#
|
||||
),
|
||||
"*, * -> Int *",
|
||||
"*, * -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -689,7 +689,7 @@ mod solve_expr {
|
||||
func
|
||||
"#
|
||||
),
|
||||
"*, * -> Int *",
|
||||
"*, * -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -753,7 +753,7 @@ mod solve_expr {
|
||||
c
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -788,7 +788,7 @@ mod solve_expr {
|
||||
alwaysFive "stuff"
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -835,7 +835,7 @@ mod solve_expr {
|
||||
x
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -849,7 +849,7 @@ mod solve_expr {
|
||||
enlist 5
|
||||
"#
|
||||
),
|
||||
"List (Int *)",
|
||||
"List (Num *)",
|
||||
);
|
||||
}
|
||||
|
||||
@ -876,7 +876,7 @@ mod solve_expr {
|
||||
1 |> (\a -> a)
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -890,7 +890,7 @@ mod solve_expr {
|
||||
1 |> always2 "foo"
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -955,7 +955,7 @@ mod solve_expr {
|
||||
apply identity 5
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -984,7 +984,7 @@ mod solve_expr {
|
||||
// flip neverendingInt
|
||||
// "#
|
||||
// ),
|
||||
// "(Int *, (a -> a)) -> Int *",
|
||||
// "(Num *, (a -> a)) -> Num *",
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -1058,7 +1058,7 @@ mod solve_expr {
|
||||
// 1 // 2
|
||||
// "#
|
||||
// ),
|
||||
// "Int *",
|
||||
// "Num *",
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -1070,7 +1070,7 @@ mod solve_expr {
|
||||
// 1 + 2
|
||||
// "#
|
||||
// ),
|
||||
// "Int *",
|
||||
// "Num *",
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -1119,7 +1119,7 @@ mod solve_expr {
|
||||
[ alwaysFive "foo", alwaysFive [] ]
|
||||
"#
|
||||
),
|
||||
"List (Int *)",
|
||||
"List (Num *)",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1134,7 +1134,7 @@ mod solve_expr {
|
||||
24
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1148,7 +1148,7 @@ mod solve_expr {
|
||||
3 -> 4
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1161,17 +1161,17 @@ mod solve_expr {
|
||||
|
||||
#[test]
|
||||
fn one_field_record() {
|
||||
infer_eq("{ x: 5 }", "{ x : Int * }");
|
||||
infer_eq("{ x: 5 }", "{ x : Num * }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn two_field_record() {
|
||||
infer_eq("{ x: 5, y : 3.14 }", "{ x : Int *, y : Float * }");
|
||||
infer_eq("{ x: 5, y : 3.14 }", "{ x : Num *, y : Float * }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn record_literal_accessor() {
|
||||
infer_eq("{ x: 5, y : 3.14 }.x", "Int *");
|
||||
infer_eq("{ x: 5, y : 3.14 }.x", "Num *");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1230,7 +1230,7 @@ mod solve_expr {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
foo : Int * -> custom
|
||||
foo : Num * -> custom
|
||||
|
||||
foo 2
|
||||
"#
|
||||
@ -1327,7 +1327,7 @@ mod solve_expr {
|
||||
\Foo -> 42
|
||||
"#
|
||||
),
|
||||
"[ Foo ] -> Int *",
|
||||
"[ Foo ] -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1339,7 +1339,7 @@ mod solve_expr {
|
||||
\@Foo -> 42
|
||||
"#
|
||||
),
|
||||
"[ @Foo ] -> Int *",
|
||||
"[ @Foo ] -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1354,7 +1354,7 @@ mod solve_expr {
|
||||
False -> 0
|
||||
"#
|
||||
),
|
||||
"[ False, True ] -> Int *",
|
||||
"[ False, True ] -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1366,7 +1366,7 @@ mod solve_expr {
|
||||
Foo "happy" 2020
|
||||
"#
|
||||
),
|
||||
"[ Foo Str (Int *) ]*",
|
||||
"[ Foo Str (Num *) ]*",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1378,7 +1378,7 @@ mod solve_expr {
|
||||
@Foo "happy" 2020
|
||||
"#
|
||||
),
|
||||
"[ @Foo Str (Int *) ]*",
|
||||
"[ @Foo Str (Num *) ]*",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1407,7 +1407,7 @@ mod solve_expr {
|
||||
{ x: 4 } -> 4
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2347,7 +2347,7 @@ mod solve_expr {
|
||||
{ numIdentity, x : numIdentity 42, y }
|
||||
"#
|
||||
),
|
||||
"{ numIdentity : Num a -> Num a, x : Int *, y : F64 }",
|
||||
"{ numIdentity : Num a -> Num a, x : Num a, y : F64 }",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2383,7 +2383,7 @@ mod solve_expr {
|
||||
f
|
||||
"#
|
||||
),
|
||||
"Int * -> Int *",
|
||||
"Num * -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2416,7 +2416,7 @@ mod solve_expr {
|
||||
toBit
|
||||
"#
|
||||
),
|
||||
"[ False, True ] -> Int *",
|
||||
"[ False, True ] -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2453,7 +2453,7 @@ mod solve_expr {
|
||||
fromBit
|
||||
"#
|
||||
),
|
||||
"Int * -> [ False, True ]*",
|
||||
"Num * -> [ False, True ]*",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2505,7 +2505,7 @@ mod solve_expr {
|
||||
foo { x: 5 }
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -2774,7 +2774,7 @@ mod solve_expr {
|
||||
// infer_eq_without_problem(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// s : Int *
|
||||
// s : Num *
|
||||
// s = 3.1
|
||||
|
||||
// s
|
||||
@ -3214,7 +3214,7 @@ mod solve_expr {
|
||||
List.get [ 10, 9, 8, 7 ] 1
|
||||
"#
|
||||
),
|
||||
"Result (Int *) [ OutOfBounds ]*",
|
||||
"Result (Num *) [ OutOfBounds ]*",
|
||||
);
|
||||
|
||||
infer_eq_without_problem(
|
||||
@ -3497,7 +3497,7 @@ mod solve_expr {
|
||||
f
|
||||
"#
|
||||
),
|
||||
"{ p : *, q : * }* -> Int *",
|
||||
"{ p : *, q : * }* -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3552,7 +3552,7 @@ mod solve_expr {
|
||||
_ -> 3
|
||||
"#
|
||||
),
|
||||
"Int * -> Int *",
|
||||
"Num * -> Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3724,8 +3724,7 @@ mod solve_expr {
|
||||
negatePoint { x: 1, y: 2.1, z: 0x3 }
|
||||
"#
|
||||
),
|
||||
// TODO this should be "Int a", FIXME
|
||||
"{ x : Int *, y : F64, z : Int * }",
|
||||
"{ x : Num a, y : F64, z : Int * }",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3742,8 +3741,7 @@ mod solve_expr {
|
||||
{ a, b }
|
||||
"#
|
||||
),
|
||||
// TODO this should be "Int a", FIXME
|
||||
"{ a : { x : Int *, y : F64, z : c }, b : { blah : Str, x : Int *, y : F64, z : c } }",
|
||||
"{ a : { x : Num a, y : F64, z : c }, b : { blah : Str, x : Num a, y : F64, z : c } }",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3755,7 +3753,7 @@ mod solve_expr {
|
||||
\{ x, y ? 0 } -> x + y
|
||||
"#
|
||||
),
|
||||
"{ x : Int a, y ? Int a }* -> Int a",
|
||||
"{ x : Num a, y ? Num a }* -> Num a",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3769,7 +3767,7 @@ mod solve_expr {
|
||||
x + y
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3783,7 +3781,7 @@ mod solve_expr {
|
||||
{ x, y ? 0 } -> x + y
|
||||
"#
|
||||
),
|
||||
"{ x : Int a, y ? Int a }* -> Int a",
|
||||
"{ x : Num a, y ? Num a }* -> Num a",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3948,7 +3946,7 @@ mod solve_expr {
|
||||
g
|
||||
"#
|
||||
),
|
||||
"Int a -> Int a",
|
||||
"Num a -> Num a",
|
||||
);
|
||||
}
|
||||
|
||||
@ -3987,10 +3985,10 @@ mod solve_expr {
|
||||
Foo Bar 1
|
||||
"#
|
||||
),
|
||||
"[ Foo [ Bar ]* (Int *) ]*",
|
||||
"[ Foo [ Bar ]* (Num *) ]*",
|
||||
);
|
||||
|
||||
infer_eq_without_problem("Foo Bar 1", "[ Foo [ Bar ]* (Int *) ]*");
|
||||
infer_eq_without_problem("Foo Bar 1", "[ Foo [ Bar ]* (Num *) ]*");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -4682,7 +4680,7 @@ mod solve_expr {
|
||||
x
|
||||
"#
|
||||
),
|
||||
"Int *",
|
||||
"Num *",
|
||||
);
|
||||
}
|
||||
|
||||
@ -4983,7 +4981,7 @@ mod solve_expr {
|
||||
None -> 0
|
||||
"#
|
||||
),
|
||||
"[ None, Some { tag : [ A, B ] }* ] -> Int *",
|
||||
"[ None, Some { tag : [ A, B ] }* ] -> Num *",
|
||||
)
|
||||
}
|
||||
|
||||
@ -5016,7 +5014,7 @@ mod solve_expr {
|
||||
{ x: Red, y ? 5 } -> y
|
||||
"#
|
||||
),
|
||||
"{ x : [ Blue, Red ], y ? Int a }* -> Int a",
|
||||
"{ x : [ Blue, Red ], y ? Num a }* -> Num a",
|
||||
)
|
||||
}
|
||||
|
||||
@ -5029,8 +5027,7 @@ mod solve_expr {
|
||||
\UserId id -> id + 1
|
||||
"#
|
||||
),
|
||||
// TODO needs parantheses
|
||||
"[ UserId Int a ] -> Int a",
|
||||
"[ UserId (Num a) ] -> Num a",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -66,11 +66,11 @@ pub fn type_problem<'b>(
|
||||
let last = range.len() - 1;
|
||||
for (i, choice) in range.into_iter().enumerate() {
|
||||
if i == last && i == 1 {
|
||||
range_choices.push(alloc.text(" or "));
|
||||
range_choices.push(alloc.reflow(" or "));
|
||||
} else if i == last && i > 1 {
|
||||
range_choices.push(alloc.text(", or "));
|
||||
} else if i > 1 {
|
||||
range_choices.push(alloc.text(", "));
|
||||
range_choices.push(alloc.reflow(", or "));
|
||||
} else if i > 0 {
|
||||
range_choices.push(alloc.reflow(", "));
|
||||
}
|
||||
|
||||
range_choices.push(to_doc(alloc, Parens::Unnecessary, choice));
|
||||
|
@ -862,9 +862,9 @@ mod test_reporting {
|
||||
2│> 2 if 1 -> 0x0
|
||||
3│ _ -> 0x1
|
||||
|
||||
Right now it’s an integer of type:
|
||||
Right now it’s a number of type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
But I need every `if` guard condition to evaluate to a Bool—either
|
||||
`True` or `False`.
|
||||
@ -896,7 +896,7 @@ mod test_reporting {
|
||||
|
||||
but the `then` branch has the type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
I need all branches in an `if` to have the same type!
|
||||
"#
|
||||
@ -927,7 +927,7 @@ mod test_reporting {
|
||||
|
||||
But all the previous branches have type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
I need all branches in an `if` to have the same type!
|
||||
"#
|
||||
@ -993,7 +993,7 @@ mod test_reporting {
|
||||
|
||||
However, the preceding elements in the list all have the type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
I need every element in a list to have the same type!
|
||||
"#
|
||||
@ -1250,8 +1250,8 @@ mod test_reporting {
|
||||
2│ x = if True then 3.14 else 4
|
||||
^
|
||||
|
||||
It can only be used as a
|
||||
`I8``U8`, `I16`, `U16`, `I32`, `U32`, `I64`, `Nat`, `U64`, `I128`, or `U128`
|
||||
It can only be used as a `I8`, `U8`, `I16`, `U16`, `I32`, `U32`, `I64`, `Nat`, `U64`,
|
||||
`I128`, `U128`, `F32`, `F64`, or `Dec`
|
||||
|
||||
But it is being used as:
|
||||
|
||||
@ -1439,7 +1439,7 @@ mod test_reporting {
|
||||
|
||||
But the expression between `when` and `is` has the type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -1470,7 +1470,7 @@ mod test_reporting {
|
||||
|
||||
But all the previous branches match:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -1500,7 +1500,7 @@ mod test_reporting {
|
||||
|
||||
But the expression between `when` and `is` has the type:
|
||||
|
||||
{ foo : Int a }
|
||||
{ foo : Num a }
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -1620,13 +1620,13 @@ mod test_reporting {
|
||||
2│ {} | 1 -> 3
|
||||
^^^^^^
|
||||
|
||||
The first pattern is trying to match integers:
|
||||
The first pattern is trying to match numbers:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
But the expression between `when` and `is` has the type:
|
||||
|
||||
{ foo : Int a }
|
||||
{ foo : Num a }
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -1652,9 +1652,9 @@ mod test_reporting {
|
||||
1│ (Foo x) = 42
|
||||
^^
|
||||
|
||||
It is an integer of type:
|
||||
It is a number of type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
But you are trying to use it as:
|
||||
|
||||
@ -2177,8 +2177,8 @@ mod test_reporting {
|
||||
|
||||
This is usually a typo. Here are the `x` fields that are most similar:
|
||||
|
||||
{ fo : Int b
|
||||
, bar : Int a
|
||||
{ fo : Num b
|
||||
, bar : Num a
|
||||
}
|
||||
|
||||
So maybe `.foo` should be `.fo`?
|
||||
@ -2244,10 +2244,10 @@ mod test_reporting {
|
||||
|
||||
This is usually a typo. Here are the `x` fields that are most similar:
|
||||
|
||||
{ fo : Int c
|
||||
, foobar : Int d
|
||||
, bar : Int a
|
||||
, baz : Int b
|
||||
{ fo : Num c
|
||||
, foobar : Num d
|
||||
, bar : Num a
|
||||
, baz : Num b
|
||||
, ...
|
||||
}
|
||||
|
||||
@ -2342,7 +2342,7 @@ mod test_reporting {
|
||||
|
||||
But `add` needs the 2nd argument to be:
|
||||
|
||||
Num (Integer a)
|
||||
Num a
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -3375,8 +3375,8 @@ mod test_reporting {
|
||||
|
||||
This `ACons` global tag application has the type:
|
||||
|
||||
[ ACons Int Signed64 [ BCons (Int a) [ ACons Str [ BNil ]b ]c ]d,
|
||||
ANil ]
|
||||
[ ACons Num (Integer Signed64) [ BCons (Num a) [ ACons Str [ BNil
|
||||
]b ]c ]d, ANil ]
|
||||
|
||||
But the type annotation on `x` says it should be:
|
||||
|
||||
@ -3401,9 +3401,7 @@ mod test_reporting {
|
||||
minlit = -170_141_183_460_469_231_731_687_303_715_884_105_728
|
||||
maxlit = 340_282_366_920_938_463_463_374_607_431_768_211_455
|
||||
|
||||
getI128 = \_ -> 1i128
|
||||
|
||||
x + y + h + l + minlit + (getI128 maxlit)
|
||||
x + y + h + l + minlit + maxlit
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
@ -4990,7 +4988,7 @@ mod test_reporting {
|
||||
|
||||
This `insert` call produces:
|
||||
|
||||
Dict Str (Int a)
|
||||
Dict Str (Num a)
|
||||
|
||||
But the type annotation on `myDict` says it should be:
|
||||
|
||||
@ -5652,7 +5650,7 @@ mod test_reporting {
|
||||
|
||||
but the `then` branch has the type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
I need all branches in an `if` to have the same type!
|
||||
"#
|
||||
@ -6293,7 +6291,7 @@ I need all branches in an `if` to have the same type!
|
||||
|
||||
This `map` call produces:
|
||||
|
||||
List [ Foo Int a ]
|
||||
List [ Foo Num a ]
|
||||
|
||||
But the type annotation on `x` says it should be:
|
||||
|
||||
@ -6543,11 +6541,11 @@ I need all branches in an `if` to have the same type!
|
||||
|
||||
This argument is an anonymous function of type:
|
||||
|
||||
Num (Integer a) -> Num (Integer a)
|
||||
Num a -> Num a
|
||||
|
||||
But `map` needs the 2nd argument to be:
|
||||
|
||||
Str -> Num (Integer a)
|
||||
Str -> Num a
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -6649,21 +6647,6 @@ I need all branches in an `if` to have the same type!
|
||||
But the type annotation on `mult` says it should be:
|
||||
|
||||
F64
|
||||
|
||||
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||
|
||||
The 2nd argument to `mult` is not what I expect:
|
||||
|
||||
4│ mult 0 0
|
||||
^
|
||||
|
||||
This argument is an integer of type:
|
||||
|
||||
Int a
|
||||
|
||||
But `mult` needs the 2nd argument to be:
|
||||
|
||||
F64
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -6712,21 +6695,6 @@ I need all branches in an `if` to have the same type!
|
||||
But the type annotation on `mult` says it should be:
|
||||
|
||||
F64
|
||||
|
||||
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||
|
||||
The 2nd argument to `mult` is not what I expect:
|
||||
|
||||
4│ mult 0 0
|
||||
^
|
||||
|
||||
This argument is an integer of type:
|
||||
|
||||
Int a
|
||||
|
||||
But `mult` needs the 2nd argument to be:
|
||||
|
||||
F64
|
||||
"#
|
||||
),
|
||||
)
|
||||
@ -7078,9 +7046,9 @@ I need all branches in an `if` to have the same type!
|
||||
5│ f = \c -> c 6
|
||||
^
|
||||
|
||||
This argument is an integer of type:
|
||||
This argument is a number of type:
|
||||
|
||||
Int a
|
||||
Num a
|
||||
|
||||
But `c` needs the 1st argument to be:
|
||||
|
||||
@ -7088,7 +7056,7 @@ I need all branches in an `if` to have the same type!
|
||||
|
||||
Tip: The type annotation uses the type variable `a` to say that this
|
||||
definition can produce any type of value. But in the body I see that
|
||||
it will only produce a `Int` value of a single specific type. Maybe
|
||||
it will only produce a `Num` value of a single specific type. Maybe
|
||||
change the type annotation to be more specific? Maybe change the code
|
||||
to be more general?
|
||||
"#
|
||||
@ -7901,9 +7869,9 @@ I need all branches in an `if` to have the same type!
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
a = -9_223_372_036_854
|
||||
List.get [1,2,3] a
|
||||
"#
|
||||
a = -9_223_372_036_854
|
||||
List.get [1,2,3] a
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
@ -7914,7 +7882,7 @@ I need all branches in an `if` to have the same type!
|
||||
2│ List.get [1,2,3] a
|
||||
^
|
||||
|
||||
It can only be used as a `I64` or `I128`
|
||||
It can only be used as a `I64`, `I128`, `F32`, `F64`, or `Dec`
|
||||
|
||||
But it is being used as:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user