force interpolated variables to be of type string

This commit is contained in:
Folkert 2024-01-30 14:26:12 +01:00
parent fec42d8654
commit 21b540751a
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
3 changed files with 72 additions and 11 deletions

View File

@ -2600,10 +2600,38 @@ fn flatten_str_lines<'a>(
fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) -> Expr { fn desugar_str_segments(var_store: &mut VarStore, segments: Vec<StrSegment>) -> Expr {
use StrSegment::*; use StrSegment::*;
let n = segments.len();
let mut iter = segments.into_iter().rev(); let mut iter = segments.into_iter().rev();
let mut loc_expr = match iter.next() { let mut loc_expr = match iter.next() {
Some(Plaintext(string)) => Loc::at(Region::zero(), Expr::Str(string)), Some(Plaintext(string)) => Loc::at(Region::zero(), Expr::Str(string)),
Some(Interpolation(loc_expr)) => loc_expr, Some(Interpolation(loc_expr)) => {
if n == 1 {
// We concat with the empty string to ensure a type error when loc_expr is not a string
let empty_string = Loc::at(Region::zero(), Expr::Str("".into()));
let fn_expr = Loc::at(
Region::zero(),
Expr::Var(Symbol::STR_CONCAT, var_store.fresh()),
);
let expr = Expr::Call(
Box::new((
var_store.fresh(),
fn_expr,
var_store.fresh(),
var_store.fresh(),
)),
vec![
(var_store.fresh(), empty_string),
(var_store.fresh(), loc_expr),
],
CalledVia::StringInterpolation,
);
Loc::at(Region::zero(), expr)
} else {
loc_expr
}
}
None => { None => {
// No segments? Empty string! // No segments? Empty string!

View File

@ -1,10 +1,14 @@
procedure Str.3 (#Attr.2, #Attr.3):
let Str.251 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.251;
procedure Test.1 (Test.5): procedure Test.1 (Test.5):
let Test.16 : [C {}, C U64, C Str] = TagId(0) Test.5; let Test.16 : [C {}, C U64, C Str] = TagId(0) Test.5;
ret Test.16; ret Test.16;
procedure Test.1 (Test.5): procedure Test.1 (Test.5):
let Test.30 : [C {}, C U64, C Str] = TagId(1) Test.5; let Test.31 : [C {}, C U64, C Str] = TagId(1) Test.5;
ret Test.30; ret Test.31;
procedure Test.2 (Test.7): procedure Test.2 (Test.7):
let Test.23 : [C {}, C U64, C Str] = TagId(2) Test.7; let Test.23 : [C {}, C U64, C Str] = TagId(2) Test.7;
@ -16,13 +20,16 @@ procedure Test.6 (Test.17, #Attr.12):
ret Test.19; ret Test.19;
procedure Test.6 (Test.17, #Attr.12): procedure Test.6 (Test.17, #Attr.12):
let Test.34 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12; let Test.35 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12;
let Test.33 : Str = ""; let Test.34 : Str = "";
ret Test.33; ret Test.34;
procedure Test.8 (Test.24, #Attr.12): procedure Test.8 (Test.24, #Attr.12):
let Test.27 : Str = UnionAtIndex (Id 2) (Index 0) #Attr.12; let Test.28 : Str = UnionAtIndex (Id 2) (Index 0) #Attr.12;
ret Test.27; let Test.27 : Str = "";
let Test.26 : Str = CallByName Str.3 Test.27 Test.28;
dec Test.28;
ret Test.26;
procedure Test.0 (): procedure Test.0 ():
let Test.3 : U8 = 0u8; let Test.3 : U8 = 0u8;
@ -55,7 +62,7 @@ procedure Test.0 ():
jump Test.13 Test.21; jump Test.13 Test.21;
default: default:
let Test.29 : U64 = 1i64; let Test.30 : U64 = 1i64;
let Test.28 : [C {}, C U64, C Str] = CallByName Test.1 Test.29; let Test.29 : [C {}, C U64, C Str] = CallByName Test.1 Test.30;
jump Test.13 Test.28; jump Test.13 Test.29;

View File

@ -813,6 +813,32 @@ fn list_get_negative_index() {
); );
} }
#[cfg(not(feature = "wasm"))] // TODO: mismatch is due to terminal control codes!
#[test]
fn invalid_string_interpolation() {
expect_failure(
"\"$(123)\"",
indoc!(
r#"
TYPE MISMATCH
This argument to this string interpolation has an unexpected type:
4 "$(123)"
^^^
The argument is a number of type:
Num *
But this string interpolation needs its argument to be:
Str
"#
),
);
}
#[test] #[test]
fn issue_2149_i8_ok() { fn issue_2149_i8_ok() {
expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]"); expect_success(r#"Str.toI8 "127""#, "Ok 127 : Result I8 [InvalidNumStr]");