mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Typecheck numeric suffixes in patterns
This commit is contained in:
parent
a6f7579c07
commit
df8113ce32
8 changed files with 270 additions and 41 deletions
|
@ -27,9 +27,9 @@ pub enum Pattern {
|
||||||
ext_var: Variable,
|
ext_var: Variable,
|
||||||
destructs: Vec<Loc<RecordDestruct>>,
|
destructs: Vec<Loc<RecordDestruct>>,
|
||||||
},
|
},
|
||||||
IntLiteral(Variable, Box<str>, i64, NumericBound<IntWidth>),
|
|
||||||
NumLiteral(Variable, Box<str>, i64, NumericBound<NumWidth>),
|
NumLiteral(Variable, Box<str>, i64, NumericBound<NumWidth>),
|
||||||
FloatLiteral(Variable, Box<str>, f64, NumericBound<FloatWidth>),
|
IntLiteral(Variable, Variable, Box<str>, i64, NumericBound<IntWidth>),
|
||||||
|
FloatLiteral(Variable, Variable, Box<str>, f64, NumericBound<FloatWidth>),
|
||||||
StrLiteral(Box<str>),
|
StrLiteral(Box<str>),
|
||||||
Underscore,
|
Underscore,
|
||||||
|
|
||||||
|
@ -192,9 +192,13 @@ pub fn canonicalize_pattern<'a>(
|
||||||
let problem = MalformedPatternProblem::MalformedFloat;
|
let problem = MalformedPatternProblem::MalformedFloat;
|
||||||
malformed_pattern(env, problem, region)
|
malformed_pattern(env, problem, region)
|
||||||
}
|
}
|
||||||
Ok((float, bound)) => {
|
Ok((float, bound)) => Pattern::FloatLiteral(
|
||||||
Pattern::FloatLiteral(var_store.fresh(), (str).into(), float, bound)
|
var_store.fresh(),
|
||||||
}
|
var_store.fresh(),
|
||||||
|
(str).into(),
|
||||||
|
float,
|
||||||
|
bound,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
},
|
},
|
||||||
|
@ -213,12 +217,20 @@ pub fn canonicalize_pattern<'a>(
|
||||||
Ok(ParsedNumResult::UnknownNum(int)) => {
|
Ok(ParsedNumResult::UnknownNum(int)) => {
|
||||||
Pattern::NumLiteral(var_store.fresh(), (str).into(), int, NumericBound::None)
|
Pattern::NumLiteral(var_store.fresh(), (str).into(), int, NumericBound::None)
|
||||||
}
|
}
|
||||||
Ok(ParsedNumResult::Int(int, bound)) => {
|
Ok(ParsedNumResult::Int(int, bound)) => Pattern::IntLiteral(
|
||||||
Pattern::IntLiteral(var_store.fresh(), (str).into(), int, bound)
|
var_store.fresh(),
|
||||||
}
|
var_store.fresh(),
|
||||||
Ok(ParsedNumResult::Float(float, bound)) => {
|
(str).into(),
|
||||||
Pattern::FloatLiteral(var_store.fresh(), (str).into(), float, bound)
|
int,
|
||||||
}
|
bound,
|
||||||
|
),
|
||||||
|
Ok(ParsedNumResult::Float(float, bound)) => Pattern::FloatLiteral(
|
||||||
|
var_store.fresh(),
|
||||||
|
var_store.fresh(),
|
||||||
|
(str).into(),
|
||||||
|
float,
|
||||||
|
bound,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
},
|
},
|
||||||
|
@ -237,7 +249,7 @@ pub fn canonicalize_pattern<'a>(
|
||||||
let sign_str = if is_negative { "-" } else { "" };
|
let sign_str = if is_negative { "-" } else { "" };
|
||||||
let int_str = format!("{}{}", sign_str, int.to_string()).into_boxed_str();
|
let int_str = format!("{}{}", sign_str, int.to_string()).into_boxed_str();
|
||||||
let i = if is_negative { -int } else { int };
|
let i = if is_negative { -int } else { int };
|
||||||
Pattern::IntLiteral(var_store.fresh(), int_str, i, bound)
|
Pattern::IntLiteral(var_store.fresh(), var_store.fresh(), int_str, i, bound)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ptype => unsupported_pattern(env, ptype, region),
|
ptype => unsupported_pattern(env, ptype, region),
|
||||||
|
|
|
@ -11,7 +11,7 @@ use roc_types::types::Category;
|
||||||
use roc_types::types::Reason;
|
use roc_types::types::Reason;
|
||||||
use roc_types::types::Type::{self, *};
|
use roc_types::types::Type::{self, *};
|
||||||
|
|
||||||
fn add_numeric_bound_constr(
|
pub fn add_numeric_bound_constr(
|
||||||
constrs: &mut Vec<Constraint>,
|
constrs: &mut Vec<Constraint>,
|
||||||
num_type: Type,
|
num_type: Type,
|
||||||
bound: impl TypedNumericBound,
|
bound: impl TypedNumericBound,
|
||||||
|
|
|
@ -178,34 +178,83 @@ pub fn constrain_pattern(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NumLiteral(var, _, _, _bound) => {
|
&NumLiteral(var, _, _, bound) => {
|
||||||
// TODO: constrain bound here
|
state.vars.push(var);
|
||||||
state.vars.push(*var);
|
|
||||||
|
let num_type = builtins::num_num(Type::Variable(var));
|
||||||
|
|
||||||
|
builtins::add_numeric_bound_constr(
|
||||||
|
&mut state.constraints,
|
||||||
|
num_type.clone(),
|
||||||
|
bound,
|
||||||
|
region,
|
||||||
|
Category::Num,
|
||||||
|
);
|
||||||
|
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Num,
|
PatternCategory::Num,
|
||||||
builtins::num_num(Type::Variable(*var)),
|
num_type,
|
||||||
expected,
|
expected,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
IntLiteral(precision_var, _, _, _bound) => {
|
&IntLiteral(num_var, precision_var, _, _, bound) => {
|
||||||
// TODO: constrain bound here
|
// First constraint on the free num var; this improves the resolved type quality in
|
||||||
|
// case the bound is an alias.
|
||||||
|
builtins::add_numeric_bound_constr(
|
||||||
|
&mut state.constraints,
|
||||||
|
Type::Variable(num_var),
|
||||||
|
bound,
|
||||||
|
region,
|
||||||
|
Category::Int,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Link the free num var with the int var and our expectation.
|
||||||
|
let int_type = builtins::num_int(Type::Variable(precision_var));
|
||||||
|
|
||||||
|
state.constraints.push(Constraint::Eq(
|
||||||
|
Type::Variable(num_var),
|
||||||
|
Expected::NoExpectation(int_type),
|
||||||
|
Category::Int,
|
||||||
|
region,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Int,
|
PatternCategory::Int,
|
||||||
builtins::num_int(Type::Variable(*precision_var)),
|
Type::Variable(num_var),
|
||||||
expected,
|
expected,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatLiteral(precision_var, _, _, _bound) => {
|
&FloatLiteral(num_var, precision_var, _, _, bound) => {
|
||||||
// TODO: constrain bound here
|
// First constraint on the free num var; this improves the resolved type quality in
|
||||||
|
// case the bound is an alias.
|
||||||
|
builtins::add_numeric_bound_constr(
|
||||||
|
&mut state.constraints,
|
||||||
|
Type::Variable(num_var),
|
||||||
|
bound,
|
||||||
|
region,
|
||||||
|
Category::Float,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Link the free num var with the float var and our expectation.
|
||||||
|
let float_type = builtins::num_float(Type::Variable(precision_var));
|
||||||
|
|
||||||
|
state.constraints.push(Constraint::Eq(
|
||||||
|
Type::Variable(num_var),
|
||||||
|
Expected::NoExpectation(float_type),
|
||||||
|
Category::Float,
|
||||||
|
region,
|
||||||
|
));
|
||||||
|
|
||||||
|
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Float,
|
PatternCategory::Float,
|
||||||
builtins::num_float(Type::Variable(*precision_var)),
|
Type::Variable(num_var),
|
||||||
expected,
|
expected,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7662,8 +7662,8 @@ fn from_can_pattern_help<'a>(
|
||||||
match can_pattern {
|
match can_pattern {
|
||||||
Underscore => Ok(Pattern::Underscore),
|
Underscore => Ok(Pattern::Underscore),
|
||||||
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||||
IntLiteral(var, _, int, _bound) => {
|
IntLiteral(_, precision_var, _, int, _bound) => {
|
||||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
match num_argument_to_int_or_float(env.subs, env.target_info, *precision_var, false) {
|
||||||
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*int as i128, precision)),
|
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*int as i128, precision)),
|
||||||
other => {
|
other => {
|
||||||
panic!(
|
panic!(
|
||||||
|
@ -7673,11 +7673,11 @@ fn from_can_pattern_help<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FloatLiteral(var, float_str, float, _bound) => {
|
FloatLiteral(_, precision_var, float_str, float, _bound) => {
|
||||||
// TODO: Can I reuse num_argument_to_int_or_float here if I pass in true?
|
// TODO: Can I reuse num_argument_to_int_or_float here if I pass in true?
|
||||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, true) {
|
match num_argument_to_int_or_float(env.subs, env.target_info, *precision_var, true) {
|
||||||
IntOrFloat::Int(_) => {
|
IntOrFloat::Int(_) => {
|
||||||
panic!("Invalid precision for float pattern {:?}", var)
|
panic!("Invalid precision for float pattern {:?}", precision_var)
|
||||||
}
|
}
|
||||||
IntOrFloat::Float(precision) => {
|
IntOrFloat::Float(precision) => {
|
||||||
Ok(Pattern::FloatLiteral(f64::to_bits(*float), precision))
|
Ok(Pattern::FloatLiteral(f64::to_bits(*float), precision))
|
||||||
|
|
|
@ -5092,4 +5092,108 @@ mod solve_expr {
|
||||||
r#"{ bi128 : I128, bi16 : I16, bi32 : I32, bi64 : I64, bi8 : I8, bnat : Nat, bu128 : U128, bu16 : U16, bu32 : U32, bu64 : U64, bu8 : U8, dec : Dec, f32 : F32, f64 : F64, fdec : Dec, ff32 : F32, ff64 : F64, i128 : I128, i16 : I16, i32 : I32, i64 : I64, i8 : I8, nat : Nat, u128 : U128, u16 : U16, u32 : U32, u64 : U64, u8 : U8 }"#,
|
r#"{ bi128 : I128, bi16 : I16, bi32 : I32, bi64 : I64, bi8 : I8, bnat : Nat, bu128 : U128, bu16 : U16, bu32 : U32, bu64 : U64, bu8 : U8, dec : Dec, f32 : F32, f64 : F64, fdec : Dec, ff32 : F32, ff64 : F64, i128 : I128, i16 : I16, i32 : I32, i64 : I64, i8 : I8, nat : Nat, u128 : U128, u16 : U16, u32 : U32, u64 : U64, u8 : U8 }"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn numeric_literal_suffixes_in_pattern() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
u8: (\n ->
|
||||||
|
when n is
|
||||||
|
123u8 -> n),
|
||||||
|
u16: (\n ->
|
||||||
|
when n is
|
||||||
|
123u16 -> n),
|
||||||
|
u32: (\n ->
|
||||||
|
when n is
|
||||||
|
123u32 -> n),
|
||||||
|
u64: (\n ->
|
||||||
|
when n is
|
||||||
|
123u64 -> n),
|
||||||
|
u128: (\n ->
|
||||||
|
when n is
|
||||||
|
123u128 -> n),
|
||||||
|
|
||||||
|
i8: (\n ->
|
||||||
|
when n is
|
||||||
|
123i8 -> n),
|
||||||
|
i16: (\n ->
|
||||||
|
when n is
|
||||||
|
123i16 -> n),
|
||||||
|
i32: (\n ->
|
||||||
|
when n is
|
||||||
|
123i32 -> n),
|
||||||
|
i64: (\n ->
|
||||||
|
when n is
|
||||||
|
123i64 -> n),
|
||||||
|
i128: (\n ->
|
||||||
|
when n is
|
||||||
|
123i128 -> n),
|
||||||
|
|
||||||
|
nat: (\n ->
|
||||||
|
when n is
|
||||||
|
123nat -> n),
|
||||||
|
|
||||||
|
bu8: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11u8 -> n),
|
||||||
|
bu16: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11u16 -> n),
|
||||||
|
bu32: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11u32 -> n),
|
||||||
|
bu64: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11u64 -> n),
|
||||||
|
bu128: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11u128 -> n),
|
||||||
|
|
||||||
|
bi8: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11i8 -> n),
|
||||||
|
bi16: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11i16 -> n),
|
||||||
|
bi32: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11i32 -> n),
|
||||||
|
bi64: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11i64 -> n),
|
||||||
|
bi128: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11i128 -> n),
|
||||||
|
|
||||||
|
bnat: (\n ->
|
||||||
|
when n is
|
||||||
|
0b11nat -> n),
|
||||||
|
|
||||||
|
dec: (\n ->
|
||||||
|
when n is
|
||||||
|
123.0dec -> n),
|
||||||
|
f32: (\n ->
|
||||||
|
when n is
|
||||||
|
123.0f32 -> n),
|
||||||
|
f64: (\n ->
|
||||||
|
when n is
|
||||||
|
123.0f64 -> n),
|
||||||
|
|
||||||
|
fdec: (\n ->
|
||||||
|
when n is
|
||||||
|
123dec -> n),
|
||||||
|
ff32: (\n ->
|
||||||
|
when n is
|
||||||
|
123f32 -> n),
|
||||||
|
ff64: (\n ->
|
||||||
|
when n is
|
||||||
|
123f64 -> n),
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
r#"{ bi128 : I128 -> I128, bi16 : I16 -> I16, bi32 : I32 -> I32, bi64 : I64 -> I64, bi8 : I8 -> I8, bnat : Nat -> Nat, bu128 : U128 -> U128, bu16 : U16 -> U16, bu32 : U32 -> U32, bu64 : U64 -> U64, bu8 : U8 -> U8, dec : Dec -> Dec, f32 : F32 -> F32, f64 : F64 -> F64, fdec : Dec -> Dec, ff32 : F32 -> F32, ff64 : F64 -> F64, i128 : I128 -> I128, i16 : I16 -> I16, i32 : I32 -> I32, i64 : I64 -> I64, i8 : I8 -> I8, nat : Nat -> Nat, u128 : U128 -> U128, u16 : U16 -> U16, u32 : U32 -> U32, u64 : U64 -> U64, u8 : U8 -> U8 }"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,6 +364,7 @@ fn write_content(env: &Env, content: &Content, subs: &Subs, buf: &mut String, pa
|
||||||
match *content {
|
match *content {
|
||||||
Alias(Symbol::NUM_BINARY32, _, _) => buf.push_str("F32"),
|
Alias(Symbol::NUM_BINARY32, _, _) => buf.push_str("F32"),
|
||||||
Alias(Symbol::NUM_BINARY64, _, _) => buf.push_str("F64"),
|
Alias(Symbol::NUM_BINARY64, _, _) => buf.push_str("F64"),
|
||||||
|
Alias(Symbol::NUM_DECIMAL, _, _) => buf.push_str("Dec"),
|
||||||
_ => write_parens!(write_parens, buf, {
|
_ => write_parens!(write_parens, buf, {
|
||||||
buf.push_str("Float ");
|
buf.push_str("Float ");
|
||||||
write_content(env, content, subs, buf, parens);
|
write_content(env, content, subs, buf, parens);
|
||||||
|
@ -411,7 +412,7 @@ fn write_integer(
|
||||||
use crate::subs::Content::*;
|
use crate::subs::Content::*;
|
||||||
|
|
||||||
macro_rules! derive_num_writes {
|
macro_rules! derive_num_writes {
|
||||||
($($lit:expr, $tag:path, $private_tag:path)*) => {
|
($($lit:expr, $tag:path)*) => {
|
||||||
write_parens!(
|
write_parens!(
|
||||||
write_parens,
|
write_parens,
|
||||||
buf,
|
buf,
|
||||||
|
@ -431,17 +432,17 @@ fn write_integer(
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_num_writes! {
|
derive_num_writes! {
|
||||||
"U8", Symbol::NUM_UNSIGNED8, Symbol::NUM_AT_UNSIGNED8
|
"U8", Symbol::NUM_UNSIGNED8
|
||||||
"U16", Symbol::NUM_UNSIGNED16, Symbol::NUM_AT_UNSIGNED16
|
"U16", Symbol::NUM_UNSIGNED16
|
||||||
"U32", Symbol::NUM_UNSIGNED32, Symbol::NUM_AT_UNSIGNED32
|
"U32", Symbol::NUM_UNSIGNED32
|
||||||
"U64", Symbol::NUM_UNSIGNED64, Symbol::NUM_AT_UNSIGNED64
|
"U64", Symbol::NUM_UNSIGNED64
|
||||||
"U128", Symbol::NUM_UNSIGNED128, Symbol::NUM_AT_UNSIGNED128
|
"U128", Symbol::NUM_UNSIGNED128
|
||||||
"I8", Symbol::NUM_SIGNED8, Symbol::NUM_AT_SIGNED8
|
"I8", Symbol::NUM_SIGNED8
|
||||||
"I16", Symbol::NUM_SIGNED16, Symbol::NUM_AT_SIGNED16
|
"I16", Symbol::NUM_SIGNED16
|
||||||
"I32", Symbol::NUM_SIGNED32, Symbol::NUM_AT_SIGNED32
|
"I32", Symbol::NUM_SIGNED32
|
||||||
"I64", Symbol::NUM_SIGNED64, Symbol::NUM_AT_SIGNED64
|
"I64", Symbol::NUM_SIGNED64
|
||||||
"I128", Symbol::NUM_SIGNED128, Symbol::NUM_AT_SIGNED128
|
"I128", Symbol::NUM_SIGNED128
|
||||||
"Nat", Symbol::NUM_NATURAL, Symbol::NUM_AT_NATURAL
|
"Nat", Symbol::NUM_NATURAL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1468,7 +1468,7 @@ fn add_pattern_category<'b>(
|
||||||
Str => alloc.reflow(" strings:"),
|
Str => alloc.reflow(" strings:"),
|
||||||
Num => alloc.reflow(" numbers:"),
|
Num => alloc.reflow(" numbers:"),
|
||||||
Int => alloc.reflow(" integers:"),
|
Int => alloc.reflow(" integers:"),
|
||||||
Float => alloc.reflow(" floats"),
|
Float => alloc.reflow(" floats:"),
|
||||||
};
|
};
|
||||||
|
|
||||||
alloc.concat(vec![i_am_trying_to_match, rest])
|
alloc.concat(vec![i_am_trying_to_match, rest])
|
||||||
|
|
|
@ -7369,6 +7369,69 @@ I need all branches in an `if` to have the same type!
|
||||||
1, "f64", mismatched_suffix_f64
|
1, "f64", mismatched_suffix_f64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! mismatched_suffix_tests_in_pattern {
|
||||||
|
($($number:expr, $suffix:expr, $name:ident)*) => {$(
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
let number = $number.to_string();
|
||||||
|
let mut typ = $suffix.to_string();
|
||||||
|
typ.get_mut(0..1).unwrap().make_ascii_uppercase();
|
||||||
|
let bad_suffix = if $suffix == "u8" { "i8" } else { "u8" };
|
||||||
|
let bad_type = if $suffix == "u8" { "I8" } else { "U8" };
|
||||||
|
let carets = "^".repeat(number.len() + $suffix.len());
|
||||||
|
let kind = match $suffix {
|
||||||
|
"dec"|"f32"|"f64" => "floats",
|
||||||
|
_ => "integers",
|
||||||
|
};
|
||||||
|
|
||||||
|
report_problem_as(
|
||||||
|
&format!(indoc!(
|
||||||
|
r#"
|
||||||
|
when {}{} is
|
||||||
|
{}{} -> 1
|
||||||
|
_ -> 1
|
||||||
|
"#
|
||||||
|
), number, bad_suffix, number, $suffix),
|
||||||
|
&format!(indoc!(
|
||||||
|
r#"
|
||||||
|
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
The 1st pattern in this `when` is causing a mismatch:
|
||||||
|
|
||||||
|
2│ {}{} -> 1
|
||||||
|
{}
|
||||||
|
|
||||||
|
The first pattern is trying to match {}:
|
||||||
|
|
||||||
|
{}
|
||||||
|
|
||||||
|
But the expression between `when` and `is` has the type:
|
||||||
|
|
||||||
|
{}
|
||||||
|
"#
|
||||||
|
), number, $suffix, carets, kind, typ, bad_type),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)*}
|
||||||
|
}
|
||||||
|
|
||||||
|
mismatched_suffix_tests_in_pattern! {
|
||||||
|
1, "u8", mismatched_suffix_u8_pattern
|
||||||
|
1, "u16", mismatched_suffix_u16_pattern
|
||||||
|
1, "u32", mismatched_suffix_u32_pattern
|
||||||
|
1, "u64", mismatched_suffix_u64_pattern
|
||||||
|
1, "u128", mismatched_suffix_u128_pattern
|
||||||
|
1, "i8", mismatched_suffix_i8_pattern
|
||||||
|
1, "i16", mismatched_suffix_i16_pattern
|
||||||
|
1, "i32", mismatched_suffix_i32_pattern
|
||||||
|
1, "i64", mismatched_suffix_i64_pattern
|
||||||
|
1, "i128", mismatched_suffix_i128_pattern
|
||||||
|
1, "nat", mismatched_suffix_nat_pattern
|
||||||
|
1, "dec", mismatched_suffix_dec_pattern
|
||||||
|
1, "f32", mismatched_suffix_f32_pattern
|
||||||
|
1, "f64", mismatched_suffix_f64_pattern
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bad_numeric_literal_suffix() {
|
fn bad_numeric_literal_suffix() {
|
||||||
report_problem_as(
|
report_problem_as(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue