Skip to content

Commit 344f4ff

Browse files
committed
Fix checked interpolation default reachability
1 parent 19fd252 commit 344f4ff

3 files changed

Lines changed: 30 additions & 8 deletions

File tree

src/check/checked_artifact.zig

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,29 @@ pub const ModuleEnvStorage = union(enum) {
8080
}
8181
};
8282

83-
fn moduleExprIsBuiltinStr(module: TypedCIR.Module, expr_idx: CIR.Expr.Idx) bool {
83+
fn moduleExprUsesBuiltinStrInterpolationPath(module: TypedCIR.Module, expr_idx: CIR.Expr.Idx) bool {
8484
const resolved = module.typeStoreConst().resolveVar(module.exprType(expr_idx));
85-
const nominal = resolved.desc.content.unwrapNominalType() orelse return false;
86-
if (!nominal.originIsBuiltin()) return false;
87-
const ident = nominal.ident.ident_idx;
88-
const common = module.commonIdents();
89-
return ident.eql(common.str) or ident.eql(common.builtin_str);
85+
switch (resolved.desc.content) {
86+
.structure => |flat_type| {
87+
if (flat_type != .nominal_type) return false;
88+
const nominal = flat_type.nominal_type;
89+
if (!nominal.originIsBuiltin()) return false;
90+
const ident = nominal.ident.ident_idx;
91+
const common = module.commonIdents();
92+
return ident.eql(common.str) or ident.eql(common.builtin_str);
93+
},
94+
.flex => |flex| {
95+
const phase = numericDefaultPhaseForFlex(module, flex) orelse return false;
96+
return phase == .mono_specialization_str;
97+
},
98+
.rigid => |rigid| {
99+
const phase = numericDefaultPhaseForConstraints(module, rigid.constraints) orelse return false;
100+
return phase == .mono_specialization_str;
101+
},
102+
.alias,
103+
.err,
104+
=> return false,
105+
}
90106
}
91107

92108
/// Public `CheckedModuleArtifactKey` declaration.
@@ -1454,7 +1470,8 @@ pub const NumericDefaultPhase = enum {
14541470
/// Defaults to Dec when still unresolved at monomorphic specialization.
14551471
mono_specialization,
14561472
/// Defaults to Str when still unresolved at monomorphic specialization
1457-
/// (string literals carrying a from_quote constraint).
1473+
/// (string literals carrying a from_quote constraint, and interpolated
1474+
/// string literals carrying a from_interpolation constraint).
14581475
mono_specialization_str,
14591476
};
14601477

@@ -5414,7 +5431,7 @@ const CheckedSourceNodes = struct {
54145431
.e_interpolation => |interpolation| {
54155432
try self.markExpr(interpolation.first, work);
54165433
try self.markExprSpan(module, interpolation.parts, work);
5417-
if (!moduleExprIsBuiltinStr(module, expr_idx)) {
5434+
if (!moduleExprUsesBuiltinStrInterpolationPath(module, expr_idx)) {
54185435
try self.markExpr(interpolation.rest, work);
54195436
}
54205437
},

src/cli/test/parallel_cli_runner.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ const subcommand_cases = [_]CliCase{
618618
.{ .id = 0, .suite = .subcommands, .name = "roc check succeeds with unused app package shorthand (issue 9488)", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/cli/package_shorthand_check_app/main.roc", .exit = .success, .not_contains = &.{.{ .stream = .stderr, .text = "panic" }} } } },
619619
.{ .id = 0, .suite = .subcommands, .name = "roc check resolves and checks a used sibling package shorthand (issue 9488)", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/cli/package_shorthand_used_app/main.roc", .exit = .not_panic, .contains = &.{ .{ .stream = .stderr, .text = "package_shorthand_used_pkg" }, .{ .stream = .stderr, .text = "TYPE MISMATCH" } }, .not_contains = &.{.{ .stream = .stderr, .text = "panic" }} } } },
620620
.{ .id = 0, .suite = .subcommands, .name = "roc check does not hang on tag union type alias inside List (issue 9481)", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/cli/tag_union_alias_hang.roc", .not_contains = &.{ .{ .stream = .stderr, .text = "panic" }, .{ .stream = .stderr, .text = "Coordinator stuck" }, .{ .stream = .stderr, .text = "Infinite loop" }, .{ .stream = .stderr, .text = "INFINITE TYPE" } } } } },
621+
.{ .id = 0, .suite = .subcommands, .name = "roc check succeeds on string interpolation in Try.map_err (issue 9650)", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/cli/issue_9650_checked_interpolation_map_err.roc", .exit = .success, .contains_any = &.{.{ .needles = &no_errors_needles }}, .not_contains = &.{ .{ .stream = .stderr, .text = "ordinary method call reached artifact publication" }, .{ .stream = .stderr, .text = "panic" } } } } },
621622
.{ .id = 0, .suite = .subcommands, .name = "roc check succeeds on Parser type module", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/package_simple_parser/Parser.roc", .not_contains = &.{.{ .stream = .stderr, .text = "error" }} } } },
622623
.{ .id = 0, .suite = .subcommands, .name = "roc check succeeds when block-local associated value captures local value", .body = .{ .command = .{ .args = &.{ "check", "--no-cache" }, .roc_file = "test/cli/block_local_assoc_capture/Test.roc", .exit = .success } } },
623624
.{ .id = 0, .suite = .subcommands, .name = "roc test runs expects in Parser type module (interpreter)", .backend = .interpreter, .body = .{ .command = .{ .args = &.{ "test", "--opt=interpreter", "--no-cache" }, .roc_file = "test/package_simple_parser/Parser.roc", .contains = &.{ .{ .stream = .stdout, .text = "passed" }, .{ .stream = .stdout, .text = "(7)" } } } } },
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package [f] {}
2+
3+
f : Str -> Try(U64, Str)
4+
f = |s| Try.map_err(Err("${(s)}"), |_| "")

0 commit comments

Comments
 (0)