diff --git a/design.md b/design.md index 6f551ab9319..a50ac8a7424 100644 --- a/design.md +++ b/design.md @@ -872,8 +872,8 @@ concrete monomorphic dispatcher type has already determined the owner. A numeric literal whose target type is a non-builtin nominal type converts through that type's `from_numeral` method, and a string literal converts -through `from_quote` (receiving the literal's post-escape UTF-8 bytes as -`List(U8)`). Every such conversion with a concrete target type is a +through `from_quote` (receiving the literal's post-escape contents as `Str`). +Every such conversion with a concrete target type is a compile-time root (`numeral_conversion` / `quote_conversion`), no matter where the literal sits in the AST: checking finalization evaluates the raw dispatch call, stores its `Try` result through `ConstStore`, unwraps `Ok` into @@ -901,20 +901,53 @@ encoding. ### String Interpolation -An interpolated string literal is canonicalization sugar. It desugars into -ordinary CIR: the interpolated expressions bind to locals in source order, -each literal segment stays a real string literal (so each converts through -`from_quote`), and the result is -`seg0.from_interpolation([].iter().prepended((interp_n, seg_n+1))...)` — the -iterator yields each interpolated value paired with the literal segment that -follows it. `from_interpolation : val, Iter((interpolated, val)) -> val` is an -ordinary method: each implementing type chooses its `interpolated` type (`Str` -chooses `Str`; a `Url`-style type can interpolate `Str` rather than itself), -and a type that needs to validate assembled values simply does not implement -it. The synthesized call node is recorded so checking unifies the call result -with the receiver, pinning the literal's target type from the use site before -string defaulting runs. No post-canonicalization stage knows interpolation -exists. +An interpolated string literal is its own CIR expression. It is not +desugared as receiver method-call syntax, because interpolation method +selection is owned by the expression result type, not by the first literal +segment. The interpolated expressions bind to locals in source order. Literal +segments are always builtin `Str` values, and the interpolation expression +passes the first segment plus an `Iter((interpolated, Str))` of the remaining +interpolated values paired with the literal segment that follows each one. + +For an unsuffixed interpolation, checking gives the expression this type: + +```roc +val where [ + val.from_interpolation : Str, Iter((_interpolated, Str)) -> val, +] +``` + +The static dispatch owner is `val`, the interpolation result type. If `val` +remains unconstrained, it defaults to `Str`, which selects: + +```roc +Str.from_interpolation : Str, Iter((Str, Str)) -> Str +``` + +Types that want checked interpolation through `Try` implement their own +`from_interpolation` and rely on `Try` forwarding: + +```roc +Try.from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err) + where [ + ok.from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err), + ] +``` + +For a suffixed interpolation such as `"a${x}b".Regex`, the suffix is not a +static-dispatch owner. It is a direct associated-function call to +`Regex.from_interpolation`; the function's argument types constrain the +literal segments and interpolated expressions, and the function's return type is +the type of the whole interpolation expression. Missing suffixed interpolation +functions are reported as missing associated functions on the suffix type. + +Interpolation deliberately does not parameterize literal segments over an +arbitrary `literal` type with a `literal.from_quote` constraint. That design +would defer quoted-segment conversion errors until monomorphic specializations +are known. `roc check` must report all compile-time conversion errors without +monomorphizing the program, so interpolation segments use builtin `Str` +directly. Normal non-interpolated quoted literals still convert through +`from_quote` as described above. ## Shared Post-Check Model diff --git a/src/build/roc/Builtin.roc b/src/build/roc/Builtin.roc index 93a68c49b42..58bbf3be184 100644 --- a/src/build/roc/Builtin.roc +++ b/src/build/roc/Builtin.roc @@ -333,20 +333,15 @@ Builtin :: [].{ ## ``` from_utf8 : List(U8) -> Try(Str, [BadUtf8({ problem : Str.Utf8Problem, index : U64 }), ..]) - ## Converts the UTF-8 bytes of a string literal to a [Str]. + ## Converts a string literal to a [Str]. ## ## The compiler calls this when a string literal's type is [Str], passing - ## the literal's bytes after escape processing. It can also be called - ## directly, in which case invalid UTF-8 returns `Err`. + ## the literal's contents after escape processing. ## ```roc - ## expect Str.from_quote([82, 111, 99]) == Ok("Roc") - ## expect Str.from_quote([255]).is_err() + ## expect Str.from_quote("Roc") == Ok("Roc") ## ``` - from_quote : List(U8) -> Try(Str, [BadQuotedBytes(Str)]) - from_quote = |bytes| match Str.from_utf8(bytes) { - Ok(str) => Ok(str) - Err(_) => Err(BadQuotedBytes("the bytes were not valid UTF-8")) - } + from_quote : Str -> Try(Str, [BadQuotedBytes(Str)]) + from_quote = |str| Ok(str) ## Assembles an interpolated string literal. ## @@ -490,9 +485,8 @@ Builtin :: [].{ ## Returns an iterator that yields the given item first, followed by ## everything the given iterator yields. ## - ## The compiler uses this to assemble the iterator it passes to a type's - ## `from_interpolation` method when an interpolated string literal - ## targets that type. + ## The compiler uses this to assemble the iterator it passes to + ## `from_interpolation` when checking an interpolated string literal. ## ```roc ## expect Iter.fold([2, 3].iter().prepended(1), [], |acc, item| acc.append(item)) == [1, 2, 3] ## ``` @@ -1899,6 +1893,18 @@ Builtin :: [].{ Err(_) => True } + ## Forwards interpolated string literal assembly through an inner type + ## whose `from_interpolation` method returns the same [Try]. + from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err) + where [ + ok.from_interpolation : Str, Iter((interpolated, Str)) -> Try(ok, err), + ] + from_interpolation = |first, rest| { + OkType : ok + + OkType.from_interpolation(first, rest) + } + ## If the result is `Ok`, returns the value it holds. Otherwise, returns ## the given default value. ## diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index 75b1dc183f8..0c3dbced9e0 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -12425,25 +12425,24 @@ fn processEscapeSequences(allocator: std.mem.Allocator, input: []const u8) std.m return result.toOwnedSlice(allocator); } -/// Helper function to create a string literal expression and add it to the scratch stack -/// Desugar an interpolated string literal into ordinary CIR: +/// Canonicalize an interpolated string literal. /// /// ```roc /// "a${x}b${y}c" /// ``` -/// becomes +/// becomes a block which evaluates interpolated expressions in source order and +/// finishes with a result-owned interpolation dispatch: /// ```roc /// { /// #interp_0 = x /// #interp_1 = y -/// "a".from_interpolation([].iter().prepended((#interp_1, "c")).prepended((#interp_0, "b"))) +/// /// } /// ``` /// The interpolated expressions bind to locals first so they evaluate in /// source order; the iterator yields each interpolated value paired with the -/// literal segment that follows it. Every literal segment stays a real string -/// literal expression, so each converts through `from_quote` like any other, -/// and the receiver's type suffix (when present) pins the target type. +/// literal `Str` segment that follows it. With a type suffix, the final +/// expression is a direct call to `Suffix.from_interpolation(first, rest)`. fn desugarInterpolatedString( self: *Self, span: CIR.Expr.Span, @@ -12508,7 +12507,8 @@ fn desugarInterpolatedString( } const stmts_span = try self.env.store.statementSpanFrom(stmts_top); - // Wrap each literal segment in its own string expression. + // Interpolation segments are always builtin Str, so keep them as raw + // string-segment expressions instead of wrapping them in quote literals. const seg_exprs = try gpa.alloc(Expr.Idx, segments.items.len); defer gpa.free(seg_exprs); for (segments.items, 0..) |maybe_segment, i| { @@ -12518,18 +12518,7 @@ fn desugarInterpolatedString( .literal = empty_literal, } }, region); }; - const seg_region = self.env.store.getNodeRegion(ModuleEnv.nodeIdxFrom(segment_idx)); - const seg_scratch_top = self.env.store.scratchExprTop(); - try self.env.store.addScratchExpr(segment_idx); - const seg_span = try self.env.store.exprSpanFrom(seg_scratch_top); - seg_exprs[i] = try self.env.addExpr(CIR.Expr{ .e_str = .{ - .span = seg_span, - } }, seg_region); - } - - // The receiver's type suffix (e.g. `"a${x}b".MyType`) pins the target type. - if (type_ident) |suffix_ident| { - try self.recordTypedNumericSuffix(seg_exprs[0], suffix_ident); + seg_exprs[i] = segment_idx; } const iter_method = try self.env.insertIdent(Ident.for_text("iter")); @@ -12539,6 +12528,8 @@ fn desugarInterpolatedString( // [].iter() const empty_list_idx = try self.env.addExpr(CIR.Expr{ .e_empty_list = .{} }, region); var chain_idx = try self.addSyntheticMethodCall(empty_list_idx, iter_method, &.{}, region); + const part_exprs = try gpa.alloc(Expr.Idx, interps.items.len * 2); + defer gpa.free(part_exprs); // Prepend (interpolation, following-segment) pairs back to front so the // iterator yields them in source order. @@ -12549,6 +12540,8 @@ fn desugarInterpolatedString( const tmp_lookup_idx = try self.env.addExpr(CIR.Expr{ .e_lookup_local = .{ .pattern_idx = tmp_patterns[pair_i], } }, interp_region); + part_exprs[pair_i * 2] = tmp_lookup_idx; + part_exprs[pair_i * 2 + 1] = seg_exprs[pair_i + 1]; const elems_top = self.env.store.scratchExprTop(); try self.env.store.addScratchExpr(tmp_lookup_idx); try self.env.store.addScratchExpr(seg_exprs[pair_i + 1]); @@ -12558,13 +12551,35 @@ fn desugarInterpolatedString( } }, interp_region); chain_idx = try self.addSyntheticMethodCall(chain_idx, prepended_method, &.{pair_idx}, interp_region); } + const parts_span = try self.env.store.appendExprSpan(part_exprs); + + const final_idx = if (type_ident) |suffix_ident| suffix_blk: { + const fn_expr = try self.canonicalizeTypeAssociatedLookup(suffix_ident, from_interpolation_method, region) orelse + try self.canonicalizedMalformedExpr(Diagnostic{ .undeclared_type = .{ + .name = suffix_ident, + .region = region, + } }); + + const args_top = self.env.store.scratchExprTop(); + try self.env.store.addScratchExpr(seg_exprs[0]); + try self.env.store.addScratchExpr(chain_idx); + const args_span = try self.env.store.exprSpanFrom(args_top); - const call_idx = try self.addSyntheticMethodCall(seg_exprs[0], from_interpolation_method, &.{chain_idx}, region); - try self.env.recordInterpolationCallNode(ModuleEnv.nodeIdxFrom(call_idx)); + break :suffix_blk try self.env.addExpr(CIR.Expr{ .e_call = .{ + .func = fn_expr.idx, + .args = args_span, + .called_via = CalledVia.apply, + } }, region); + } else try self.env.addExpr(CIR.Expr{ .e_interpolation = .{ + .first = seg_exprs[0], + .parts = parts_span, + .rest = chain_idx, + .method_name_region = region, + } }, region); return try self.env.addExpr(CIR.Expr{ .e_block = .{ .stmts = stmts_span, - .final_expr = call_idx, + .final_expr = final_idx, } }, region); } diff --git a/src/canonicalize/DependencyGraph.zig b/src/canonicalize/DependencyGraph.zig index d01f427b7d5..62b8cee4bc5 100644 --- a/src/canonicalize/DependencyGraph.zig +++ b/src/canonicalize/DependencyGraph.zig @@ -193,6 +193,12 @@ fn collectExprDependencies( } try pending.append(stack_allocator, call.receiver); }, + .e_interpolation => |interpolation| { + for (cir.store.sliceExpr(interpolation.parts)) |part_idx| { + try pending.append(stack_allocator, part_idx); + } + try pending.append(stack_allocator, interpolation.first); + }, .e_structural_eq => |eq| { try pending.append(stack_allocator, eq.rhs); try pending.append(stack_allocator, eq.lhs); diff --git a/src/canonicalize/Expression.zig b/src/canonicalize/Expression.zig index 7f3ba15b44b..52b57495312 100644 --- a/src/canonicalize/Expression.zig +++ b/src/canonicalize/Expression.zig @@ -357,6 +357,25 @@ pub const Expr = union(enum) { args: Expr.Span, constraint_fn_var: TypeVar, }, + /// Compiler-created interpolation dispatch. + /// + /// Unlike an ordinary method call, this dispatch is owned by the result + /// type of the whole interpolation expression. Runtime arguments are the + /// first `Str` segment and the iterator of interpolated values paired with + /// following `Str` segments. + e_interpolation: struct { + first: Expr.Idx, + /// Flat `(interpolated, following_segment)` pairs. The span length is + /// always even, with `following_segment` expressions already typed as + /// builtin `Str` segments. + parts: Expr.Span, + /// Synthetic iterator chain for the custom-dispatch path. The builtin + /// `Str` path consumes `parts` directly and does not check or lower + /// this expression. + rest: Expr.Idx, + method_name_region: base.Region, + constraint_fn_var: ?TypeVar = null, + }, /// Structural equality chosen explicitly by the checker. /// /// This is not method dispatch. It represents the semantic case where @@ -1261,6 +1280,36 @@ pub const Expr = union(enum) { try tree.endNode(begin, attrs); }, + .e_interpolation => |e| { + const begin = tree.beginNode(); + try tree.pushStaticAtom("e-interpolation"); + const region = ir.store.getExprRegion(expr_idx); + try ir.appendRegionInfoToSExprTreeFromRegion(tree, region); + if (e.constraint_fn_var) |constraint_fn_var| { + try tree.pushU64Pair("constraint-fn-var", @intFromEnum(constraint_fn_var)); + } + const attrs = tree.beginNode(); + + { + const first_begin = tree.beginNode(); + try tree.pushStaticAtom("first"); + const first_attrs = tree.beginNode(); + try ir.store.getExpr(e.first).pushToSExprTree(ir, tree, e.first); + try tree.endNode(first_begin, first_attrs); + } + + { + const parts_begin = tree.beginNode(); + try tree.pushStaticAtom("parts"); + const parts_attrs = tree.beginNode(); + for (ir.store.sliceExpr(e.parts)) |part_idx| { + try ir.store.getExpr(part_idx).pushToSExprTree(ir, tree, part_idx); + } + try tree.endNode(parts_begin, parts_attrs); + } + + try tree.endNode(begin, attrs); + }, .e_structural_eq => |e| { const begin = tree.beginNode(); try tree.pushStaticAtom("e-structural-eq"); diff --git a/src/canonicalize/ModuleEnv.zig b/src/canonicalize/ModuleEnv.zig index eebbe6a2691..85c3e0681ef 100644 --- a/src/canonicalize/ModuleEnv.zig +++ b/src/canonicalize/ModuleEnv.zig @@ -190,6 +190,7 @@ pub const CommonIdents = extern struct { err: Ident.Idx, from_numeral: Ident.Idx, from_quote: Ident.Idx, + from_interpolation: Ident.Idx, true_tag: Ident.Idx, false_tag: Ident.Idx, // from_utf8 result fields @@ -289,6 +290,7 @@ pub const CommonIdents = extern struct { .err = try common.insertIdent(gpa, Ident.for_text("Err")), .from_numeral = try common.insertIdent(gpa, Ident.for_text("from_numeral")), .from_quote = try common.insertIdent(gpa, Ident.for_text("from_quote")), + .from_interpolation = try common.insertIdent(gpa, Ident.for_text("from_interpolation")), .true_tag = try common.insertIdent(gpa, Ident.for_text("True")), .false_tag = try common.insertIdent(gpa, Ident.for_text("False")), // from_utf8 result fields @@ -391,6 +393,7 @@ pub const CommonIdents = extern struct { .err = common.findIdent("Err") orelse unreachable, .from_numeral = common.findIdent("from_numeral") orelse unreachable, .from_quote = common.findIdent("from_quote") orelse unreachable, + .from_interpolation = common.findIdent("from_interpolation") orelse unreachable, .true_tag = common.findIdent("True") orelse unreachable, .false_tag = common.findIdent("False") orelse unreachable, // from_utf8 result fields @@ -642,11 +645,6 @@ numeral_dispatch_plans: NumeralDispatchPlan.SafeList, /// expression and pattern nodes. Shares `NumeralDispatchPlan`'s shape: a source /// node plus the constraint's target and function type vars. quote_dispatch_plans: NumeralDispatchPlan.SafeList, -/// Raw node indices of the `from_interpolation` calls canonicalization -/// synthesized while desugaring interpolated string literals. The -/// from_interpolation protocol returns the receiver's type, and checking -/// consumes this to unify the call result with the receiver. -interpolation_call_nodes: collections.SafeList(u32), /// Scope-resolved explicit numeric suffix targets attached by canonicalization. numeric_suffix_types: NumericSuffixType.SafeList, @@ -806,7 +804,6 @@ pub fn init(gpa: std.mem.Allocator, source: []const u8) std.mem.Allocator.Error! .numeral_literals = try NumeralLiteral.SafeList.initCapacity(gpa, 8), .numeral_dispatch_plans = try NumeralDispatchPlan.SafeList.initCapacity(gpa, 8), .quote_dispatch_plans = try NumeralDispatchPlan.SafeList.initCapacity(gpa, 8), - .interpolation_call_nodes = try collections.SafeList(u32).initCapacity(gpa, 4), .numeric_suffix_types = try NumericSuffixType.SafeList.initCapacity(gpa, 8), }; } @@ -829,7 +826,6 @@ pub fn deinit(self: *Self) void { self.numeral_literals.deinit(self.gpa); self.numeral_dispatch_plans.deinit(self.gpa); self.quote_dispatch_plans.deinit(self.gpa); - self.interpolation_call_nodes.deinit(self.gpa); self.numeric_suffix_types.deinit(self.gpa); // diagnostics are stored in the NodeStore, no need to free separately self.store.deinit(); @@ -871,7 +867,6 @@ pub fn deinitCachedModule(self: *Self) void { self.numeral_literals.deinit(self.gpa); self.numeral_dispatch_plans.deinit(self.gpa); self.quote_dispatch_plans.deinit(self.gpa); - self.interpolation_call_nodes.deinit(self.gpa); self.numeric_suffix_types.deinit(self.gpa); // If enableRuntimeInserts was called on the interner, it allocated new memory @@ -3025,7 +3020,6 @@ pub const Serialized = extern struct { numeral_literals: NumeralLiteral.SafeList.Serialized, numeral_dispatch_plans: NumeralDispatchPlan.SafeList.Serialized, quote_dispatch_plans: NumeralDispatchPlan.SafeList.Serialized, - interpolation_call_nodes: collections.SafeList(u32).Serialized, numeric_suffix_types: NumericSuffixType.SafeList.Serialized, // Reserved space (was is_lambda_lifted and is_defunctionalized, now unused) _reserved_flags: [2]u8 = .{ 0, 0 }, @@ -3089,7 +3083,6 @@ pub const Serialized = extern struct { try self.numeral_literals.serialize(&env.numeral_literals, allocator, writer); try self.numeral_dispatch_plans.serialize(&env.numeral_dispatch_plans, allocator, writer); try self.quote_dispatch_plans.serialize(&env.quote_dispatch_plans, allocator, writer); - try self.interpolation_call_nodes.serialize(&env.interpolation_call_nodes, allocator, writer); try self.numeric_suffix_types.serialize(&env.numeric_suffix_types, allocator, writer); self._reserved_flags = .{ 0, 0 }; @@ -3144,7 +3137,6 @@ pub const Serialized = extern struct { .numeral_literals = self.numeral_literals.deserializeInto(base_addr), .numeral_dispatch_plans = self.numeral_dispatch_plans.deserializeInto(base_addr), .quote_dispatch_plans = self.quote_dispatch_plans.deserializeInto(base_addr), - .interpolation_call_nodes = self.interpolation_call_nodes.deserializeInto(base_addr), .numeric_suffix_types = self.numeric_suffix_types.deserializeInto(base_addr), }; @@ -3202,7 +3194,6 @@ pub const Serialized = extern struct { .numeral_literals = try self.numeral_literals.deserializeWithCopy(base_addr, gpa), .numeral_dispatch_plans = try self.numeral_dispatch_plans.deserializeWithCopy(base_addr, gpa), .quote_dispatch_plans = try self.quote_dispatch_plans.deserializeWithCopy(base_addr, gpa), - .interpolation_call_nodes = try self.interpolation_call_nodes.deserializeWithCopy(base_addr, gpa), .numeric_suffix_types = try self.numeric_suffix_types.deserializeWithCopy(base_addr, gpa), }; @@ -3382,122 +3373,6 @@ pub fn quoteDispatchPlanForNode(self: *const Self, node_idx: Node.Idx) ?NumeralD return null; } -/// Record a `from_interpolation` call synthesized by interpolation desugaring. -pub fn recordInterpolationCallNode(self: *Self, node_idx: Node.Idx) std.mem.Allocator.Error!void { - _ = try self.interpolation_call_nodes.append(self.gpa, @intFromEnum(node_idx)); -} - -/// Whether the node is a `from_interpolation` call synthesized by -/// interpolation desugaring. -pub fn isInterpolationCallNode(self: *const Self, node_idx: Node.Idx) bool { - const raw_node: u32 = @intFromEnum(node_idx); - for (self.interpolation_call_nodes.items.items) |recorded| { - if (recorded == raw_node) return true; - } - return false; -} - -/// Whether the expression is a desugared interpolation dispatch call whose -/// result type resolved to builtin `Str`. Such a call can be published as a -/// plain ordered segment list — equivalent to `Str.from_interpolation` — -/// instead of dispatching through the synthetic iterator chain. -pub fn isStrInterpolationCall(self: *const Self, expr_idx: CIR.Expr.Idx) bool { - if (!self.isInterpolationCallNode(nodeIdxFrom(expr_idx))) return false; - switch (self.store.getExpr(expr_idx)) { - .e_dispatch_call => {}, - else => return false, - } - var current = varFrom(expr_idx); - while (true) { - const resolved = self.types.resolveVar(current); - switch (resolved.desc.content) { - .alias => |alias| current = self.types.getAliasBackingVar(alias), - .structure => |flat| return switch (flat) { - .nominal_type => |nominal| nominal.originIsBuiltin() and - (nominal.ident.ident_idx.eql(self.idents.str) or - nominal.ident.ident_idx.eql(self.idents.builtin_str)), - else => false, - }, - else => return false, - } - } -} - -/// One `(interpolation, following-segment)` pair from the synthetic -/// `prepended` chain of a desugared interpolated string. -pub const InterpolationPair = struct { - interpolation: CIR.Expr.Idx, - segment: CIR.Expr.Idx, -}; - -/// Iterator yielding a desugared interpolated string's -/// `(interpolation, following-segment)` pairs in source order. -pub const InterpolationPairIterator = struct { - env: *const Self, - current: CIR.Expr.Idx, - - /// Next pair in source order, or null once the terminal `[].iter()` - /// call is reached. - pub fn next(self: *InterpolationPairIterator) ?InterpolationPair { - const call = switch (self.env.store.getExpr(self.current)) { - .e_dispatch_call => |call| call, - else => { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation chain expression is not a dispatch call", .{}); - } - unreachable; - }, - }; - const args = self.env.store.sliceExpr(call.args); - if (args.len == 0) return null; - if (args.len != 1) { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation chain call has {d} arguments", .{args.len}); - } - unreachable; - } - const elems = switch (self.env.store.getExpr(args[0])) { - .e_tuple => |tuple| self.env.store.sliceExpr(tuple.elems), - else => { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation chain argument is not a pair", .{}); - } - unreachable; - }, - }; - if (elems.len != 2) { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation pair has {d} elements", .{elems.len}); - } - unreachable; - } - self.current = call.receiver; - return .{ .interpolation = elems[0], .segment = elems[1] }; - } -}; - -/// Iterate the `(interpolation, following-segment)` pairs of a desugared -/// interpolation dispatch call in source order. -pub fn interpolationPairs(self: *const Self, call_expr_idx: CIR.Expr.Idx) InterpolationPairIterator { - const call = switch (self.store.getExpr(call_expr_idx)) { - .e_dispatch_call => |call| call, - else => { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation call expression is not a dispatch call", .{}); - } - unreachable; - }, - }; - const args = self.store.sliceExpr(call.args); - if (args.len != 1) { - if (builtin.mode == .Debug) { - std.debug.panic("module env invariant violated: interpolation call has {d} arguments", .{args.len}); - } - unreachable; - } - return .{ .env = self, .current = args[0] }; -} - /// Record the scope-resolved type target for an explicit numeric suffix. pub fn recordNumericSuffixType( self: *Self, diff --git a/src/canonicalize/Node.zig b/src/canonicalize/Node.zig index 1edb34162d2..1de577ac9e5 100644 --- a/src/canonicalize/Node.zig +++ b/src/canonicalize/Node.zig @@ -67,6 +67,7 @@ pub const Tag = enum { expr_field_access, expr_method_call, expr_dispatch_call, + expr_interpolation, expr_structural_eq, expr_method_eq, expr_type_method_call, @@ -310,6 +311,7 @@ pub const Payload = extern union { expr_field_access: ExprFieldAccess, expr_method_call: ExprMethodCall, expr_dispatch_call: ExprDispatchCall, + expr_interpolation: ExprInterpolation, expr_structural_eq: ExprStructuralEq, expr_method_eq: ExprMethodEq, expr_type_method_call: ExprTypeMethodCall, @@ -638,6 +640,13 @@ pub const Payload = extern union { constraint_fn_var: u32, }; + pub const ExprInterpolation = extern struct { + first: u32, + parts_rest_idx: u32, // Index into span_with_node_data: (parts.start, parts.len, rest) + method_name_region_span2_idx: u32, + constraint_fn_var_plus_one: u32, + }; + pub const ExprStructuralEq = extern struct { lhs: u32, rhs: u32, diff --git a/src/canonicalize/NodeStore.zig b/src/canonicalize/NodeStore.zig index 1e76ce5308b..ae39ac5860c 100644 --- a/src/canonicalize/NodeStore.zig +++ b/src/canonicalize/NodeStore.zig @@ -371,7 +371,7 @@ pub fn relocate(store: *NodeStore, offset: isize) void { /// Count of the diagnostic nodes in the ModuleEnv pub const MODULEENV_DIAGNOSTIC_NODE_COUNT = 77; /// Count of the expression nodes in the ModuleEnv -pub const MODULEENV_EXPR_NODE_COUNT = 52; +pub const MODULEENV_EXPR_NODE_COUNT = 53; /// Count of the statement nodes in the ModuleEnv pub const MODULEENV_STATEMENT_NODE_COUNT = 17; /// Count of the type annotation nodes in the ModuleEnv @@ -1074,6 +1074,27 @@ pub fn getExpr(store: *const NodeStore, expr: CIR.Expr.Idx) CIR.Expr { .constraint_fn_var = @enumFromInt(p.constraint_fn_var), } }; }, + .expr_interpolation => { + const p = payload.expr_interpolation; + const region_span = store.span2_data.items.items[p.method_name_region_span2_idx]; + const parts_rest = store.span_with_node_data.items.items[p.parts_rest_idx]; + return CIR.Expr{ .e_interpolation = .{ + .first = @enumFromInt(p.first), + .parts = .{ .span = .{ + .start = parts_rest.start, + .len = parts_rest.len, + } }, + .rest = @enumFromInt(parts_rest.node), + .method_name_region = base.Region{ + .start = .{ .offset = region_span.start }, + .end = .{ .offset = region_span.len }, + }, + .constraint_fn_var = if (p.constraint_fn_var_plus_one == 0) + null + else + @enumFromInt(p.constraint_fn_var_plus_one - 1), + } }; + }, .expr_structural_eq => { const p = payload.expr_structural_eq; return CIR.Expr{ .e_structural_eq = .{ @@ -1269,6 +1290,38 @@ pub fn replaceExprWithDispatchCall( store.nodes.set(node_idx, node); } +/// Replaces an existing expression with checked interpolation dispatch metadata. +pub fn replaceExprWithInterpolationConstraint( + store: *NodeStore, + expr_idx: CIR.Expr.Idx, + first: CIR.Expr.Idx, + parts: CIR.Expr.Span, + rest: CIR.Expr.Idx, + method_name_region: Region, + constraint_fn_var: types.Var, +) Allocator.Error!void { + const node_idx: Node.Idx = @enumFromInt(@intFromEnum(expr_idx)); + const parts_rest_idx: u32 = @intCast(store.span_with_node_data.len()); + _ = try store.span_with_node_data.append(store.gpa, .{ + .start = parts.span.start, + .len = parts.span.len, + .node = @intFromEnum(rest), + }); + const region_span2_idx: u32 = @intCast(store.span2_data.len()); + _ = try store.span2_data.append(store.gpa, .{ + .start = method_name_region.start.offset, + .len = method_name_region.end.offset, + }); + var node = Node.init(.expr_interpolation); + node.setPayload(.{ .expr_interpolation = .{ + .first = @intFromEnum(first), + .parts_rest_idx = parts_rest_idx, + .method_name_region_span2_idx = region_span2_idx, + .constraint_fn_var_plus_one = @intFromEnum(constraint_fn_var) + 1, + } }); + store.nodes.set(node_idx, node); +} + /// Replaces an existing expression with unresolved type dispatch metadata. pub fn replaceExprWithTypeDispatchCall( store: *NodeStore, @@ -2259,6 +2312,29 @@ pub fn addExpr(store: *NodeStore, expr: CIR.Expr, region: base.Region) Allocator .constraint_fn_var = @intFromEnum(e.constraint_fn_var), } }); }, + .e_interpolation => |e| { + node.tag = .expr_interpolation; + const parts_rest_idx: u32 = @intCast(store.span_with_node_data.len()); + _ = try store.span_with_node_data.append(store.gpa, .{ + .start = e.parts.span.start, + .len = e.parts.span.len, + .node = @intFromEnum(e.rest), + }); + const region_span2_idx: u32 = @intCast(store.span2_data.len()); + _ = try store.span2_data.append(store.gpa, .{ + .start = e.method_name_region.start.offset, + .len = e.method_name_region.end.offset, + }); + node.setPayload(.{ .expr_interpolation = .{ + .first = @intFromEnum(e.first), + .parts_rest_idx = parts_rest_idx, + .method_name_region_span2_idx = region_span2_idx, + .constraint_fn_var_plus_one = if (e.constraint_fn_var) |var_| + @intFromEnum(var_) + 1 + else + 0, + } }); + }, .e_structural_eq => |e| { node.tag = .expr_structural_eq; node.setPayload(.{ .expr_structural_eq = .{ diff --git a/src/canonicalize/RocEmitter.zig b/src/canonicalize/RocEmitter.zig index 0a0018c1c48..54f81ea7ca4 100644 --- a/src/canonicalize/RocEmitter.zig +++ b/src/canonicalize/RocEmitter.zig @@ -387,6 +387,13 @@ fn emitExprFrame( try frames.append(allocator, .{ .write = "." }); try frames.append(allocator, .{ .expr = method_call.receiver }); }, + .e_interpolation => |interpolation| { + try frames.append(allocator, .{ .write = ")" }); + try pushExprList(frames, allocator, self.module_env.store.sliceExpr(interpolation.parts), "]", ", "); + try frames.append(allocator, .{ .write = ", [" }); + try frames.append(allocator, .{ .expr = interpolation.first }); + try frames.append(allocator, .{ .write = "(" }); + }, .e_structural_eq => |eq| { try frames.append(allocator, .{ .expr = eq.rhs }); try frames.append(allocator, .{ .write = if (eq.negated) " != " else " == " }); diff --git a/src/canonicalize/test/BuiltinTestContext.zig b/src/canonicalize/test/BuiltinTestContext.zig index 1c18568e478..80b2b60f7ee 100644 --- a/src/canonicalize/test/BuiltinTestContext.zig +++ b/src/canonicalize/test/BuiltinTestContext.zig @@ -80,7 +80,6 @@ fn loadCompiledModule(gpa: std.mem.Allocator, bin_data: []const u8, module_name: .numeral_literals = serialized_ptr.numeral_literals.deserializeInto(base_ptr), .numeral_dispatch_plans = serialized_ptr.numeral_dispatch_plans.deserializeInto(base_ptr), .quote_dispatch_plans = serialized_ptr.quote_dispatch_plans.deserializeInto(base_ptr), - .interpolation_call_nodes = serialized_ptr.interpolation_call_nodes.deserializeInto(base_ptr), .numeric_suffix_types = serialized_ptr.numeric_suffix_types.deserializeInto(base_ptr), }; diff --git a/src/canonicalize/test/node_store_test.zig b/src/canonicalize/test/node_store_test.zig index ee03d3c17cf..9a950c7039c 100644 --- a/src/canonicalize/test/node_store_test.zig +++ b/src/canonicalize/test/node_store_test.zig @@ -253,6 +253,15 @@ test "NodeStore round trip - Expressions" { .span = CIR.Expr.Span{ .span = rand_span() }, }, }); + try expressions.append(gpa, CIR.Expr{ + .e_interpolation = .{ + .first = rand_idx(CIR.Expr.Idx), + .parts = CIR.Expr.Span{ .span = rand_span() }, + .rest = rand_idx(CIR.Expr.Idx), + .method_name_region = rand_region(), + .constraint_fn_var = rand_idx(types.Var), + }, + }); try expressions.append(gpa, CIR.Expr{ .e_bytes_literal = .{ .literal = rand_idx(StringLiteral.Idx), diff --git a/src/check/Check.zig b/src/check/Check.zig index 54722d5c510..cbc9b6d20e6 100644 --- a/src/check/Check.zig +++ b/src/check/Check.zig @@ -113,6 +113,11 @@ builtin_types_copied: bool, ident_to_var_map: std.AutoHashMap(Ident.Idx, Var), /// Checker-local source-site mapping for method/equality rewrites. constraint_expr_by_fn_var: std.AutoHashMap(Var, CIR.Expr.Idx), +/// Interpolation synthetic iterator expressions checked for custom dispatch. +checked_interpolation_rests: std.AutoHashMap(Var, void), +/// When checking a custom interpolation's synthetic iterator, defer resolving +/// the dispatch constraints it creates until the surrounding dispatch pass. +defer_expr_static_dispatch_checks: bool, /// Dispatcher/method pairs already reported by `reportConstraintError`, so a /// constraint failing in multiple passes (or reachable through several aliased /// type variables) is reported once. @@ -231,6 +236,20 @@ const InstantiationDispatcher = struct { dispatcher_var: Var, }; +fn isLiteralStaticDispatchOrigin(origin: StaticDispatchConstraint.Origin) bool { + return switch (origin) { + .from_numeral, + .from_quote, + .from_interpolation, + => true, + .desugared_binop, + .desugared_unaryop, + .method_call, + .where_clause, + => false, + }; +} + /// Indicates if something has been processed or not const HasProcessed = enum { processed, processing, not_processed }; @@ -446,6 +465,8 @@ fn initAssumePrepared( .builtin_types_copied = false, .ident_to_var_map = std.AutoHashMap(Ident.Idx, Var).init(gpa), .constraint_expr_by_fn_var = std.AutoHashMap(Var, CIR.Expr.Idx).init(gpa), + .checked_interpolation_rests = std.AutoHashMap(Var, void).init(gpa), + .defer_expr_static_dispatch_checks = false, .reported_constraint_errors = std.AutoHashMap(ReportedConstraintError, void).init(gpa), .expect_region_by_constraint_fn_var = std.AutoHashMap(Var, Region).init(gpa), .current_expect_region = null, @@ -539,6 +560,7 @@ pub fn deinit(self: *Self) void { self.import_cache.deinit(self.gpa); self.ident_to_var_map.deinit(); self.constraint_expr_by_fn_var.deinit(); + self.checked_interpolation_rests.deinit(); self.reported_constraint_errors.deinit(); self.expect_region_by_constraint_fn_var.deinit(); self.top_level_ptrns.deinit(); @@ -922,7 +944,7 @@ fn instantiateVarHelp( var has_from_numeral = false; var has_non_from_numeral = false; for (constraints) |c| { - if (c.origin == .from_numeral or c.origin == .from_quote) { + if (isLiteralStaticDispatchOrigin(c.origin)) { has_from_numeral = true; } else { has_non_from_numeral = true; @@ -1618,8 +1640,8 @@ fn mkFlexWithFromNumeralConstraint( } /// Create a flex variable with a from_quote constraint for string literals. -/// The constraint's function type is `List(U8) -> Try(a, [BadQuotedBytes(Str)])`, -/// where the bytes are the literal's UTF-8 content after escape processing. +/// The constraint's function type is `Str -> Try(a, [BadQuotedBytes(Str)])`, +/// where the Str is the literal's content after escape processing. fn mkFlexWithFromQuoteConstraint( self: *Self, source_node: ?CIR.Node.Idx, @@ -1635,9 +1657,8 @@ fn mkFlexWithFromQuoteConstraint( const flex_rank = env.rank(); const flex_var = try self.freshFromContentAtRank(.{ .flex = Flex.init() }, env, region, flex_rank); - // Create the argument type: List(U8) - const u8_var = try self.freshFromContent(try self.mkNumberTypeContent(.u8, env), env, region); - const arg_var = try self.freshFromContent(try self.mkListContent(u8_var, env), env, region); + // Create the argument type: Str + const arg_var = try self.freshStr(env, region); // Create the error type: [BadQuotedBytes(Str)] (closed tag union) const str_var = self.str_var; @@ -2355,7 +2376,7 @@ fn reportAmbiguousStaticDispatchPerInstantiation( var first_constraint: ?StaticDispatchConstraint = null; var skip_receiver = false; for (constraints) |c| { - if (c.origin == .from_numeral or c.origin == .from_quote) { + if (isLiteralStaticDispatchOrigin(c.origin)) { skip_receiver = true; } else if (c.fn_name.eql(self.cir.idents.is_eq)) { continue; @@ -2520,7 +2541,7 @@ fn reportAmbiguousStaticDispatch( var first_constraint: ?StaticDispatchConstraint = null; for (constraints) |c| { switch (c.origin) { - .from_numeral, .from_quote, .where_clause => { + .from_numeral, .from_quote, .from_interpolation, .where_clause => { has_excluded_origin = true; }, .method_call, .desugared_binop, .desugared_unaryop => { @@ -6751,6 +6772,51 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, env: *Env, expected: Expected) } }); _ = try self.unify(expr_var, record_field_var, env); }, + .e_interpolation => |interpolation| { + self.checking_call_arg = true; + does_fx = try self.checkExpr(interpolation.first, env, Expected.none()) or does_fx; + const first_var = ModuleEnv.varFrom(interpolation.first); + var did_err = self.types.resolveVar(first_var).desc.content == .err; + + const parts = self.cir.store.sliceExpr(interpolation.parts); + std.debug.assert(parts.len % 2 == 0); + var part_i: usize = 0; + while (part_i < parts.len) : (part_i += 2) { + self.checking_call_arg = true; + does_fx = try self.checkExpr(parts[part_i], env, Expected.none()) or does_fx; + did_err = did_err or (self.types.resolveVar(ModuleEnv.varFrom(parts[part_i])).desc.content == .err); + + self.checking_call_arg = true; + does_fx = try self.checkExpr(parts[part_i + 1], env, Expected.none()) or does_fx; + did_err = did_err or (self.types.resolveVar(ModuleEnv.varFrom(parts[part_i + 1])).desc.content == .err); + } + + const rest_var = ModuleEnv.varFrom(interpolation.rest); + try self.setVarRank(rest_var, env); + + if (did_err) { + try self.unifyWith(expr_var, .err, env); + } else { + const arg_vars = [_]Var{ first_var, rest_var }; + const constraint_fn_var = try self.mkInterpolationConstraint( + expr_var, + &arg_vars, + expr_var, + self.cir.idents.from_interpolation, + env, + interpolation.method_name_region, + expr_idx, + ); + try self.cir.store.replaceExprWithInterpolationConstraint( + expr_idx, + interpolation.first, + interpolation.parts, + interpolation.rest, + interpolation.method_name_region, + constraint_fn_var, + ); + } + }, .e_method_call => |method_call| { does_fx = try self.checkExpr(method_call.receiver, env, Expected.none()) or does_fx; const receiver_var = ModuleEnv.varFrom(method_call.receiver); @@ -6790,12 +6856,6 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, env: *Env, expected: Expected) method_call.args, constraint_fn_var, ); - if (self.cir.isInterpolationCallNode(ModuleEnv.nodeIdxFrom(expr_idx))) { - // The from_interpolation protocol returns the receiver's - // type, so the literal's target is pinned by the result - // before string defaulting runs. - _ = try self.unify(expr_var, receiver_var, env); - } } }, .e_dispatch_call => |method_call| { @@ -7062,7 +7122,9 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, env: *Env, expected: Expected) } // Check any accumulated static dispatch constraints - try self.checkStaticDispatchConstraints(env, false); + if (!self.defer_expr_static_dispatch_checks) { + try self.checkStaticDispatchConstraints(env, false); + } // If this type of expr should be generalized, generalize it! if (should_generalize) { @@ -9307,6 +9369,48 @@ fn mkTypeMethodCallConstraint( return constraint_fn_var; } +fn mkInterpolationConstraint( + self: *Self, + dispatcher_var: Var, + arg_vars: []const Var, + ret_var: Var, + method_name: Ident.Idx, + env: *Env, + region: Region, + expr_idx: CIR.Expr.Idx, +) Allocator.Error!Var { + const args_range = try self.types.appendVars(arg_vars); + const constraint_fn_var = try self.freshFromContent(.{ .structure = .{ .fn_unbound = Func{ + .args = args_range, + .ret = ret_var, + .needs_instantiation = false, + } } }, env, region); + + const constraint = StaticDispatchConstraint{ + .fn_name = method_name, + .fn_var = constraint_fn_var, + .origin = .from_interpolation, + }; + const constraint_range = try self.types.appendStaticDispatchConstraints(&.{constraint}); + try self.constraint_expr_by_fn_var.put(constraint_fn_var, expr_idx); + if (self.current_expect_region) |expect_region| { + try self.expect_region_by_constraint_fn_var.put(constraint_fn_var, expect_region); + } + + const constrained_var = try self.freshFromContent( + .{ .flex = Flex{ .name = null, .constraints = constraint_range } }, + env, + region, + ); + + _ = try self.unify(constrained_var, dispatcher_var, env); + + // Shares the literal-defaulting counter with numerals and quoted strings. + self.types.from_numeral_flex_count += 1; + + return constraint_fn_var; +} + fn rewriteImplicitEqMethodCallAsStructuralEq( self: *Self, constraint: StaticDispatchConstraint, @@ -9752,7 +9856,7 @@ fn resolveFromNumeralFlexFromConcreteDispatchArg( const dispatcher_resolved = self.types.resolveVar(dispatcher_var); for (constraints) |constraint| { - if (constraint.origin == .from_numeral or constraint.origin == .from_quote) continue; + if (isLiteralStaticDispatchOrigin(constraint.origin)) continue; const fn_content = self.types.resolveVar(constraint.fn_var).desc.content; const func = fn_content.unwrapFunc() orelse continue; @@ -9933,11 +10037,11 @@ fn finalizeNumericDefaultsInternal(self: *Self, env: *Env) std.mem.Allocator.Err } } -/// Default every non-generalized flex var carrying a from_quote constraint to -/// Str. This runs before numeric context resolution: a still-flex string -/// literal blocks resolution of the method chains hanging off it (e.g. -/// `"x".to_utf8().concat([0])`), and those chains are what give numeric -/// literals their context. +/// Default every non-generalized flex var carrying a quote-like literal +/// constraint to Str. This runs before numeric context resolution: a still-flex +/// string literal or interpolation blocks resolution of the method chains +/// hanging off it (e.g. `"x".to_utf8().concat([0])`), and those chains are what +/// give numeric literals their context. fn finalizeQuoteDefaults(self: *Self, env: *Env) Allocator.Error!void { if (self.types.from_numeral_flex_count == 0) return; @@ -9958,18 +10062,20 @@ fn finalizeQuoteDefaults(self: *Self, env: *Env) Allocator.Error!void { if (resolved.desc.content != .flex) continue; const flex = resolved.desc.content.flex; const constraints = self.types.sliceStaticDispatchConstraints(flex.constraints); - var has_from_quote = false; + var has_str_defaultable_literal = false; var has_from_numeral = false; for (constraints) |c| { switch (c.origin) { - .from_quote => has_from_quote = true, + .from_quote, + .from_interpolation, + => has_str_defaultable_literal = true, .from_numeral => has_from_numeral = true, else => {}, } } // A var carrying both origins is left for the numeric default, which - // then reports the unsatisfiable from_quote constraint against Dec. - if (!has_from_quote or has_from_numeral) continue; + // then reports the unsatisfiable string-like constraint against Dec. + if (!has_str_defaultable_literal or has_from_numeral) continue; if (resolved.desc.rank == .generalized) { if (!collected_pinnable) { @@ -10241,6 +10347,14 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas )) { continue; } + if (constraint.origin == .from_interpolation and self.nominalIsBuiltinStrType(nominal_type)) { + if (try self.satisfyBuiltinStrInterpolation(deferred_constraint.var_, constraint, env)) { + continue; + } + } + if (constraint.origin == .from_interpolation) { + try self.ensureCustomInterpolationRestChecked(constraint, env); + } const method_binding = if (constraint.fn_name.eql(self.cir.idents.is_eq) and try self.nominalSupportsImplicitIsEq(nominal_type)) blk: { @@ -10382,6 +10496,7 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas continue; }; + const deferred_len_before = env.deferred_static_dispatch_constraints.items.items.len; const fn_result = try self.unifyInContext(method_var, constraint.fn_var, env, .{ .method_type = .{ .constraint_var = deferred_constraint.var_, @@ -10402,6 +10517,13 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas } try self.unifyWith(deferred_constraint.var_, .err, env); try self.unifyWith(constraint_fn.ret, .err, env); + } else if (try self.reportRecursiveStaticDispatchIfNeeded( + deferred_constraint.var_, + constraint, + deferred_len_before, + env, + )) { + try self.unifyWith(constraint_fn.ret, .err, env); } else { try self.reportEffectfulDispatchInExpect(constraint); } @@ -10438,6 +10560,9 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas )) { continue; } + if (constraint.origin == .from_interpolation) { + try self.ensureCustomInterpolationRestChecked(constraint, env); + } if (constraint.fn_name.eql(self.cir.idents.is_eq)) { const method_binding = original_env.lookupMethodBindingFromTwoEnvsAndDeclConst( @@ -10563,6 +10688,7 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas continue; }; + const deferred_len_before = env.deferred_static_dispatch_constraints.items.items.len; const fn_result = try self.unifyInContext(method_var, constraint.fn_var, env, .{ .method_type = .{ .constraint_var = deferred_constraint.var_, @@ -10577,6 +10703,13 @@ fn checkStaticDispatchConstraints(self: *Self, env: *Env, is_numeric_default_pas } try self.unifyWith(deferred_constraint.var_, .err, env); try self.unifyWith(constraint_fn.ret, .err, env); + } else if (try self.reportRecursiveStaticDispatchIfNeeded( + deferred_constraint.var_, + constraint, + deferred_len_before, + env, + )) { + try self.unifyWith(constraint_fn.ret, .err, env); } else { try self.reportEffectfulDispatchInExpect(constraint); } @@ -10691,6 +10824,90 @@ fn reportEffectfulDispatchInExpect( } } +fn interpolationExprForConstraint(self: *Self, constraint: StaticDispatchConstraint) ?CIR.Expr.Idx { + if (constraint.origin != .from_interpolation) return null; + const expr_idx = self.constraint_expr_by_fn_var.get(constraint.fn_var) orelse return null; + if (self.cir.store.getExpr(expr_idx) != .e_interpolation) return null; + return expr_idx; +} + +fn recordInterpolationPartTypeMismatch(self: *Self, expected_var: Var, actual_var: Var) Allocator.Error!void { + const expected_snapshot = try self.snapshots.snapshotVarForError(self.types, &self.type_writer, expected_var); + const actual_snapshot = try self.snapshots.snapshotVarForError(self.types, &self.type_writer, actual_var); + _ = try self.problems.appendProblem(self.gpa, .{ .type_mismatch = .{ + .types = .{ + .expected_var = expected_var, + .expected_snapshot = expected_snapshot, + .actual_var = actual_var, + .actual_snapshot = actual_snapshot, + }, + .context = .none, + } }); +} + +fn constrainInterpolationExprToStr(self: *Self, expr_idx: CIR.Expr.Idx, expected_str_var: Var, env: *Env) Allocator.Error!bool { + const expr_var = ModuleEnv.varFrom(expr_idx); + const resolved_expr = self.types.resolveVar(expr_var); + if (resolved_expr.desc.content == .err) return false; + + const compatible = blk: { + var probe = try self.beginProbe(); + defer probe.rollback(); + break :blk try self.probeUnifyWithoutRecordingProblems(expected_str_var, expr_var); + }; + + if (!compatible) { + try self.recordInterpolationPartTypeMismatch(expected_str_var, expr_var); + return true; + } + + const result = try self.unify(expected_str_var, expr_var, env); + std.debug.assert(result.isOk()); + return false; +} + +fn satisfyBuiltinStrInterpolation( + self: *Self, + dispatcher_var: Var, + constraint: StaticDispatchConstraint, + env: *Env, +) Allocator.Error!bool { + const expr_idx = self.interpolationExprForConstraint(constraint) orelse return false; + const interpolation = self.cir.store.getExpr(expr_idx).e_interpolation; + const expr_region = self.cir.store.getNodeRegion(ModuleEnv.nodeIdxFrom(expr_idx)); + const expected_str_var = try self.freshStr(env, expr_region); + + var did_err = false; + const parts = self.cir.store.sliceExpr(interpolation.parts); + std.debug.assert(parts.len % 2 == 0); + var part_i: usize = 0; + while (part_i < parts.len) : (part_i += 2) { + did_err = (try self.constrainInterpolationExprToStr(parts[part_i], expected_str_var, env)) or did_err; + } + + if (did_err) { + try self.unifyWith(dispatcher_var, .err, env); + try self.markConstraintFunctionAsError(constraint, env); + } + return true; +} + +fn ensureCustomInterpolationRestChecked( + self: *Self, + constraint: StaticDispatchConstraint, + env: *Env, +) Allocator.Error!void { + const expr_idx = self.interpolationExprForConstraint(constraint) orelse return; + const entry = try self.checked_interpolation_rests.getOrPut(constraint.fn_var); + if (entry.found_existing) return; + + const interpolation = self.cir.store.getExpr(expr_idx).e_interpolation; + const saved = self.defer_expr_static_dispatch_checks; + self.defer_expr_static_dispatch_checks = true; + defer self.defer_expr_static_dispatch_checks = saved; + _ = try self.checkExpr(interpolation.rest, env, Expected.none()); +} + /// Check if a structural type supports is_eq. /// A type supports is_eq if: /// - It's not a function type @@ -10881,6 +11098,17 @@ fn builtinNumKindFromNominalType(self: *const Self, nominal_type: types_mod.Nomi return self.builtinNumKindFromBuiltinSourceDecl(nominal_type.sourceDeclOptional()); } +fn nominalIsBuiltinStrType(self: *const Self, nominal_type: types_mod.NominalType) bool { + if (!nominal_type.originIsBuiltin()) return false; + if (nominal_type.sourceDeclOptional()) |source_decl| { + if (self.builtin_ctx.builtin_indices) |indices| { + if (source_decl == @intFromEnum(indices.str_type)) return true; + } + } + const ident = nominal_type.ident.ident_idx; + return ident.eql(self.cir.idents.str) or ident.eql(self.cir.idents.builtin_str); +} + fn nominalIsBuiltinNumberType(self: *Self, nominal_type: types_mod.NominalType) bool { return self.builtinNumKindFromNominalType(nominal_type) != null; } @@ -11121,9 +11349,8 @@ fn varSupportsIsEqInternal( /// Check if a flex var has incompatible constraints and report errors. /// This is called after type-checking to catch cases like `!3` where a flex var -/// has both `from_numeral` (numeric) and `not` (Bool only) constraints. -/// If the flex var has a from_numeral constraint (meaning it will default to a numeric -/// type like Dec), we validate that all other constraints can be satisfied by Dec. +/// has both `from_numeral` (numeric) and `not` (Bool only) constraints. Literal +/// constraints default to Dec for numerals and Str for quote/interpolation. fn checkFlexVarConstraintCompatibility(self: *Self, var_: Var, env: *Env, is_numeric_default_pass: bool) Allocator.Error!void { const resolved = self.types.resolveVar(var_); if (resolved.desc.content != .flex) return; @@ -11134,29 +11361,33 @@ fn checkFlexVarConstraintCompatibility(self: *Self, var_: Var, env: *Env, is_num // Find the literal-origin constraint that determines the default type. var has_from_numeral = false; - var has_from_quote = false; + var has_str_defaultable_literal = false; for (constraints) |c| { switch (c.origin) { .from_numeral => has_from_numeral = true, - .from_quote => has_from_quote = true, + .from_quote, + .from_interpolation, + => has_str_defaultable_literal = true, else => {}, } } - if (!has_from_numeral and !has_from_quote) return; + if (!has_from_numeral and !has_str_defaultable_literal) return; - // This flex will default to Dec (numerals) or Str (quotes). Validate that - // all other constraints can be satisfied by the default type. + // This flex will default to Dec (numerals) or Str (quotes/interpolations). + // Validate that all other constraints can be satisfied by the default type. const builtin_env = self.builtin_ctx.builtin_module orelse return; const indices = self.builtin_ctx.builtin_indices orelse return; const default_type_stmt = if (has_from_numeral) indices.dec_type else indices.str_type; for (constraints) |constraint| { // Skip the literal-origin constraint the default type satisfies by - // definition. (With both origins present, the var defaults to Dec and - // the from_quote constraint must still be validated against it.) + // definition. (With a numeric origin present, the var defaults to Dec + // and any string-like constraint must still be validated against it.) switch (constraint.origin) { .from_numeral => if (has_from_numeral) continue, - .from_quote => if (!has_from_numeral) continue, + .from_quote, + .from_interpolation, + => if (!has_from_numeral) continue, else => {}, } @@ -11439,6 +11670,63 @@ const ReportedConstraintError = struct { fn_name: Ident.Idx, }; +fn reportRecursiveStaticDispatchIfNeeded( + self: *Self, + dispatcher_var: Var, + constraint: StaticDispatchConstraint, + deferred_len_before: usize, + env: *Env, +) Allocator.Error!bool { + if (constraint.origin != .where_clause) return false; + if (!constraint.fn_name.eql(self.cir.idents.from_interpolation)) return false; + + const items = env.deferred_static_dispatch_constraints.items.items; + if (deferred_len_before == items.len) return false; + + const dispatcher_resolved = self.types.resolveVar(dispatcher_var).var_; + var deferred_index = deferred_len_before; + while (deferred_index < items.len) : (deferred_index += 1) { + const deferred = items[deferred_index]; + if (self.types.resolveVar(deferred.var_).var_ != dispatcher_resolved) continue; + + const new_constraints = self.types.sliceStaticDispatchConstraints(deferred.constraints); + for (new_constraints) |new_constraint| { + if (new_constraint.origin != .where_clause) continue; + if (!new_constraint.fn_name.eql(constraint.fn_name)) continue; + if (!try self.staticDispatchConstraintFunctionsCanUnify( + constraint.fn_var, + new_constraint.fn_var, + )) { + continue; + } + + const snapshot = try self.snapshots.snapshotVarForError(self.types, &self.type_writer, dispatcher_var); + _ = try self.problems.appendProblem(self.cir.gpa, .{ .static_dispatch = .{ + .recursive_dispatch = .{ + .dispatcher_snapshot = snapshot, + .fn_var = constraint.fn_var, + .method_name = constraint.fn_name, + }, + } }); + + try self.markConstraintFunctionAsError(constraint, env); + try self.markConstraintFunctionAsError(new_constraint, env); + return true; + } + } + return false; +} + +fn staticDispatchConstraintFunctionsCanUnify( + self: *Self, + left: Var, + right: Var, +) Allocator.Error!bool { + var probe = try self.beginProbe(); + defer probe.rollback(); + return try self.probeUnifyWithoutRecordingProblems(left, right); +} + /// Report a constraint validation error fn reportConstraintError( self: *Self, diff --git a/src/check/checked_artifact.zig b/src/check/checked_artifact.zig index 70361a37e57..1ce09a9845c 100644 --- a/src/check/checked_artifact.zig +++ b/src/check/checked_artifact.zig @@ -80,6 +80,15 @@ pub const ModuleEnvStorage = union(enum) { } }; +fn moduleExprIsBuiltinStr(module: TypedCIR.Module, expr_idx: CIR.Expr.Idx) bool { + const resolved = module.typeStoreConst().resolveVar(module.exprType(expr_idx)); + const nominal = resolved.desc.content.unwrapNominalType() orelse return false; + if (!nominal.originIsBuiltin()) return false; + const ident = nominal.ident.ident_idx; + const common = module.commonIdents(); + return ident.eql(common.str) or ident.eql(common.builtin_str); +} + /// Public `CheckedModuleArtifactKey` declaration. pub const CheckedModuleArtifactKey = struct { source_hash: [32]u8 = [_]u8{0} ** 32, @@ -1055,6 +1064,7 @@ fn exprDependsOnUnboundPlatformRequirement( .empty_record, .zero_argument_tag, .dispatch_call, + .interpolation, .method_eq, .type_dispatch_call, .runtime_error, @@ -3912,6 +3922,7 @@ fn appendStaticDispatchTypeRoots( const tag = module.nodeTag(@enumFromInt(node_idx)); switch (tag) { .expr_dispatch_call, + .expr_interpolation, .expr_type_dispatch_call, .expr_method_eq, => {}, @@ -3926,6 +3937,19 @@ fn appendStaticDispatchTypeRoots( _ = try appendCheckedTypeRoot(allocator, module, names, imports, roots, payloads, active, module.exprType(dispatch_call.receiver)); _ = try appendCheckedTypeRoot(allocator, module, names, imports, roots, payloads, active, dispatch_call.constraint_fn_var); }, + .e_interpolation => |interpolation| { + _ = try appendCheckedTypeRoot(allocator, module, names, imports, roots, payloads, active, module.exprType(expr_idx)); + _ = try appendCheckedTypeRoot( + allocator, + module, + names, + imports, + roots, + payloads, + active, + interpolation.constraint_fn_var orelse checkedArtifactInvariant("checked interpolation expression had no static dispatch constraint type", .{}), + ); + }, .e_type_dispatch_call => |dispatch_call| { const alias_stmt = module.getStatement(dispatch_call.type_var_alias_stmt); _ = try appendCheckedTypeRoot(allocator, module, names, imports, roots, payloads, active, ModuleEnv.varFrom(alias_stmt.s_type_var_alias.type_var_anno)); @@ -4156,13 +4180,13 @@ fn numericDefaultPhaseForConstraints( constraints_range: types.StaticDispatchConstraint.SafeList.Range, ) ?NumericDefaultPhase { const constraints = module.typeStoreConst().sliceStaticDispatchConstraints(constraints_range); - var has_from_quote = false; + var has_str_defaultable_literal = false; for (constraints) |constraint| { if (constraint.origin == .from_numeral) return .mono_specialization; - if (constraint.origin == .from_quote) has_from_quote = true; + if (constraint.origin == .from_quote or constraint.origin == .from_interpolation) has_str_defaultable_literal = true; if (isDefaultableArithmeticConstraint(module, constraint)) return .mono_specialization; } - if (has_from_quote) return .mono_specialization_str; + if (has_str_defaultable_literal) return .mono_specialization_str; return null; } @@ -4181,6 +4205,7 @@ fn isDefaultableArithmeticConstraint( .desugared_unaryop => constraint.fn_name.eql(idents.negate), .from_numeral, .from_quote, + .from_interpolation, .method_call, .where_clause, => false, @@ -4936,7 +4961,7 @@ pub const CheckedExprData = union(enum) { typed_num_from_numeral: ?StaticDispatchPlanId, /// A string literal whose target is a non-builtin nominal type, converted /// through the type's `from_quote` method. `literal` holds the complete - /// post-escape UTF-8 bytes. + /// post-escape string contents. str_from_quote: struct { plan: ?StaticDispatchPlanId, literal: CheckedStringLiteralId, @@ -5012,6 +5037,7 @@ pub const CheckedExprData = union(enum) { field_name: canonical.RecordFieldLabelId, }, dispatch_call: ?StaticDispatchPlanId, + interpolation: ?StaticDispatchPlanId, structural_eq: struct { lhs: CheckedExprId, rhs: CheckedExprId, @@ -5383,17 +5409,13 @@ const CheckedSourceNodes = struct { }, .e_dispatch_call => |call| { try self.markExpr(call.receiver, work); - if (module.moduleEnvConst().isStrInterpolationCall(expr_idx)) { - // A Str-typed interpolation publishes as a plain segment - // list; the synthetic iterator chain stays out of the - // artifact, so only the pair payloads are reachable. - var pairs = module.moduleEnvConst().interpolationPairs(expr_idx); - while (pairs.next()) |pair| { - try self.markExpr(pair.interpolation, work); - try self.markExpr(pair.segment, work); - } - } else { - try self.markExprSpan(module, call.args, work); + try self.markExprSpan(module, call.args, work); + }, + .e_interpolation => |interpolation| { + try self.markExpr(interpolation.first, work); + try self.markExprSpan(module, interpolation.parts, work); + if (!moduleExprIsBuiltinStr(module, expr_idx)) { + try self.markExpr(interpolation.rest, work); } }, .e_structural_eq => |eq| { @@ -5855,6 +5877,7 @@ pub const CheckedBodyStore = struct { const data = &self.exprs[@intFromEnum(checked_expr)].data; switch (data.*) { .dispatch_call => data.* = .{ .dispatch_call = entry.value_ptr.* }, + .interpolation => data.* = .{ .interpolation = entry.value_ptr.* }, .method_eq => data.* = .{ .method_eq = entry.value_ptr.* }, .type_dispatch_call => data.* = .{ .type_dispatch_call = entry.value_ptr.* }, else => { @@ -6241,6 +6264,7 @@ fn checkedExprDataDiverges( .empty_record, .zero_argument_tag, .dispatch_call, + .interpolation, .method_eq, .type_dispatch_call, .runtime_error, @@ -6602,12 +6626,8 @@ const CheckedBodyPayloadCopier = struct { "ordinary method call reached artifact publication after checking; expected explicit static-dispatch plan", .{}, ), - .e_dispatch_call => blk: { - if (self.module.moduleEnvConst().isStrInterpolationCall(expr_idx)) { - break :blk .{ .str = try self.copyStrInterpolationSegments(expr_idx) }; - } - break :blk .{ .dispatch_call = null }; - }, + .e_dispatch_call => .{ .dispatch_call = null }, + .e_interpolation => |interpolation| try self.copyInterpolationExpr(expr_idx, interpolation), .e_structural_eq => |eq| .{ .structural_eq = .{ .lhs = self.checkedExpr(eq.lhs), .rhs = self.checkedExpr(eq.rhs), @@ -6658,26 +6678,24 @@ const CheckedBodyPayloadCopier = struct { }; } - /// Publish a Str-typed interpolation dispatch call as its ordered - /// segment list: the receiver literal, then each interpolation and the - /// literal segment that follows it. Lowering turns this into direct - /// string concatenation, so the synthetic iterator chain never reaches - /// code generation. - fn copyStrInterpolationSegments(self: *@This(), expr_idx: CIR.Expr.Idx) Allocator.Error![]const CheckedExprId { - const env = self.module.moduleEnvConst(); + fn copyInterpolationExpr(self: *@This(), expr_idx: CIR.Expr.Idx, interpolation: anytype) Allocator.Error!CheckedExprData { + if (self.checkedBuiltinForExpr(expr_idx) == .str) { + return .{ .str = try self.copyStrInterpolationSegments(interpolation) }; + } + return .{ .interpolation = null }; + } + + fn copyStrInterpolationSegments(self: *@This(), interpolation: anytype) Allocator.Error![]const CheckedExprId { var segments = std.ArrayList(CheckedExprId).empty; errdefer segments.deinit(self.allocator); - const call = switch (self.module.expr(expr_idx).data) { - .e_dispatch_call => |call| call, - else => checkedArtifactInvariant("interpolation segment publication reached a non-dispatch expression", .{}), - }; - try segments.append(self.allocator, self.checkedExpr(call.receiver)); - var pairs = env.interpolationPairs(expr_idx); - while (pairs.next()) |pair| { - try segments.append(self.allocator, self.checkedExpr(pair.interpolation)); - try segments.append(self.allocator, self.checkedExpr(pair.segment)); + try segments.append(self.allocator, self.checkedExpr(interpolation.first)); + const parts = self.module.sliceExpr(interpolation.parts); + std.debug.assert(parts.len % 2 == 0); + for (parts) |part_idx| { + try segments.append(self.allocator, self.checkedExpr(part_idx)); } + return try segments.toOwnedSlice(self.allocator); } @@ -6695,7 +6713,7 @@ const CheckedBodyPayloadCopier = struct { return .{ .str = try self.copyExprSpan(span) }; } - /// Intern the complete post-escape bytes of a literal-only string, + /// Intern the complete post-escape contents of a literal-only string, /// concatenating its segments. fn internQuoteBytes(self: *@This(), span: CIR.Expr.Span) Allocator.Error!CheckedStringLiteralId { const segments = self.module.sliceExpr(span); @@ -7691,6 +7709,7 @@ fn deinitCheckedExprData(allocator: Allocator, data: *CheckedExprData) void { .empty_record, .zero_argument_tag, .dispatch_call, + .interpolation, .structural_eq, .method_eq, .type_dispatch_call, @@ -7772,6 +7791,7 @@ fn verifyCheckedExprDataComplete(data: CheckedExprData) void { .lookup_external => |ref| std.debug.assert(ref != null), .lookup_required => |ref| std.debug.assert(ref != null), .dispatch_call => |plan| std.debug.assert(plan != null), + .interpolation => |plan| std.debug.assert(plan != null), .method_eq => |plan| std.debug.assert(plan != null), .type_dispatch_call => |plan| std.debug.assert(plan != null), .num_from_numeral => |plan| std.debug.assert(plan != null), @@ -9036,6 +9056,7 @@ const CheckedTemplateRefCollector = struct { if (ref_id) |id| try self.value_refs.append(self.allocator, id); }, .dispatch_call, + .interpolation, .method_eq, .type_dispatch_call, => |plan_id| { @@ -9758,6 +9779,7 @@ const NestedProcSiteBuilder = struct { }, .field_access => |field| try self.scanExpr(field.receiver, owner, false), .dispatch_call, + .interpolation, .method_eq, .type_dispatch_call, => |plan_id| try self.scanStaticDispatchPlanArgs(plan_id orelse checkedArtifactInvariant("checked dispatch expression reached nested procedure site collection without a static-dispatch plan", .{}), owner), diff --git a/src/check/problem.zig b/src/check/problem.zig index 4eadaa8a2cb..c52c3cfaedc 100644 --- a/src/check/problem.zig +++ b/src/check/problem.zig @@ -32,6 +32,7 @@ pub const DispatcherNotNominal = types.DispatcherNotNominal; pub const DispatcherDoesNotImplMethod = types.DispatcherDoesNotImplMethod; pub const TypeDoesNotSupportEquality = types.TypeDoesNotSupportEquality; pub const UnresolvedDispatcher = types.UnresolvedDispatcher; +pub const RecursiveDispatch = types.RecursiveDispatch; // Number errors pub const NumberDoesNotFit = types.NumberDoesNotFit; diff --git a/src/check/problem/types.zig b/src/check/problem/types.zig index a3f6723d046..2d4083e2a37 100644 --- a/src/check/problem/types.zig +++ b/src/check/problem/types.zig @@ -264,6 +264,7 @@ pub const StaticDispatch = union(enum) { dispatcher_does_not_impl_method: DispatcherDoesNotImplMethod, type_does_not_support_equality: TypeDoesNotSupportEquality, unresolved_dispatcher: UnresolvedDispatcher, + recursive_dispatch: RecursiveDispatch, }; /// Error when a static dispatch method is called on a receiver whose type is an @@ -332,6 +333,14 @@ pub const TypeDoesNotSupportEquality = struct { fn_var: Var, }; +/// Error when satisfying a static-dispatch constraint immediately requires the +/// same static-dispatch constraint again on the same dispatcher type. +pub const RecursiveDispatch = struct { + dispatcher_snapshot: SnapshotContentIdx, + fn_var: Var, + method_name: Ident.Idx, +}; + // nominal type errors // /// Error when you try to use an opaque nominal type constructor diff --git a/src/check/report.zig b/src/check/report.zig index 871ac81a664..de7fc375d02 100644 --- a/src/check/report.zig +++ b/src/check/report.zig @@ -47,6 +47,7 @@ const DispatcherNotNominal = problem_mod.DispatcherNotNominal; const DispatcherDoesNotImplMethod = problem_mod.DispatcherDoesNotImplMethod; const TypeDoesNotSupportEquality = problem_mod.TypeDoesNotSupportEquality; const UnresolvedDispatcher = problem_mod.UnresolvedDispatcher; +const RecursiveDispatch = problem_mod.RecursiveDispatch; // Match/exhaustiveness errors const NonExhaustiveMatch = problem_mod.NonExhaustiveMatch; @@ -781,6 +782,7 @@ pub const ReportBuilder = struct { .dispatcher_does_not_impl_method => |data| return self.buildStaticDispatchDispatcherDoesNotImplMethod(data), .type_does_not_support_equality => |data| return self.buildTypeDoesNotSupportEquality(data), .unresolved_dispatcher => |data| return self.buildStaticDispatchUnresolvedDispatcher(data), + .recursive_dispatch => |data| return self.buildStaticDispatchRecursiveDispatch(data), } }, .recursive_alias => |data| { @@ -2092,6 +2094,54 @@ pub const ReportBuilder = struct { return report; } + /// Build a report for an unproductive static-dispatch cycle. + fn buildStaticDispatchRecursiveDispatch( + self: *Self, + data: RecursiveDispatch, + ) Allocator.Error!Report { + var report = Report.init(self.gpa, "RECURSIVE DISPATCH", .runtime_error); + errdefer report.deinit(); + + const snapshot_str = try report.addOwnedString(self.getFormattedString(data.dispatcher_snapshot)); + + try D.renderSlice(&.{ + D.bytes("This"), + D.ident(data.method_name).withAnnotation(.emphasized), + D.bytes("dispatch would have to call itself to satisfy its own type:"), + }, self, &report); + try report.document.addLineBreak(); + + if (self.getRegionSafe(@enumFromInt(@intFromEnum(data.fn_var)))) |region| { + const region_info = self.module_env.calcRegionInfo(region.*); + try report.document.addSourceRegion( + region_info, + .error_highlight, + self.filename, + self.source, + self.module_env.getLineStarts(), + ); + try report.document.addLineBreak(); + } + + try D.renderSlice(&.{ + D.bytes("The dispatcher type is:"), + }, self, &report); + try report.document.addLineBreak(); + try report.document.addLineBreak(); + try report.document.addCodeBlock(snapshot_str); + try report.document.addLineBreak(); + try report.document.addLineBreak(); + + try D.renderSlice(&.{ + D.bytes("Hint:").withAnnotation(.emphasized), + D.bytes("Use a more specific result type, or add an associated function whose"), + D.ident(data.method_name).withAnnotation(.emphasized), + D.bytes("implementation does not require the same dispatch on the same type."), + }, self, &report); + + return report; + } + /// Build a report for when a string literal is used where a non-string type is expected fn buildStringUsedAsNonString( self: *Self, diff --git a/src/check/static_dispatch_registry.zig b/src/check/static_dispatch_registry.zig index 034034d2786..93bd1836d33 100644 --- a/src/check/static_dispatch_registry.zig +++ b/src/check/static_dispatch_registry.zig @@ -445,7 +445,7 @@ pub const StaticDispatchDispatcher = union(enum) { pub const StaticDispatchOperand = union(enum) { checked_expr: CheckedExprId, generated_numeral: ModuleEnv.NumeralLiteral, - /// A string literal's post-escape bytes, passed to `from_quote` as List(U8). + /// A string literal's post-escape contents, passed to `from_quote` as Str. generated_quote: CheckedStringLiteralId, }; @@ -538,6 +538,7 @@ pub const StaticDispatchPlanTable = struct { const tag = module.nodeTag(@enumFromInt(node_idx)); switch (tag) { .expr_dispatch_call, + .expr_interpolation, .expr_type_dispatch_call, .expr_method_eq, => {}, @@ -545,12 +546,9 @@ pub const StaticDispatchPlanTable = struct { } const expr_idx: CIR.Expr.Idx = @enumFromInt(node_idx); - // Str-typed interpolation calls publish as plain segment lists, - // so they have no dispatch plan and their iterator-chain - // arguments never enter the checked body store. - if (module.moduleEnvConst().isStrInterpolationCall(expr_idx)) continue; const checked_expr = checked_bodies.exprIdForSource(expr_idx) orelse continue; const expr = module.expr(expr_idx); + const checked_expr_data = checked_bodies.exprs[@intFromEnum(checked_expr)].data; const idents = module.identStoreConst(); const plan_id: StaticDispatchPlanId = @enumFromInt(@as(u32, @intCast(plans.items.len))); switch (expr.data) { @@ -572,6 +570,22 @@ pub const StaticDispatchPlanTable = struct { .result_mode = try staticDispatchResultModeForCheckedValueCall(allocator, module, checked_types, &constraint_index, dispatch_call.method_name, dispatch_call.constraint_fn_var), }); }, + .e_interpolation => |interpolation| { + if (checked_expr_data != .interpolation) continue; + const args = try staticDispatchOperandsForSlice(allocator, checked_bodies, &.{ interpolation.first, interpolation.rest }); + const from_interpolation = try names.internMethodName("from_interpolation"); + const constraint_fn_var = interpolation.constraint_fn_var orelse unreachable; + + try plans.append(allocator, .{ + .expr = checked_expr, + .method = from_interpolation, + .dispatcher = .type_only, + .dispatcher_ty = try checkedTypeIdForVar(allocator, module, checked_types, module.exprType(expr_idx)), + .callable_ty = try checkedTypeIdForVar(allocator, module, checked_types, constraint_fn_var), + .args = args, + .result_mode = .value, + }); + }, .e_type_dispatch_call => |dispatch_call| { const alias_stmt = module.getStatement(dispatch_call.type_var_alias_stmt); const args = try staticDispatchOperandsForSlice(allocator, checked_bodies, module.sliceExpr(dispatch_call.args)); @@ -826,12 +840,18 @@ const StaticDispatchConstraintIndex = struct { const expr_idx: CIR.Expr.Idx = @enumFromInt(node_idx); const constraint_fn_var: ?Var = switch (module.nodeTag(@enumFromInt(node_idx))) { .expr_dispatch_call => module.expr(expr_idx).data.e_dispatch_call.constraint_fn_var, + .expr_interpolation => module.expr(expr_idx).data.e_interpolation.constraint_fn_var, .expr_type_dispatch_call => module.expr(expr_idx).data.e_type_dispatch_call.constraint_fn_var, .expr_method_eq => module.expr(expr_idx).data.e_method_eq.constraint_fn_var, else => null, }; if (constraint_fn_var) |fn_var| { - if (checked_bodies.exprIdForSource(expr_idx) == null) continue; + const checked_expr = checked_bodies.exprIdForSource(expr_idx) orelse continue; + if (module.nodeTag(@enumFromInt(node_idx)) == .expr_interpolation and + checked_bodies.exprs[@intFromEnum(checked_expr)].data != .interpolation) + { + continue; + } try live_fn_vars.put(allocator, fn_var, {}); } } diff --git a/src/check/test/TestEnv.zig b/src/check/test/TestEnv.zig index fa2e7d5ba5f..012ed32a1f4 100644 --- a/src/check/test/TestEnv.zig +++ b/src/check/test/TestEnv.zig @@ -108,7 +108,6 @@ fn loadCompiledModule(gpa: std.mem.Allocator, bin_data: []const u8, module_name: .numeral_literals = serialized_ptr.numeral_literals.deserializeInto(base_ptr), .numeral_dispatch_plans = serialized_ptr.numeral_dispatch_plans.deserializeInto(base_ptr), .quote_dispatch_plans = serialized_ptr.quote_dispatch_plans.deserializeInto(base_ptr), - .interpolation_call_nodes = serialized_ptr.interpolation_call_nodes.deserializeInto(base_ptr), .numeric_suffix_types = serialized_ptr.numeric_suffix_types.deserializeInto(base_ptr), }; diff --git a/src/check/test/cross_module_mono_test.zig b/src/check/test/cross_module_mono_test.zig index 745d44787c8..4c6d47caffa 100644 --- a/src/check/test/cross_module_mono_test.zig +++ b/src/check/test/cross_module_mono_test.zig @@ -111,7 +111,6 @@ fn loadCompiledModule(gpa: std.mem.Allocator, bin_data: []const u8, module_name: .numeral_literals = serialized_ptr.numeral_literals.deserializeInto(base_ptr), .numeral_dispatch_plans = serialized_ptr.numeral_dispatch_plans.deserializeInto(base_ptr), .quote_dispatch_plans = serialized_ptr.quote_dispatch_plans.deserializeInto(base_ptr), - .interpolation_call_nodes = serialized_ptr.interpolation_call_nodes.deserializeInto(base_ptr), .numeric_suffix_types = serialized_ptr.numeric_suffix_types.deserializeInto(base_ptr), }; diff --git a/src/check/test/type_checking_integration.zig b/src/check/test/type_checking_integration.zig index f425099e881..857e895dcf2 100644 --- a/src/check/test/type_checking_integration.zig +++ b/src/check/test/type_checking_integration.zig @@ -380,7 +380,7 @@ test "check type - record - field typo" { \\ \\It has the type: \\ - \\ { helo: a } where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])] + \\ { helo: a } where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])] \\ \\But the annotation say it should be: \\ @@ -413,7 +413,7 @@ test "check type - record - field missing" { \\ \\It has the type: \\ - \\ { hello: a } where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])] + \\ { hello: a } where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])] \\ \\But the annotation say it should be: \\ @@ -445,7 +445,7 @@ test "check type - record - ext - field missing" { \\ \\It has the type: \\ - \\ { hello: a } where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])] + \\ { hello: a } where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])] \\ \\But the annotation say it should be: \\ @@ -4167,7 +4167,7 @@ test "check type - record ext - arg inferred as open" { \\ \\This argument has the type: \\ - \\ { foo: a } where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])] + \\ { foo: a } where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])] \\ \\But `use_record` needs the first argument to be: \\ @@ -5325,7 +5325,7 @@ test "check type - zulip repro" { \\ \\This argument has the type: \\ - \\ { foo: a } where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])] + \\ { foo: a } where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])] \\ \\But `use_record` needs the first argument to be: \\ @@ -5444,7 +5444,7 @@ test "check type - exhaustive match with nested payload is inferred as closed" { try checkTypesModuleDefs( source, &.{ - .{ .def = "test", .expected = "[Err(a), Ok([Blue, Red])] -> a\n where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])]" }, + .{ .def = "test", .expected = "[Err(a), Ok([Blue, Red])] -> a\n where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])]" }, }, ); } @@ -5463,7 +5463,7 @@ test "check type - exhaustive match with nested payload with wildcard is inferre try checkTypesModuleDefs( source, &.{ - .{ .def = "test", .expected = "[Err(a), Ok([Blue, Red, ..])] -> a\n where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])]" }, + .{ .def = "test", .expected = "[Err(a), Ok([Blue, Red, ..])] -> a\n where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])]" }, }, ); } @@ -5535,7 +5535,7 @@ test "check type - exhaustive match mixed nested closure" { try checkTypesModuleDefs( source, &.{ - .{ .def = "test", .expected = "[Err(a), Ok([A, B])] -> a\n where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)])]" }, + .{ .def = "test", .expected = "[Err(a), Ok([A, B])] -> a\n where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)])]" }, }, ); } diff --git a/src/check/unify.zig b/src/check/unify.zig index a6d80817cb1..f7f6f80967d 100644 --- a/src/check/unify.zig +++ b/src/check/unify.zig @@ -399,13 +399,14 @@ const Unifier = struct { // Unify flex // - /// Check if a flex var has a literal-origin (from_numeral or from_quote) + /// Check if a flex var has a literal-origin (from_numeral, from_quote, or + /// from_interpolation) /// constraint, which is what `from_numeral_flex_count` tracks. fn flexHasFromNumeral(self: *const Self, flex: Flex) bool { if (flex.constraints.len() == 0) return false; const constraints = self.types_store.sliceStaticDispatchConstraints(flex.constraints); for (constraints) |c| { - if (c.origin == .from_numeral or c.origin == .from_quote) return true; + if (c.origin == .from_numeral or c.origin == .from_quote or c.origin == .from_interpolation) return true; } return false; } diff --git a/src/cli/test/parallel_cli_runner.zig b/src/cli/test/parallel_cli_runner.zig index 89933685781..5c6bb059575 100644 --- a/src/cli/test/parallel_cli_runner.zig +++ b/src/cli/test/parallel_cli_runner.zig @@ -1862,6 +1862,8 @@ fn customDefaultPlatformDebugBacktrace( .{ .stream = .stderr, .text = "Roc application crashed with this message:\n\n\tdefault platform crash contract\n\n" }, .{ .stream = .stderr, .text = "Backtrace:" }, .{ .stream = .stderr, .text = "\x1b[94mtrigger!\x1b[0m" }, + .{ .stream = .stderr, .text = "\x1b[94mmain!\x1b[0m" }, + .{ .stream = .stderr, .text = " main:" }, }, .stack_overflow => &.{ .{ .stream = .stderr, .text = "Roc application overflowed its stack memory\n\n" }, diff --git a/src/compile/test/module_env_test.zig b/src/compile/test/module_env_test.zig index 8cd1661ae62..3e31bcbd790 100644 --- a/src/compile/test/module_env_test.zig +++ b/src/compile/test/module_env_test.zig @@ -97,6 +97,7 @@ test "ModuleEnv.Serialized roundtrip" { // Plus 7 more identifiers: tag, payload, is_negative, digits_before_pt, digits_after_pt, box, unbox // Plus 2 Try tag identifiers: Ok, Err // Plus 1 method identifier: from_numeral + // Plus 1 interpolation method identifier: from_interpolation // Plus 2 Bool tag identifiers: True, False // Plus 6 from_utf8 identifiers: byte_index, string, is_ok, problem_code, problem, index // Plus 2 synthetic identifiers for ? operator desugaring: #ok, #err @@ -108,8 +109,8 @@ test "ModuleEnv.Serialized roundtrip" { // Plus 2 fully qualified Box intrinsic method names: Builtin.Box.box, Builtin.Box.unbox // Plus 1 fully qualified Bool type name: Builtin.Bool // Count reflects the merged builtin set after the zig-16 / origin/main merge - // (grew from 85 to 91 builtin identifiers). - try testing.expectEqual(@as(u32, 91), original.common.idents.interner.entry_count); + // (grew from 85 to 92 builtin identifiers). + try testing.expectEqual(@as(u32, 92), original.common.idents.interner.entry_count); try testing.expectEqualStrings("hello", original.getIdent(hello_idx)); try testing.expectEqualStrings("world", original.getIdent(world_idx)); @@ -118,9 +119,9 @@ test "ModuleEnv.Serialized roundtrip" { try testing.expectEqual(@as(usize, 2), original.imports.imports.len()); // Should have 2 unique imports // First verify that the CommonEnv data was preserved after deserialization - // Should have same identifiers as original: hello, world, TestModule + 16 well-known identifiers + 21 type identifiers + 3 field/tag identifiers + 7 more identifiers + 2 Try tag identifiers + 1 method identifier + 2 Bool tag identifiers + 6 from_utf8 identifiers + 2 synthetic identifiers for ? operator desugaring + 2 numeric method identifiers (abs, abs_diff) + 1 inspect method identifier (to_inspect) + 15 unqualified builtin type names from ModuleEnv.init() (Num, Bool, U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec) + 2 fully qualified Box intrinsic method names (Builtin.Box.box, Builtin.Box.unbox) + 1 fully qualified Bool type name (Builtin.Bool) + // Should have same identifiers as original: hello, world, TestModule + 16 well-known identifiers + 21 type identifiers + 3 field/tag identifiers + 7 more identifiers + 2 Try tag identifiers + 1 method identifier + 1 interpolation method identifier + 2 Bool tag identifiers + 6 from_utf8 identifiers + 2 synthetic identifiers for ? operator desugaring + 2 numeric method identifiers (abs, abs_diff) + 1 inspect method identifier (to_inspect) + 15 unqualified builtin type names from ModuleEnv.init() (Num, Bool, U8, U16, U32, U64, U128, I8, I16, I32, I64, I128, F32, F64, Dec) + 2 fully qualified Box intrinsic method names (Builtin.Box.box, Builtin.Box.unbox) + 1 fully qualified Bool type name (Builtin.Bool) // (Note: "Try" is now shared with well-known identifiers, reducing total by 1) - try testing.expectEqual(@as(u32, 91), env.common.idents.interner.entry_count); + try testing.expectEqual(@as(u32, 92), env.common.idents.interner.entry_count); try testing.expectEqual(@as(usize, 1), env.common.exposed_items.count()); try testing.expectEqual(@as(?u32, 42), env.common.exposed_items.getValueNodeIndexById(gpa, @as(u32, @bitCast(hello_idx)))); diff --git a/src/eval/test/eval_tests.zig b/src/eval/test/eval_tests.zig index 437e628456b..a7359ee1537 100644 --- a/src/eval/test/eval_tests.zig +++ b/src/eval/test/eval_tests.zig @@ -643,12 +643,12 @@ const core_tests = [_]TestCase{ .expected = .{ .inspect_str = "(\"other\", \"one byte\")" }, }, .{ - .name = "inspect: custom from_quote receives literal bytes", + .name = "inspect: custom from_quote receives literal Str", .source_kind = .module, .source = - \\Tag := [Tag(List(U8))].{ - \\ from_quote : List(U8) -> Try(Tag, [BadQuotedBytes(Str)]) - \\ from_quote = |bytes| Ok(Tag(bytes)) + \\Tag := [Tag(Str)].{ + \\ from_quote : Str -> Try(Tag, [BadQuotedBytes(Str)]) + \\ from_quote = |str| Ok(Tag(str)) \\} \\ \\force : Tag -> Tag @@ -656,7 +656,7 @@ const core_tests = [_]TestCase{ \\ \\main = force("Roc") , - .expected = .{ .inspect_str = "Tag([82, 111, 99])" }, + .expected = .{ .inspect_str = "Tag(\"Roc\")" }, }, .{ .name = "inspect: from_quote literal defaults to Str", @@ -670,9 +670,9 @@ const core_tests = [_]TestCase{ .name = "inspect: custom from_quote literal pattern dispatches through is_eq", .source_kind = .module, .source = - \\Tag := [Tag(List(U8))].{ - \\ from_quote : List(U8) -> Try(Tag, [BadQuotedBytes(Str)]) - \\ from_quote = |bytes| Ok(Tag(bytes)) + \\Tag := [Tag(Str)].{ + \\ from_quote : Str -> Try(Tag, [BadQuotedBytes(Str)]) + \\ from_quote = |str| Ok(Tag(str)) \\ is_eq : Tag, Tag -> Bool \\ is_eq = |a, b| match (a, b) { \\ (Tag(x), Tag(y)) => x == y @@ -710,14 +710,14 @@ const core_tests = [_]TestCase{ .name = "inspect: string literal type suffix pins custom from_quote target", .source_kind = .module, .source = - \\Tag := [Tag(List(U8))].{ - \\ from_quote : List(U8) -> Try(Tag, [BadQuotedBytes(Str)]) - \\ from_quote = |bytes| Ok(Tag(bytes)) + \\Tag := [Tag(Str)].{ + \\ from_quote : Str -> Try(Tag, [BadQuotedBytes(Str)]) + \\ from_quote = |str| Ok(Tag(str)) \\} \\ \\main = "Roc".Tag , - .expected = .{ .inspect_str = "Tag([82, 111, 99])" }, + .expected = .{ .inspect_str = "Tag(\"Roc\")" }, }, .{ .name = "inspect: string literal Str type suffix", @@ -732,8 +732,8 @@ const core_tests = [_]TestCase{ .source_kind = .module, .source = \\Tally := [Tally(U64)].{ - \\ from_quote : List(U8) -> Try(Tally, [BadQuotedBytes(Str)]) - \\ from_quote = |bytes| Ok(Tally(bytes.len())) + \\ from_quote : Str -> Try(Tally, [BadQuotedBytes(Str)]) + \\ from_quote = |str| Ok(Tally(str.count_utf8_bytes())) \\} \\ \\main = { @@ -751,11 +751,11 @@ const core_tests = [_]TestCase{ .source_kind = .module, .source = \\Url := [Url(Str)].{ - \\ from_quote : List(U8) -> Try(Url, [BadQuotedBytes(Str)]) - \\ from_quote = |bytes| Ok(Url(Str.from_utf8_lossy(bytes))) - \\ from_interpolation : Url, Iter((Str, Url)) -> Url + \\ from_quote : Str -> Try(Url, [BadQuotedBytes(Str)]) + \\ from_quote = |str| Ok(Url(str)) + \\ from_interpolation : Str, Iter((Str, Str)) -> Url \\ from_interpolation = |first, rest| { - \\ Url.Url(rest.fold(first.inner(), |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment.inner()))) + \\ Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment))) \\ } \\ inner : Url -> Str \\ inner = |Url.Url(str)| str @@ -770,6 +770,58 @@ const core_tests = [_]TestCase{ , .expected = .{ .inspect_str = "Url(\"https://example.com\")" }, }, + .{ + .name = "inspect: Try interpolation forwards to custom result type", + .source_kind = .module, + .source = + \\Url := [Url(Str)].{ + \\ from_interpolation : Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl]) + \\ from_interpolation = |first, rest| Ok(Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment)))) + \\} + \\ + \\main = { + \\ domain = "example" + \\ url : Try(Url, [InvalidUrl]) + \\ url = "https://${domain}.com" + \\ url + \\} + , + .expected = .{ .inspect_str = "Ok(Url(\"https://example.com\"))" }, + }, + .{ + .name = "problem: nested Try interpolation does not recursively satisfy forwarding", + .source_kind = .module, + .source = + \\Url := [Url(Str)].{ + \\ from_interpolation : Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl]) + \\ from_interpolation = |first, rest| Ok(Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment)))) + \\} + \\ + \\main = { + \\ domain = "example" + \\ url : Try(Try(Url, [InvalidUrl]), [Outer]) + \\ url = "https://${domain}.com" + \\ url + \\} + , + .expected = .{ .problem = {} }, + }, + .{ + .name = "inspect: suffixed interpolation accepts custom return type", + .source_kind = .module, + .source = + \\Url := [Url(Str)].{ + \\ from_interpolation : Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl]) + \\ from_interpolation = |first, rest| Ok(Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment)))) + \\} + \\ + \\main = { + \\ domain = "example" + \\ "https://${domain}.com".Url + \\} + , + .expected = .{ .inspect_str = "Ok(Url(\"https://example.com\"))" }, + }, .{ .name = "inspect: interpolation with adjacent and boundary interpolations", .source_kind = .module, @@ -787,8 +839,8 @@ const core_tests = [_]TestCase{ .source_kind = .module, .source = \\Strict := [Strict].{ - \\ from_quote : List(U8) -> Try(Strict, [BadQuotedBytes(Str)]) - \\ from_quote = |_bytes| Err(BadQuotedBytes("Strict rejects every string")) + \\ from_quote : Str -> Try(Strict, [BadQuotedBytes(Str)]) + \\ from_quote = |_str| Err(BadQuotedBytes("Strict rejects every string")) \\} \\ \\force : Strict -> Strict diff --git a/src/eval/test/parallel_runner.zig b/src/eval/test/parallel_runner.zig index 0cd089bba1b..a71f9b03a28 100644 --- a/src/eval/test/parallel_runner.zig +++ b/src/eval/test/parallel_runner.zig @@ -44,7 +44,7 @@ //! ## Hang detection //! //! Integrated into the parent's poll() loop. If a child has been running -//! longer than the timeout (default 30s for interpreter/dev/wasm, 7 minutes +//! longer than the timeout (default 60s for interpreter/dev/wasm, 7 minutes //! for LLVM), the parent SIGKILLs it. No separate watchdog thread is needed. //! //! ## Usage @@ -81,6 +81,8 @@ const helpers = eval.test_helpers; const LoweredProgram = helpers.LoweredProgram; const posix = std.posix; +const DEFAULT_EVAL_TIMEOUT_MS: u64 = 60_000; +const MUSL_EVAL_TIMEOUT_MS: u64 = 120_000; fn milliTimestamp(io: std.Io) i64 { return std.Io.Timestamp.now(io, .awake).toMilliseconds(); @@ -1713,7 +1715,7 @@ fn printHelp() void { \\ --threads Max concurrent child processes (default: number of CPU cores). \\ --verbose Print PASS and SKIP results (default: only FAIL/CRASH). \\ --timeout Hang timeout in ms for parse/interp/dev/wasm. - \\ Default: 30000, 120000 on musl. + \\ Default: 60000, 120000 on musl. \\ LLVM uses a separate 420000ms backend budget. \\ LLVM eval lock slots match the worker count. \\ --llvm Include the LLVM backend. Default: skip LLVM. @@ -2137,10 +2139,10 @@ const WorkerTrace = struct { } }; -fn effectiveHangTimeoutMs(cli: harness.StandardArgs, max_children: usize) u64 { +fn effectiveHangTimeoutMs(cli: harness.StandardArgs) u64 { if (cli.timeout_provided and cli.timeout_ms > 0) return cli.timeout_ms; - if (builtin.abi == .musl) return 120_000; - return if (max_children <= 1) 10_000 else 30_000; + if (builtin.abi == .musl) return MUSL_EVAL_TIMEOUT_MS; + return DEFAULT_EVAL_TIMEOUT_MS; } fn effectiveMaxChildren(cli: harness.StandardArgs, cpu_count: usize, test_count: usize) usize { @@ -2228,7 +2230,7 @@ pub fn main(init: std.process.Init) anyerror!void { if (idx >= tests.len) std.process.exit(2); var tc = tests[idx]; if (cli.worker_backend) |name| applyBackendIsolation(&tc.skip, name); - const worker_timeout_ms: u64 = if (cli.timeout_provided and cli.timeout_ms > 0) cli.timeout_ms else 30_000; + const worker_timeout_ms: u64 = if (cli.timeout_provided and cli.timeout_ms > 0) cli.timeout_ms else DEFAULT_EVAL_TIMEOUT_MS; var arena = collections.SingleThreadArena.init(base.defaultGpa()); defer arena.deinit(); @@ -2259,7 +2261,7 @@ pub fn main(init: std.process.Init) anyerror!void { // until stdin EOFs. Amortizes the per-Child process-boot cost across // many tests on the same worker. if (cli.worker_stream) { - const worker_timeout_ms: u64 = if (cli.timeout_provided and cli.timeout_ms > 0) cli.timeout_ms else 30_000; + const worker_timeout_ms: u64 = if (cli.timeout_provided and cli.timeout_ms > 0) cli.timeout_ms else DEFAULT_EVAL_TIMEOUT_MS; var arena = collections.SingleThreadArena.init(base.defaultGpa()); defer arena.deinit(); @@ -2353,7 +2355,7 @@ pub fn main(init: std.process.Init) anyerror!void { // Native musl CI has enough process-startup variance for the larger shared // harness default to be more reliable, especially for heavy boundary tests. - const hang_timeout_ms: u64 = effectiveHangTimeoutMs(cli, max_children); + const hang_timeout_ms: u64 = effectiveHangTimeoutMs(cli); // Build a worker_argv_template so Windows can spawn `Child` workers that // re-invoke this binary with `--worker `. On POSIX the template is diff --git a/src/layout/type_layout_resolver.zig b/src/layout/type_layout_resolver.zig index 7dfd0750307..51e90d006e1 100644 --- a/src/layout/type_layout_resolver.zig +++ b/src/layout/type_layout_resolver.zig @@ -679,7 +679,7 @@ pub const Resolver = struct { for (self.getTypesStore(module_idx).sliceStaticDispatchConstraints(constraints)) |constraint| { switch (constraint.origin) { .from_numeral, .desugared_binop, .desugared_unaryop => return true, - .method_call, .where_clause => {}, + .from_quote, .from_interpolation, .method_call, .where_clause => {}, } } diff --git a/src/lsp/cir_visitor.zig b/src/lsp/cir_visitor.zig index 0f10c195e52..7921c6f1b90 100644 --- a/src/lsp/cir_visitor.zig +++ b/src/lsp/cir_visitor.zig @@ -211,6 +211,12 @@ pub fn CirVisitor(comptime Context: type) type { if (self.stopped) return; } }, + .e_interpolation => |interpolation| { + self.walkExpr(store, interpolation.first); + if (self.stopped) return; + self.walkExpr(store, interpolation.rest); + if (self.stopped) return; + }, .e_structural_eq => |eq| { self.walkExpr(store, eq.lhs); if (self.stopped) return; diff --git a/src/lsp/scope_map.zig b/src/lsp/scope_map.zig index a7a37e6b23b..debb20a5d3f 100644 --- a/src/lsp/scope_map.zig +++ b/src/lsp/scope_map.zig @@ -267,6 +267,10 @@ pub const ScopeMap = struct { try self.traverseExpr(module_env, arg_idx, scope_end, depth + 1); } }, + .e_interpolation => |interpolation| { + try self.traverseExpr(module_env, interpolation.first, scope_end, depth + 1); + try self.traverseExpr(module_env, interpolation.rest, scope_end, depth + 1); + }, .e_structural_eq => |eq| { try self.traverseExpr(module_env, eq.lhs, scope_end, depth + 1); try self.traverseExpr(module_env, eq.rhs, scope_end, depth + 1); diff --git a/src/postcheck/monotype/lower.zig b/src/postcheck/monotype/lower.zig index 31abebde7ed..b967630f275 100644 --- a/src/postcheck/monotype/lower.zig +++ b/src/postcheck/monotype/lower.zig @@ -3333,6 +3333,7 @@ const BodyContext = struct { return switch (expr.data) { .call => |call| (try self.callResultMonoType(expr.ty, call, null)) orelse try self.lowerType(expr.ty), .dispatch_call => |plan| (try self.dispatchResultMonoType(expr.ty, plan, null)) orelse try self.lowerType(expr.ty), + .interpolation => |plan| (try self.dispatchResultMonoType(expr.ty, plan, null)) orelse try self.lowerType(expr.ty), .type_dispatch_call => |plan| (try self.dispatchResultMonoType(expr.ty, plan, null)) orelse try self.lowerType(expr.ty), .method_eq => |plan| (try self.dispatchResultMonoType(expr.ty, plan, null)) orelse try self.lowerType(expr.ty), .lookup_local => |lookup| try self.lookupExprMonoType(expr.ty, lookup.resolved), @@ -3369,6 +3370,7 @@ const BodyContext = struct { switch (expr.data) { .call => |call| return try self.lowerCallExpr(expr.ty, call), .dispatch_call => |plan| return try self.lowerDispatchExpr(expr.ty, plan), + .interpolation => |plan| return try self.lowerDispatchExpr(expr.ty, plan), .type_dispatch_call => |plan| return try self.lowerDispatchExpr(expr.ty, plan), .method_eq => |plan| return try self.lowerDispatchExpr(expr.ty, plan), .structural_eq => |eq| return try self.lowerDirectStructuralEq(expr.ty, eq), @@ -3440,6 +3442,7 @@ const BodyContext = struct { }, .call => Common.invariant("call expression reached ordinary expression lowering after call-site lowering"), .dispatch_call, + .interpolation, .type_dispatch_call, .method_eq, => Common.invariant("dispatch expression reached ordinary expression lowering after call-site lowering"), @@ -3822,6 +3825,7 @@ const BodyContext = struct { switch (expr.data) { .call => |call| return try self.callResultMonoType(expr.ty, call, expected_ty), .dispatch_call => |plan| return try self.dispatchResultMonoType(expr.ty, plan, expected_ty), + .interpolation => |plan| return try self.dispatchResultMonoType(expr.ty, plan, expected_ty), .type_dispatch_call => |plan| return try self.dispatchResultMonoType(expr.ty, plan, expected_ty), .method_eq => |plan| return try self.dispatchResultMonoType(expr.ty, plan, expected_ty), .field_access => |field| return try self.fieldAccessMonoType(field.receiver, field.field_name), @@ -4486,6 +4490,7 @@ const BodyContext = struct { }); }, .dispatch_call => |plan| return try self.lowerDispatchExprAtType(expr.ty, plan, ty), + .interpolation => |plan| return try self.lowerDispatchExprAtType(expr.ty, plan, ty), .type_dispatch_call => |plan| return try self.lowerDispatchExprAtType(expr.ty, plan, ty), .method_eq => |plan| return try self.lowerDispatchExprAtType(expr.ty, plan, ty), .lookup_local => |lookup| return try self.lowerLookupExprAtType(expr.ty, lookup.resolved, ty), @@ -4903,27 +4908,17 @@ const BodyContext = struct { }; } - /// Materialize a string literal's bytes as the `List(U8)` argument of a - /// `from_quote` dispatch call. + /// Materialize a string literal as the `Str` argument of a `from_quote` + /// dispatch call. fn lowerQuoteValue( self: *BodyContext, literal: checked.CheckedStringLiteralId, ty: Type.TypeId, ) Allocator.Error!Ast.ExprId { - const bytes = self.view.bodies.string_literals[@intFromEnum(literal)]; - const data: Ast.ExprData = .{ .list = blk: { - const elem_ty = switch (self.builder.shapeContent(ty)) { - .list => |elem| elem, - else => Common.invariant("checked from_quote argument was not a List(U8)"), - }; - const items = try self.allocator.alloc(Ast.ExprId, bytes.len); - defer self.allocator.free(items); - for (bytes, 0..) |byte, i| { - items[i] = try self.builder.intLiteralExpr(byte, elem_ty); - } - break :blk try self.builder.program.addExprSpan(items); - } }; - return try self.builder.program.addExpr(.{ .ty = ty, .data = data }); + return try self.builder.program.addExpr(.{ + .ty = ty, + .data = .{ .str_lit = try self.lowerStringLiteral(literal) }, + }); } fn lowerNumeralValue( @@ -5295,10 +5290,66 @@ const BodyContext = struct { fn structuralEqualityOperandType(self: *BodyContext, eq: anytype) Allocator.Error!Type.TypeId { const lhs_checked_ty = self.view.bodies.exprs[@intFromEnum(eq.lhs)].ty; const rhs_checked_ty = self.view.bodies.exprs[@intFromEnum(eq.rhs)].ty; + const conflict_message = "checked structural equality operand type conflicted with an existing Monotype constraint"; + try self.constrainCheckedTypeRelations(lhs_checked_ty, self, rhs_checked_ty); + + if (try self.structuralEqualityExprResultType(eq.lhs, null)) |lhs_ty| { + return try self.constrainStructuralEqualityOperandType(lhs_ty, eq.rhs, rhs_checked_ty, conflict_message); + } + if (try self.structuralEqualityExprResultType(eq.rhs, null)) |rhs_ty| { + return try self.constrainStructuralEqualityOperandType(rhs_ty, eq.lhs, lhs_checked_ty, conflict_message); + } + return try self.lowerType(lhs_checked_ty); } + /// Resolves the Monotype an equality operand evaluates to, when that operand is a + /// result-producing expression (call, dispatch, lookup, field access). The shared + /// equality operand type is taken from this result so an open tag literal on the other + /// side cannot narrow it. Returns null for any other expression shape (e.g. a tag + /// literal): the caller then falls through to the concrete-shape ladder in + /// structuralEqualityOperandType, so this must not fall back to lowerType itself. + fn structuralEqualityExprResultType( + self: *BodyContext, + expr_id: checked.CheckedExprId, + expected_ty: ?Type.TypeId, + ) Allocator.Error!?Type.TypeId { + const expr = self.view.bodies.exprs[@intFromEnum(expr_id)]; + return switch (expr.data) { + .call => |call| try self.callResultMonoType(expr.ty, call, expected_ty), + .dispatch_call => |plan| try self.dispatchResultMonoType(expr.ty, plan, expected_ty), + .interpolation => |plan| try self.dispatchResultMonoType(expr.ty, plan, expected_ty), + .type_dispatch_call => |plan| try self.dispatchResultMonoType(expr.ty, plan, expected_ty), + .method_eq => |plan| try self.dispatchResultMonoType(expr.ty, plan, expected_ty), + .lookup_local => |lookup| try self.lookupExprMonoType(expr.ty, lookup.resolved), + .lookup_external => |resolved| try self.lookupExprMonoType(expr.ty, resolved), + .lookup_required => |resolved| try self.lookupExprMonoType(expr.ty, resolved), + .field_access => |field| blk: { + if (expected_ty) |ty| { + try self.constrainTypeToMono(expr.ty, ty); + break :blk ty; + } + break :blk try self.fieldAccessMonoType(field.receiver, field.field_name); + }, + else => null, + }; + } + + fn constrainStructuralEqualityOperandType( + self: *BodyContext, + operand_ty: Type.TypeId, + other_expr_id: checked.CheckedExprId, + other_checked_ty: checked.CheckedTypeId, + comptime conflict_message: []const u8, + ) Allocator.Error!Type.TypeId { + try self.constrainTypeToMono(other_checked_ty, operand_ty); + if (try self.structuralEqualityExprResultType(other_expr_id, operand_ty)) |other_ty| { + if (!self.sameType(operand_ty, other_ty)) Common.invariant(conflict_message); + } + return operand_ty; + } + fn lowerEqualityExpr( self: *BodyContext, ty: Type.TypeId, @@ -7795,6 +7846,7 @@ const BodyContext = struct { .empty_record, .zero_argument_tag, .dispatch_call, + .interpolation, .method_eq, .type_dispatch_call, .runtime_error, diff --git a/src/types/types.zig b/src/types/types.zig index 638df26a432..743deca7740 100644 --- a/src/types/types.zig +++ b/src/types/types.zig @@ -932,6 +932,7 @@ pub const StaticDispatchConstraint = struct { where_clause, // From where clause in type annotation from_numeral, // From numeric literal conversion from_quote, // From string literal conversion + from_interpolation, // From interpolated string literal conversion }; /// A safe list of static dispatch constraints diff --git a/test/serialization_size_check.zig b/test/serialization_size_check.zig index a47a3fb178e..a2898fa1a4e 100644 --- a/test/serialization_size_check.zig +++ b/test/serialization_size_check.zig @@ -31,7 +31,7 @@ const expected_safelist_u8_size = 24; const expected_safelist_u32_size = 24; const expected_safemultilist_teststruct_size = 24; const expected_safemultilist_node_size = 24; -const expected_moduleenv_size = 1712; // Platform-independent size +const expected_moduleenv_size = 1696; // Platform-independent size const expected_nodestore_size = 384; // Platform-independent size // Compile-time assertions - build will fail if sizes don't match expected values diff --git a/test/snapshots/annotations.md b/test/snapshots/annotations.md index 34ef47d0342..4875e8fa79e 100644 --- a/test/snapshots/annotations.md +++ b/test/snapshots/annotations.md @@ -246,7 +246,7 @@ NO CHANGE (ty-rigid-var-lookup (ty-rigid-var (name "a"))))))) (d-let (p-assign (ident "succeedPairSameType")) - (e-call (constraint-fn-var 426) + (e-call (constraint-fn-var 408) (e-lookup-local (p-assign (ident "mkPair"))) (e-num (value "1")) @@ -256,7 +256,7 @@ NO CHANGE (ty-lookup (name "U8") (builtin))))) (d-let (p-assign (ident "failPairDiffTypes")) - (e-call (constraint-fn-var 559) + (e-call (constraint-fn-var 538) (e-lookup-local (p-assign (ident "mkPair"))) (e-string diff --git a/test/snapshots/arrow_lambda.md b/test/snapshots/arrow_lambda.md index cc08d95cf53..bae0a1a9d14 100644 --- a/test/snapshots/arrow_lambda.md +++ b/test/snapshots/arrow_lambda.md @@ -90,7 +90,7 @@ NO CHANGE (e-num (value "10")))) (d-let (p-assign (ident "test2")) - (e-call (constraint-fn-var 134) + (e-call (constraint-fn-var 128) (e-lambda (args (p-underscore)) @@ -100,14 +100,14 @@ NO CHANGE (e-literal (string "hello"))))) (d-let (p-assign (ident "test3")) - (e-call (constraint-fn-var 188) + (e-call (constraint-fn-var 173) (e-lambda (args (p-assign (ident "s"))) (e-if (if-branches (if-branch - (e-dispatch-call (method "is_empty") (constraint-fn-var 135) + (e-dispatch-call (method "is_empty") (constraint-fn-var 129) (receiver (e-lookup-local (p-assign (ident "s")))) diff --git a/test/snapshots/arrow_qualified_functions.md b/test/snapshots/arrow_qualified_functions.md index 079b8dad211..27e1603c24d 100644 --- a/test/snapshots/arrow_qualified_functions.md +++ b/test/snapshots/arrow_qualified_functions.md @@ -117,21 +117,21 @@ test7 = 42->Ok() (can-ir (d-let (p-assign (ident "test1")) - (e-call (constraint-fn-var 79) + (e-call (constraint-fn-var 76) (e-lookup-external (builtin)) (e-string (e-literal (string "hello"))))) (d-let (p-assign (ident "test2")) - (e-call (constraint-fn-var 139) + (e-call (constraint-fn-var 121) (e-lookup-external (builtin)) (e-string (e-literal (string "hello"))))) (d-let (p-assign (ident "test3")) - (e-call (constraint-fn-var 222) + (e-call (constraint-fn-var 186) (e-lookup-external (builtin)) (e-string @@ -147,13 +147,13 @@ test7 = 42->Ok() (p-assign (ident "a"))))) (d-let (p-assign (ident "test4")) - (e-call (constraint-fn-var 327) + (e-call (constraint-fn-var 267) (e-lookup-local (p-assign (ident "fn0"))) (e-num (value "10")))) (d-let (p-assign (ident "test5")) - (e-call (constraint-fn-var 360) + (e-call (constraint-fn-var 300) (e-lookup-local (p-assign (ident "fn0"))) (e-num (value "10")))) diff --git a/test/snapshots/bound_type_var_no_annotation.md b/test/snapshots/bound_type_var_no_annotation.md index 15bcafa7472..27dcbcc2cec 100644 --- a/test/snapshots/bound_type_var_no_annotation.md +++ b/test/snapshots/bound_type_var_no_annotation.md @@ -229,14 +229,14 @@ main! = |_| { (e-num (value "42")))) (s-let (p-assign (ident "text")) - (e-call (constraint-fn-var 244) + (e-call (constraint-fn-var 241) (e-lookup-local (p-assign (ident "identity"))) (e-string (e-literal (string "hello"))))) (s-let (p-assign (ident "pair")) - (e-call (constraint-fn-var 249) + (e-call (constraint-fn-var 246) (e-lookup-local (p-assign (ident "combine"))) (e-lookup-local @@ -245,7 +245,7 @@ main! = |_| { (p-assign (ident "text"))))) (s-let (p-assign (ident "result")) - (e-call (constraint-fn-var 280) + (e-call (constraint-fn-var 277) (e-lookup-local (p-assign (ident "addOne"))) (e-num (value "5")))) diff --git a/test/snapshots/can_list_mismatch_then_nested_error.md b/test/snapshots/can_list_mismatch_then_nested_error.md index 5b97298bcff..3784bb538ec 100644 --- a/test/snapshots/can_list_mismatch_then_nested_error.md +++ b/test/snapshots/can_list_mismatch_then_nested_error.md @@ -32,7 +32,7 @@ Other code expects this to have the type: List(a) where [ a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)]), - a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), + a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), ] **TYPE MISMATCH** @@ -48,7 +48,7 @@ The type was determined to be: List(a) where [ a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)]), - a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), + a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), ] **TYPE MISMATCH** diff --git a/test/snapshots/comprehensive/Container.md b/test/snapshots/comprehensive/Container.md index 0ce35bfd918..17d18382611 100644 --- a/test/snapshots/comprehensive/Container.md +++ b/test/snapshots/comprehensive/Container.md @@ -966,14 +966,14 @@ main = { (e-num (value "42")))) (s-let (p-assign (ident "_test2")) - (e-call (constraint-fn-var 539) + (e-call (constraint-fn-var 536) (e-lookup-local (p-assign (ident "id"))) (e-string (e-literal (string "test"))))) (s-let (p-assign (ident "result")) - (e-dispatch-call (method "map") (constraint-fn-var 540) + (e-dispatch-call (method "map") (constraint-fn-var 537) (receiver (e-lookup-local (p-assign (ident "container")))) @@ -1033,14 +1033,14 @@ main = { (e-block (s-let (p-assign (ident "mapped")) - (e-dispatch-call (method "map") (constraint-fn-var 542) + (e-dispatch-call (method "map") (constraint-fn-var 539) (receiver (e-lookup-local (p-assign (ident "container")))) (args (e-lookup-local (p-assign (ident "f")))))) - (e-dispatch-call (method "get_or") (constraint-fn-var 544) + (e-dispatch-call (method "get_or") (constraint-fn-var 541) (receiver (e-lookup-local (p-assign (ident "mapped")))) @@ -1066,20 +1066,20 @@ main = { (e-tag (name "Empty")))) (s-let (p-assign (ident "id_num")) - (e-call (constraint-fn-var 642) + (e-call (constraint-fn-var 636) (e-lookup-local (p-assign (ident "id"))) (e-num (value "42")))) (s-let (p-assign (ident "id_str")) - (e-call (constraint-fn-var 661) + (e-call (constraint-fn-var 652) (e-lookup-local (p-assign (ident "id"))) (e-string (e-literal (string "world"))))) (s-let (p-assign (ident "id_bool")) - (e-call (constraint-fn-var 665) + (e-call (constraint-fn-var 656) (e-lookup-local (p-assign (ident "id"))) (e-tag (name "True")))) @@ -1088,7 +1088,7 @@ main = { (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 696) + (e-dispatch-call (method "plus") (constraint-fn-var 687) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -1096,8 +1096,8 @@ main = { (e-num (value "10")))))) (s-let (p-assign (ident "processor")) - (e-call (constraint-fn-var 721) - (e-call (constraint-fn-var 713) + (e-call (constraint-fn-var 712) + (e-call (constraint-fn-var 704) (e-lookup-local (p-assign (ident "make_processor"))) (e-lookup-local @@ -1106,13 +1106,13 @@ main = { (p-assign (ident "add_ten"))))) (s-let (p-assign (ident "processed")) - (e-call (constraint-fn-var 752) + (e-call (constraint-fn-var 743) (e-lookup-local (p-assign (ident "processor"))) (e-num (value "5")))) (s-let (p-assign (ident "num_result")) - (e-dispatch-call (method "map") (constraint-fn-var 785) + (e-dispatch-call (method "map") (constraint-fn-var 776) (receiver (e-lookup-local (p-assign (ident "num_container")))) @@ -1120,7 +1120,7 @@ main = { (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 783) + (e-dispatch-call (method "plus") (constraint-fn-var 774) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -1128,7 +1128,7 @@ main = { (e-num (value "1")))))))) (s-let (p-assign (ident "_str_result")) - (e-dispatch-call (method "map") (constraint-fn-var 795) + (e-dispatch-call (method "map") (constraint-fn-var 786) (receiver (e-lookup-local (p-assign (ident "str_container")))) @@ -1140,11 +1140,11 @@ main = { (p-assign (ident "s"))))))) (s-let (p-assign (ident "chained")) - (e-dispatch-call (method "get_or") (constraint-fn-var 925) + (e-dispatch-call (method "get_or") (constraint-fn-var 916) (receiver - (e-dispatch-call (method "flat_map") (constraint-fn-var 885) + (e-dispatch-call (method "flat_map") (constraint-fn-var 876) (receiver - (e-dispatch-call (method "map") (constraint-fn-var 837) + (e-dispatch-call (method "map") (constraint-fn-var 828) (receiver (e-lookup-local (p-assign (ident "num_container")))) @@ -1152,7 +1152,7 @@ main = { (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 835) + (e-dispatch-call (method "plus") (constraint-fn-var 826) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -1165,7 +1165,7 @@ main = { (e-nominal (nominal "Container") (e-tag (name "Value") (args - (e-dispatch-call (method "plus") (constraint-fn-var 877) + (e-dispatch-call (method "plus") (constraint-fn-var 868) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -1178,7 +1178,7 @@ main = { (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 932) + (e-dispatch-call (method "plus") (constraint-fn-var 923) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -1187,7 +1187,7 @@ main = { (p-assign (ident "x"))))))) (s-let (p-assign (ident "transformed")) - (e-call (constraint-fn-var 970) + (e-call (constraint-fn-var 961) (e-lookup-local (p-assign (ident "transform_twice"))) (e-lookup-local @@ -1214,7 +1214,7 @@ main = { (e-lookup-local (p-assign (ident "transformed")))) (field (name "final") - (e-dispatch-call (method "get_or") (constraint-fn-var 1001) + (e-dispatch-call (method "get_or") (constraint-fn-var 992) (receiver (e-lookup-local (p-assign (ident "num_result")))) diff --git a/test/snapshots/dev_object_string_interpolation.md b/test/snapshots/dev_object_string_interpolation.md index 252b3afead3..1d3706be9d2 100644 --- a/test/snapshots/dev_object_string_interpolation.md +++ b/test/snapshots/dev_object_string_interpolation.md @@ -38,7 +38,7 @@ name = "World" main = { cinterp_0 = greeting cinterp_1 = name - "".from_interpolation([].iter().prepended((cinterp_1, "!")).prepended((cinterp_0, ", "))) + ("", [cinterp_0, ", ", cinterp_1, "!"]) } ~~~ diff --git a/test/snapshots/effectful_with_effectful_annotation.md b/test/snapshots/effectful_with_effectful_annotation.md index ae270ec1992..2fdfa48ce8f 100644 --- a/test/snapshots/effectful_with_effectful_annotation.md +++ b/test/snapshots/effectful_with_effectful_annotation.md @@ -107,7 +107,7 @@ NO CHANGE (ty-record)))) (d-let (p-assign (ident "main!")) - (e-call (constraint-fn-var 55) + (e-call (constraint-fn-var 52) (e-lookup-local (p-assign (ident "print_msg!"))) (e-string diff --git a/test/snapshots/eval/file_import_both.md b/test/snapshots/eval/file_import_both.md index 0ca2e05fc41..2f159b27c7d 100644 --- a/test/snapshots/eval/file_import_both.md +++ b/test/snapshots/eval/file_import_both.md @@ -72,7 +72,7 @@ NO CHANGE (s-expect (e-method-eq (negated "false") (lhs - (e-call (constraint-fn-var 127) + (e-call (constraint-fn-var 112) (e-lookup-external (builtin)) (e-lookup-local diff --git a/test/snapshots/eval/issue8738_question_on_non_try.md b/test/snapshots/eval/issue8738_question_on_non_try.md index d07a79228dc..8db6338d5cf 100644 --- a/test/snapshots/eval/issue8738_question_on_non_try.md +++ b/test/snapshots/eval/issue8738_question_on_non_try.md @@ -144,7 +144,7 @@ NO CHANGE (e-match (match (cond - (e-call (constraint-fn-var 130) + (e-call (constraint-fn-var 127) (e-lookup-local (p-assign (ident "ok_or"))) (e-tag (name "Err") @@ -181,7 +181,7 @@ NO CHANGE (e-empty_record)))))) (d-let (p-assign (ident "result")) - (e-call (constraint-fn-var 168) + (e-call (constraint-fn-var 165) (e-lookup-local (p-assign (ident "do_something")))))) ~~~ diff --git a/test/snapshots/eval/issue8773_polymorphic_opaque.md b/test/snapshots/eval/issue8773_polymorphic_opaque.md index d1147f0783b..2bac1ee18b6 100644 --- a/test/snapshots/eval/issue8773_polymorphic_opaque.md +++ b/test/snapshots/eval/issue8773_polymorphic_opaque.md @@ -191,7 +191,7 @@ NO CHANGE (e-match (match (cond - (e-call (constraint-fn-var 259) + (e-call (constraint-fn-var 241) (e-lookup-external (builtin)) (e-lookup-local @@ -202,7 +202,7 @@ NO CHANGE (pattern (degenerate false) (p-applied-tag))) (value - (e-call (constraint-fn-var 262) + (e-call (constraint-fn-var 244) (e-lookup-local (p-assign (ident "get_text"))) (e-lookup-local diff --git a/test/snapshots/eval/issue8783_fold_recursive_opaque.md b/test/snapshots/eval/issue8783_fold_recursive_opaque.md index 0c2926faa34..53a34c04f34 100644 --- a/test/snapshots/eval/issue8783_fold_recursive_opaque.md +++ b/test/snapshots/eval/issue8783_fold_recursive_opaque.md @@ -172,38 +172,21 @@ NO CHANGE (p-assign (ident "acc")))) (s-let (p-assign (ident "#interp_1")) - (e-call (constraint-fn-var 587) + (e-call (constraint-fn-var 273) (e-lookup-local (p-assign (ident "process"))) (e-lookup-local (p-assign (ident "child"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 771) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 729) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 671) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 607) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " "))))))))))) + (e-interpolation (constraint-fn-var 283) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) (annotation (ty-fn (effectful false) (ty-lookup (name "Str") (builtin)) @@ -232,7 +215,7 @@ NO CHANGE (p-assign (ident "tag")))) (s-let (p-assign (ident "#interp_3")) - (e-call (constraint-fn-var 239) + (e-call (constraint-fn-var 230) (e-lookup-external (builtin)) (e-lookup-local @@ -241,33 +224,16 @@ NO CHANGE (e-literal (string ""))) (e-lookup-local (p-assign (ident "process_child"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 459) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 381) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 323) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 259) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string ":")))))))))))) + (e-interpolation (constraint-fn-var 240) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ":")) + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -295,7 +261,7 @@ NO CHANGE (ty-lookup (name "Elem") (local)))) (d-let (p-assign (ident "result")) - (e-call (constraint-fn-var 1039) + (e-call (constraint-fn-var 402) (e-lookup-local (p-assign (ident "process"))) (e-lookup-local diff --git a/test/snapshots/eval/issue8783_simple_for_match.md b/test/snapshots/eval/issue8783_simple_for_match.md index 2653a637a97..7653fa7eef2 100644 --- a/test/snapshots/eval/issue8783_simple_for_match.md +++ b/test/snapshots/eval/issue8783_simple_for_match.md @@ -212,7 +212,7 @@ NO CHANGE (pattern (degenerate false) (p-applied-tag))) (value - (e-dispatch-call (method "plus") (constraint-fn-var 345) + (e-dispatch-call (method "plus") (constraint-fn-var 315) (receiver (e-lookup-local (p-assign (ident "acc")))) @@ -223,7 +223,7 @@ NO CHANGE (pattern (degenerate false) (p-applied-tag))) (value - (e-dispatch-call (method "plus") (constraint-fn-var 457) + (e-dispatch-call (method "plus") (constraint-fn-var 427) (receiver (e-lookup-local (p-assign (ident "acc")))) @@ -236,7 +236,7 @@ NO CHANGE (ty-lookup (name "I64") (builtin))))) (d-let (p-assign (ident "count")) - (e-call (constraint-fn-var 587) + (e-call (constraint-fn-var 557) (e-lookup-external (builtin)) (e-lookup-local diff --git a/test/snapshots/eval/nominal_record_field_access.md b/test/snapshots/eval/nominal_record_field_access.md index ebc61906ed3..7faf82310ca 100644 --- a/test/snapshots/eval/nominal_record_field_access.md +++ b/test/snapshots/eval/nominal_record_field_access.md @@ -165,7 +165,7 @@ expect getName(Wrapper.WithRecord({ name: "hello" })) == "hello" (s-expect (e-method-eq (negated "false") (lhs - (e-call (constraint-fn-var 196) + (e-call (constraint-fn-var 181) (e-lookup-local (p-assign (ident "getName"))) (e-nominal (nominal "Wrapper") @@ -179,7 +179,7 @@ expect getName(Wrapper.WithRecord({ name: "hello" })) == "hello" (s-expect (e-method-eq (negated "false") (lhs - (e-call (constraint-fn-var 343) + (e-call (constraint-fn-var 298) (e-lookup-local (p-assign (ident "getName"))) (e-nominal (nominal "Wrapper") diff --git a/test/snapshots/eval/str_to_utf8_method.md b/test/snapshots/eval/str_to_utf8_method.md index 13abc2ffe4e..63ecaaafe70 100644 --- a/test/snapshots/eval/str_to_utf8_method.md +++ b/test/snapshots/eval/str_to_utf8_method.md @@ -56,7 +56,7 @@ NO CHANGE (can-ir (d-let (p-assign (ident "bytes")) - (e-dispatch-call (method "to_utf8") (constraint-fn-var 51) + (e-dispatch-call (method "to_utf8") (constraint-fn-var 48) (receiver (e-string (e-literal (string "hello")))) diff --git a/test/snapshots/eval/string_interpolated.md b/test/snapshots/eval/string_interpolated.md index 9784bc4ac44..9f9aeb9ddf4 100644 --- a/test/snapshots/eval/string_interpolated.md +++ b/test/snapshots/eval/string_interpolated.md @@ -67,33 +67,16 @@ NO CHANGE (p-assign (ident "#interp_1")) (e-lookup-local (p-assign (ident "world")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 252) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 210) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 152) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 88) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " "))))))))))) + (e-interpolation (constraint-fn-var 69) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/expr/block_pattern_unify.md b/test/snapshots/expr/block_pattern_unify.md index 0169189b417..50712441e16 100644 --- a/test/snapshots/expr/block_pattern_unify.md +++ b/test/snapshots/expr/block_pattern_unify.md @@ -65,7 +65,7 @@ EndOfFile, (e-literal (string "hello")))) (s-let (p-assign (ident "result")) - (e-dispatch-call (method "plus") (constraint-fn-var 97) + (e-dispatch-call (method "plus") (constraint-fn-var 94) (receiver (e-lookup-local (p-assign (ident "x")))) diff --git a/test/snapshots/expr/string_interpolation_simple.md b/test/snapshots/expr/string_interpolation_simple.md index e61e566652a..2ecd3a5bc23 100644 --- a/test/snapshots/expr/string_interpolation_simple.md +++ b/test/snapshots/expr/string_interpolation_simple.md @@ -33,26 +33,15 @@ NO CHANGE (s-let (p-assign (ident "#interp_0")) (e-runtime-error (tag "ident_not_in_scope"))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 146) - (receiver - (e-string - (e-literal (string "Hello ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 104) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 40) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "!")))))))))) + (e-interpolation + (first + (e-literal (string "Hello "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "!"))))) ~~~ # TYPES ~~~clojure -(expr (type "Str")) +(expr (type "Error")) ~~~ diff --git a/test/snapshots/expr/tag_vs_function_calls.md b/test/snapshots/expr/tag_vs_function_calls.md index 4ac45385827..97327db023a 100644 --- a/test/snapshots/expr/tag_vs_function_calls.md +++ b/test/snapshots/expr/tag_vs_function_calls.md @@ -122,7 +122,7 @@ EndOfFile, (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 141) + (e-dispatch-call (method "plus") (constraint-fn-var 135) (receiver (e-lookup-local (p-assign (ident "x")))) diff --git a/test/snapshots/expr/tuple_comprehensive.md b/test/snapshots/expr/tuple_comprehensive.md index a8b90c730df..cd74061b9a3 100644 --- a/test/snapshots/expr/tuple_comprehensive.md +++ b/test/snapshots/expr/tuple_comprehensive.md @@ -201,7 +201,7 @@ EndOfFile, (p-assign (ident "mixed")) (e-tuple (elems - (e-call (constraint-fn-var 463) + (e-call (constraint-fn-var 460) (e-lookup-local (p-assign (ident "add_one"))) (e-num (value "5"))) @@ -229,7 +229,7 @@ EndOfFile, (e-lambda (args (p-assign (ident "n"))) - (e-dispatch-call (method "plus") (constraint-fn-var 602) + (e-dispatch-call (method "plus") (constraint-fn-var 596) (receiver (e-lookup-local (p-assign (ident "n")))) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_019.md b/test/snapshots/fuzz_crash/fuzz_crash_019.md index 5de65de2493..4b611af7e4b 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_019.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_019.md @@ -1038,7 +1038,7 @@ It has the type: (f, j, Error, [O, ..], (Error, Error), List(k)) where [ f.from_numeral : Numeral -> Try(f, [InvalidNumeral(Str)]), - j.from_quote : List(U8) -> Try(j, [BadQuotedBytes(Str)]), + j.from_quote : Str -> Try(j, [BadQuotedBytes(Str)]), k.from_numeral : Numeral -> Try(k, [InvalidNumeral(Str)]), ] @@ -1106,11 +1106,11 @@ This number is being used where a non-number type is needed: ^^^ The type was determined to be non-numeric here: -**fuzz_crash_019.md:93:14:93:15:** +**fuzz_crash_019.md:93:22:93:24:** ```roc line!("Ag ${n} to ${er}") ``` - ^ + ^^ Other code expects this to have the type: @@ -1920,7 +1920,7 @@ expect { (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 1468) + (e-call (constraint-fn-var 1455) (e-lookup-local (p-assign (ident "me"))) (e-not-implemented))) @@ -1934,24 +1934,13 @@ expect { (s-let (p-assign (ident "#interp_0")) (e-runtime-error (tag "ident_not_in_scope"))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1613) - (receiver - (e-string - (e-literal (string "H, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1571) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1507) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation + (first + (e-literal (string "H, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "t")) (e-list @@ -1979,34 +1968,17 @@ expect { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "er")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1945) - (receiver - (e-string - (e-literal (string "Ag ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1903) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1845) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1781) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " to ")))))))))))) - (e-dispatch-call (method "plus") (constraint-fn-var 1948) + (e-interpolation (constraint-fn-var 1634) + (first + (e-literal (string "Ag "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) + (e-dispatch-call (method "plus") (constraint-fn-var 1637) (receiver (e-runtime-error (tag "ident_not_in_scope"))) (args @@ -2070,7 +2042,7 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 2361) + (e-dispatch-call (method "is_gt") (constraint-fn-var 2041) (receiver (e-match (match @@ -2104,18 +2076,18 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_lt") (constraint-fn-var 2469) + (e-dispatch-call (method "is_lt") (constraint-fn-var 2149) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 2434) + (e-dispatch-call (method "plus") (constraint-fn-var 2114) (receiver (e-num (value "13"))) (args (e-num (value "2"))))) (args (e-num (value "5")))) - (e-dispatch-call (method "is_gte") (constraint-fn-var 2569) + (e-dispatch-call (method "is_gte") (constraint-fn-var 2249) (receiver - (e-dispatch-call (method "minus") (constraint-fn-var 2534) + (e-dispatch-call (method "minus") (constraint-fn-var 2214) (receiver (e-num (value "10"))) (args @@ -2130,7 +2102,7 @@ expect { (builtin) (e-tag (name "True"))))) (if-else - (e-dispatch-call (method "is_lte") (constraint-fn-var 2647) + (e-dispatch-call (method "is_lte") (constraint-fn-var 2327) (receiver (e-num (value "12"))) (args @@ -2144,12 +2116,12 @@ expect { (e-match (match (cond - (e-dispatch-call (method "ned") (constraint-fn-var 2714) + (e-dispatch-call (method "ned") (constraint-fn-var 2394) (receiver (e-match (match (cond - (e-dispatch-call (method "od") (constraint-fn-var 2681) + (e-dispatch-call (method "od") (constraint-fn-var 2361) (receiver (e-match (match @@ -2253,24 +2225,13 @@ expect { (e-call (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2907) - (receiver - (e-string - (e-literal (string "Ho")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2865) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2801) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " "))))))))))))))) + (e-interpolation + (first + (e-literal (string "Ho"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " ")))))))))) (d-let (p-assign (ident "y")) (e-anno-only) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_020.md b/test/snapshots/fuzz_crash/fuzz_crash_020.md index 2e847d04dd9..028c4366bfc 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_020.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_020.md @@ -1034,7 +1034,7 @@ It has the type: (f, j, Error, [O, ..], (Error, Error), List(k)) where [ f.from_numeral : Numeral -> Try(f, [InvalidNumeral(Str)]), - j.from_quote : List(U8) -> Try(j, [BadQuotedBytes(Str)]), + j.from_quote : Str -> Try(j, [BadQuotedBytes(Str)]), k.from_numeral : Numeral -> Try(k, [InvalidNumeral(Str)]), ] @@ -1102,11 +1102,11 @@ This number is being used where a non-number type is needed: ^^^ The type was determined to be non-numeric here: -**fuzz_crash_020.md:93:14:93:15:** +**fuzz_crash_020.md:93:22:93:24:** ```roc line!("Ag ${n} to ${er}") ``` - ^ + ^^ Other code expects this to have the type: @@ -1912,7 +1912,7 @@ expect { (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 1466) + (e-call (constraint-fn-var 1453) (e-lookup-local (p-assign (ident "me"))) (e-not-implemented))) @@ -1926,24 +1926,13 @@ expect { (s-let (p-assign (ident "#interp_0")) (e-runtime-error (tag "ident_not_in_scope"))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1611) - (receiver - (e-string - (e-literal (string "H, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1569) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1505) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation + (first + (e-literal (string "H, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "t")) (e-list @@ -1971,34 +1960,17 @@ expect { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "er")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1943) - (receiver - (e-string - (e-literal (string "Ag ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1901) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1843) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1779) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " to ")))))))))))) - (e-dispatch-call (method "plus") (constraint-fn-var 1946) + (e-interpolation (constraint-fn-var 1632) + (first + (e-literal (string "Ag "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) + (e-dispatch-call (method "plus") (constraint-fn-var 1635) (receiver (e-runtime-error (tag "ident_not_in_scope"))) (args @@ -2062,7 +2034,7 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 2359) + (e-dispatch-call (method "is_gt") (constraint-fn-var 2039) (receiver (e-match (match @@ -2096,18 +2068,18 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_lt") (constraint-fn-var 2467) + (e-dispatch-call (method "is_lt") (constraint-fn-var 2147) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 2432) + (e-dispatch-call (method "plus") (constraint-fn-var 2112) (receiver (e-num (value "13"))) (args (e-num (value "2"))))) (args (e-num (value "5")))) - (e-dispatch-call (method "is_gte") (constraint-fn-var 2567) + (e-dispatch-call (method "is_gte") (constraint-fn-var 2247) (receiver - (e-dispatch-call (method "minus") (constraint-fn-var 2532) + (e-dispatch-call (method "minus") (constraint-fn-var 2212) (receiver (e-num (value "10"))) (args @@ -2122,7 +2094,7 @@ expect { (builtin) (e-tag (name "True"))))) (if-else - (e-dispatch-call (method "is_lte") (constraint-fn-var 2645) + (e-dispatch-call (method "is_lte") (constraint-fn-var 2325) (receiver (e-num (value "12"))) (args @@ -2136,12 +2108,12 @@ expect { (e-match (match (cond - (e-dispatch-call (method "ned") (constraint-fn-var 2712) + (e-dispatch-call (method "ned") (constraint-fn-var 2392) (receiver (e-match (match (cond - (e-dispatch-call (method "od") (constraint-fn-var 2679) + (e-dispatch-call (method "od") (constraint-fn-var 2359) (receiver (e-match (match @@ -2245,24 +2217,13 @@ expect { (e-call (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2905) - (receiver - (e-string - (e-literal (string "Ho")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2863) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2799) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " "))))))))))))))) + (e-interpolation + (first + (e-literal (string "Ho"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " ")))))))))) (d-let (p-assign (ident "y")) (e-anno-only) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_023.md b/test/snapshots/fuzz_crash/fuzz_crash_023.md index 931edbfe1de..56a6d486e7b 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_023.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_023.md @@ -2380,7 +2380,7 @@ expect { (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 2532) + (e-call (constraint-fn-var 2507) (e-lookup-local (p-assign (ident "match_time"))) (e-not-implemented))) @@ -2403,24 +2403,13 @@ expect { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "world")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2691) - (receiver - (e-string - (e-literal (string "Hello, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2649) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2585) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 2547) + (first + (e-literal (string "Hello, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "list")) (e-list @@ -2450,36 +2439,19 @@ expect { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "number")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 3068) - (receiver - (e-string - (e-literal (string "Adding ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 3026) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2968) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2904) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " to ")))))))))))) + (e-interpolation + (first + (e-literal (string "Adding "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) (s-reassign (p-assign (ident "number")) - (e-dispatch-call (method "plus") (constraint-fn-var 3071) + (e-dispatch-call (method "plus") (constraint-fn-var 2751) (receiver (e-lookup-local (p-assign (ident "number")))) @@ -2549,7 +2521,7 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 3470) + (e-dispatch-call (method "is_gt") (constraint-fn-var 3144) (receiver (e-match (match @@ -2574,7 +2546,7 @@ expect { (value (e-num (value "12")))))))) (args - (e-dispatch-call (method "times") (constraint-fn-var 3465) + (e-dispatch-call (method "times") (constraint-fn-var 3139) (receiver (e-num (value "5"))) (args @@ -2589,18 +2561,18 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_lt") (constraint-fn-var 3578) + (e-dispatch-call (method "is_lt") (constraint-fn-var 3252) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 3543) + (e-dispatch-call (method "plus") (constraint-fn-var 3217) (receiver (e-num (value "13"))) (args (e-num (value "2"))))) (args (e-num (value "5")))) - (e-dispatch-call (method "is_gte") (constraint-fn-var 3678) + (e-dispatch-call (method "is_gte") (constraint-fn-var 3352) (receiver - (e-dispatch-call (method "minus") (constraint-fn-var 3643) + (e-dispatch-call (method "minus") (constraint-fn-var 3317) (receiver (e-num (value "10"))) (args @@ -2615,11 +2587,11 @@ expect { (builtin) (e-tag (name "True"))))) (if-else - (e-dispatch-call (method "is_lte") (constraint-fn-var 3788) + (e-dispatch-call (method "is_lte") (constraint-fn-var 3462) (receiver (e-num (value "12"))) (args - (e-dispatch-call (method "div_by") (constraint-fn-var 3783) + (e-dispatch-call (method "div_by") (constraint-fn-var 3457) (receiver (e-num (value "3"))) (args @@ -2634,12 +2606,12 @@ expect { (e-match (match (cond - (e-dispatch-call (method "next_static_dispatch_method") (constraint-fn-var 3854) + (e-dispatch-call (method "next_static_dispatch_method") (constraint-fn-var 3528) (receiver (e-match (match (cond - (e-dispatch-call (method "static_dispatch_method") (constraint-fn-var 3821) + (e-dispatch-call (method "static_dispatch_method") (constraint-fn-var 3495) (receiver (e-match (match @@ -2774,24 +2746,13 @@ expect { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "number"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 4078) - (receiver - (e-string - (e-literal (string "How about ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 4036) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 3972) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " as a string?"))))))))))))) + (e-interpolation + (first + (e-literal (string "How about "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " as a string?")))))))) (annotation (ty-fn (effectful false) (ty-apply (name "List") (builtin) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_027.md b/test/snapshots/fuzz_crash/fuzz_crash_027.md index e1ff777ade0..3df793ae72e 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_027.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_027.md @@ -1885,7 +1885,7 @@ main! = |_| { # Yeah Ie (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 1938) + (e-call (constraint-fn-var 1924) (e-lookup-local (p-assign (ident "match_time"))) (e-not-implemented))) @@ -1908,24 +1908,13 @@ main! = |_| { # Yeah Ie (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "world")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2097) - (receiver - (e-string - (e-literal (string "Hello, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2055) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1991) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 1964) + (first + (e-literal (string "Hello, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "list")) (e-runtime-error (tag "expr_not_canonicalized"))) diff --git a/test/snapshots/fuzz_crash/fuzz_crash_028.md b/test/snapshots/fuzz_crash/fuzz_crash_028.md index eb0f076662c..08bcc2d2790 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_028.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_028.md @@ -2718,7 +2718,7 @@ expect { (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 2068) + (e-call (constraint-fn-var 2049) (e-lookup-local (p-assign (ident "match_time"))) (e-not-implemented))) @@ -2741,24 +2741,13 @@ expect { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "world")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2227) - (receiver - (e-string - (e-literal (string "H, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2185) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2121) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 2089) + (first + (e-literal (string "H, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "t")) (e-list @@ -2773,7 +2762,7 @@ expect { (p-assign (ident "n")) (e-runtime-error (tag "ident_not_in_scope")) (e-block - (e-dispatch-call (method "plus") (constraint-fn-var 2530) + (e-dispatch-call (method "plus") (constraint-fn-var 2216) (receiver (e-call (e-runtime-error (tag "ident_not_in_scope")) @@ -2785,33 +2774,16 @@ expect { (s-let (p-assign (ident "#interp_2")) (e-runtime-error (tag "ident_not_in_scope"))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2528) - (receiver - (e-string - (e-literal (string "Ag ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2486) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2428) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2364) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " to ")))))))))))) + (e-interpolation + (first + (e-literal (string "Ag "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) (args (e-lookup-local (p-assign (ident "n"))))))) @@ -2884,7 +2856,7 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 2980) + (e-dispatch-call (method "is_gt") (constraint-fn-var 2657) (receiver (e-match (match @@ -2909,7 +2881,7 @@ expect { (value (e-num (value "12")))))))) (args - (e-dispatch-call (method "times") (constraint-fn-var 2975) + (e-dispatch-call (method "times") (constraint-fn-var 2652) (receiver (e-num (value "5"))) (args @@ -2924,18 +2896,18 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_lt") (constraint-fn-var 3088) + (e-dispatch-call (method "is_lt") (constraint-fn-var 2765) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 3053) + (e-dispatch-call (method "plus") (constraint-fn-var 2730) (receiver (e-num (value "13"))) (args (e-num (value "2"))))) (args (e-num (value "5")))) - (e-dispatch-call (method "is_gte") (constraint-fn-var 3188) + (e-dispatch-call (method "is_gte") (constraint-fn-var 2865) (receiver - (e-dispatch-call (method "minus") (constraint-fn-var 3153) + (e-dispatch-call (method "minus") (constraint-fn-var 2830) (receiver (e-num (value "10"))) (args @@ -2950,11 +2922,11 @@ expect { (builtin) (e-tag (name "True"))))) (if-else - (e-dispatch-call (method "is_lte") (constraint-fn-var 3298) + (e-dispatch-call (method "is_lte") (constraint-fn-var 2975) (receiver (e-num (value "12"))) (args - (e-dispatch-call (method "div_by") (constraint-fn-var 3293) + (e-dispatch-call (method "div_by") (constraint-fn-var 2970) (receiver (e-num (value "3"))) (args @@ -2969,12 +2941,12 @@ expect { (e-match (match (cond - (e-dispatch-call (method "ned") (constraint-fn-var 3364) + (e-dispatch-call (method "ned") (constraint-fn-var 3041) (receiver (e-match (match (cond - (e-dispatch-call (method "od") (constraint-fn-var 3331) + (e-dispatch-call (method "od") (constraint-fn-var 3008) (receiver (e-match (match @@ -3077,24 +3049,13 @@ expect { (e-runtime-error (tag "ident_not_in_scope")) (e-lookup-local (p-assign (ident "number"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 3556) - (receiver - (e-string - (e-literal (string "Ho")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 3514) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 3450) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " ")))))))))))))) + (e-interpolation + (first + (e-literal (string "Ho"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " "))))))))) (d-let (p-assign (ident "y")) (e-anno-only) diff --git a/test/snapshots/generalize_alias_chain.md b/test/snapshots/generalize_alias_chain.md index e40ec5053ed..10832251313 100644 --- a/test/snapshots/generalize_alias_chain.md +++ b/test/snapshots/generalize_alias_chain.md @@ -88,7 +88,7 @@ main = (alias2(1), alias2("a")) (e-lookup-local (p-assign (ident "alias2"))) (e-num (value "1"))) - (e-call (constraint-fn-var 82) + (e-call (constraint-fn-var 79) (e-lookup-local (p-assign (ident "alias2"))) (e-string diff --git a/test/snapshots/generalize_alias_if_branches.md b/test/snapshots/generalize_alias_if_branches.md index b11184a24ef..0ec42b34302 100644 --- a/test/snapshots/generalize_alias_if_branches.md +++ b/test/snapshots/generalize_alias_if_branches.md @@ -96,7 +96,7 @@ NO CHANGE (e-lookup-local (p-assign (ident "picked"))) (e-num (value "1"))) - (e-call (constraint-fn-var 91) + (e-call (constraint-fn-var 88) (e-lookup-local (p-assign (ident "picked"))) (e-string diff --git a/test/snapshots/generalize_alias_in_tuple.md b/test/snapshots/generalize_alias_in_tuple.md index 22c5eed564e..3b38d19c1b1 100644 --- a/test/snapshots/generalize_alias_in_tuple.md +++ b/test/snapshots/generalize_alias_in_tuple.md @@ -121,12 +121,12 @@ main = { (e-lookup-local (p-assign (ident "a"))) (e-num (value "1"))) - (e-call (constraint-fn-var 86) + (e-call (constraint-fn-var 83) (e-lookup-local (p-assign (ident "a"))) (e-string (e-literal (string "x")))) - (e-call (constraint-fn-var 117) + (e-call (constraint-fn-var 114) (e-lookup-local (p-assign (ident "b"))) (e-num (value "2")))))))) diff --git a/test/snapshots/generalize_alias_local_in_lambda.md b/test/snapshots/generalize_alias_local_in_lambda.md index e8c08fee2fb..3bdb6ecfe47 100644 --- a/test/snapshots/generalize_alias_local_in_lambda.md +++ b/test/snapshots/generalize_alias_local_in_lambda.md @@ -90,7 +90,7 @@ main = |_y| { (e-lookup-local (p-assign (ident "alias"))) (e-num (value "1"))) - (e-call (constraint-fn-var 80) + (e-call (constraint-fn-var 77) (e-lookup-local (p-assign (ident "alias"))) (e-string diff --git a/test/snapshots/if_then_else/if_then_else_nested_chain.md b/test/snapshots/if_then_else/if_then_else_nested_chain.md index 3af037a7a61..68bc77d5c42 100644 --- a/test/snapshots/if_then_else/if_then_else_nested_chain.md +++ b/test/snapshots/if_then_else/if_then_else_nested_chain.md @@ -113,7 +113,7 @@ NO CHANGE (e-string (e-literal (string "zero"))))) (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 177) + (e-dispatch-call (method "is_gt") (constraint-fn-var 171) (receiver (e-lookup-local (p-assign (ident "num")))) diff --git a/test/snapshots/is_eq/record_with_lambda_field.md b/test/snapshots/is_eq/record_with_lambda_field.md index 7d8f03ec7e2..7fc38618df4 100644 --- a/test/snapshots/is_eq/record_with_lambda_field.md +++ b/test/snapshots/is_eq/record_with_lambda_field.md @@ -23,8 +23,8 @@ The type is: { age: a, name: b, process: c -> c } where [ - a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), - b.from_quote : List(U8) -> Try(b, [BadQuotedBytes(Str)]), + a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), + b.from_quote : Str -> Try(b, [BadQuotedBytes(Str)]), ] This record does not support equality because these fields have types that don't support **is_eq**: diff --git a/test/snapshots/is_eq/tag_union_multiple_ineligible.md b/test/snapshots/is_eq/tag_union_multiple_ineligible.md index 147b509e02d..a7f2677e690 100644 --- a/test/snapshots/is_eq/tag_union_multiple_ineligible.md +++ b/test/snapshots/is_eq/tag_union_multiple_ineligible.md @@ -28,8 +28,8 @@ The type is: [Err(a), Ok(b), Transform(c -> c), Validate(d -> Bool), ..] where [ - a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), - b.from_quote : List(U8) -> Try(b, [BadQuotedBytes(Str)]), + a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), + b.from_quote : Str -> Try(b, [BadQuotedBytes(Str)]), d.from_numeral : Numeral -> Try(d, [InvalidNumeral(Str)]), d.is_gt : d, d -> Bool, ] @@ -154,7 +154,7 @@ expect result == result (e-lambda (args (p-assign (ident "n"))) - (e-dispatch-call (method "is_gt") (constraint-fn-var 101) + (e-dispatch-call (method "is_gt") (constraint-fn-var 98) (receiver (e-lookup-local (p-assign (ident "n")))) diff --git a/test/snapshots/issue/inspect_open_union.md b/test/snapshots/issue/inspect_open_union.md index ed51f56a4c4..2144ba630f2 100644 --- a/test/snapshots/issue/inspect_open_union.md +++ b/test/snapshots/issue/inspect_open_union.md @@ -108,7 +108,7 @@ main_for_host = |result| (pattern (degenerate false) (p-applied-tag))) (value - (e-call (constraint-fn-var 108) + (e-call (constraint-fn-var 105) (e-lookup-external (builtin)) (e-lookup-local @@ -118,7 +118,7 @@ main_for_host = |result| (pattern (degenerate false) (p-applied-tag))) (value - (e-call (constraint-fn-var 152) + (e-call (constraint-fn-var 137) (e-lookup-external (builtin)) (e-lookup-local diff --git a/test/snapshots/issue/issue_8994.md b/test/snapshots/issue/issue_8994.md index 153601b47be..c74918a1169 100644 --- a/test/snapshots/issue/issue_8994.md +++ b/test/snapshots/issue/issue_8994.md @@ -155,7 +155,7 @@ result = duplicate(["a", "b", "c"]) (ty-rigid-var-lookup (ty-rigid-var (name "a"))))))) (d-let (p-assign (ident "result")) - (e-call (constraint-fn-var 154) + (e-call (constraint-fn-var 145) (e-lookup-local (p-assign (ident "duplicate"))) (e-list diff --git a/test/snapshots/issue/issue_9075.md b/test/snapshots/issue/issue_9075.md index 28ee8331cb4..7d1651c30e3 100644 --- a/test/snapshots/issue/issue_9075.md +++ b/test/snapshots/issue/issue_9075.md @@ -127,7 +127,7 @@ main = "${y}" (p-assign (ident "thing")) (p-assign (ident "f"))) (e-block - (e-call (constraint-fn-var 55) + (e-call (constraint-fn-var 53) (e-lookup-local (p-assign (ident "f"))) (e-lookup-local @@ -142,7 +142,7 @@ main = "${y}" (ty-rigid-var-lookup (ty-rigid-var (name "b")))))) (d-let (p-assign (ident "y")) - (e-call (constraint-fn-var 122) + (e-call (constraint-fn-var 120) (e-lookup-local (p-assign (ident "call"))) (e-num (value "5")) @@ -150,7 +150,7 @@ main = "${y}" (args (p-assign (ident "i"))) (e-block - (e-dispatch-call (method "plus") (constraint-fn-var 120) + (e-dispatch-call (method "plus") (constraint-fn-var 118) (receiver (e-runtime-error (tag "erroneous_value_use"))) (args @@ -161,23 +161,12 @@ main = "${y}" (s-let (p-assign (ident "#interp_0")) (e-runtime-error (tag "erroneous_value_use"))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 248) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 206) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 142) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-runtime-error (tag "erroneous_value_use")) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 127) + (first + (e-literal (string ""))) + (parts + (e-runtime-error (tag "erroneous_value_use")) + (e-literal (string ""))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/issue/method_call_inspect_defined.md b/test/snapshots/issue/method_call_inspect_defined.md index 5b83a37d901..56a7705fea5 100644 --- a/test/snapshots/issue/method_call_inspect_defined.md +++ b/test/snapshots/issue/method_call_inspect_defined.md @@ -56,7 +56,7 @@ EndOfFile, (e-literal (string "hello")))) (s-expr (e-runtime-error (tag "expr_not_canonicalized"))) - (e-dispatch-call (method "inspect") (constraint-fn-var 33) + (e-dispatch-call (method "inspect") (constraint-fn-var 30) (receiver (e-lookup-local (p-assign (ident "x")))) diff --git a/test/snapshots/issue/try_match_type_bug.md b/test/snapshots/issue/try_match_type_bug.md index a406869d132..25394db8053 100644 --- a/test/snapshots/issue/try_match_type_bug.md +++ b/test/snapshots/issue/try_match_type_bug.md @@ -103,7 +103,7 @@ get_greeting = |{}| { (e-match (match (cond - (e-call (constraint-fn-var 182) + (e-call (constraint-fn-var 179) (e-lookup-external (builtin)) (e-list diff --git a/test/snapshots/issue/underscore_error_type.md b/test/snapshots/issue/underscore_error_type.md index f966d743ff2..cef910fab15 100644 --- a/test/snapshots/issue/underscore_error_type.md +++ b/test/snapshots/issue/underscore_error_type.md @@ -176,7 +176,7 @@ It has the type: (a, b) where [ - a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), + a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), b.from_numeral : Numeral -> Try(b, [InvalidNumeral(Str)]), ] diff --git a/test/snapshots/lambda_multi_arg_mismatch.md b/test/snapshots/lambda_multi_arg_mismatch.md index aa0db1dcb1e..d571bad4937 100644 --- a/test/snapshots/lambda_multi_arg_mismatch.md +++ b/test/snapshots/lambda_multi_arg_mismatch.md @@ -229,7 +229,7 @@ result = multi_arg_fn( (ty-rigid-var-lookup (ty-rigid-var (name "e"))))))) (d-let (p-assign (ident "result")) - (e-call (constraint-fn-var 275) + (e-call (constraint-fn-var 266) (e-lookup-local (p-assign (ident "multi_arg_fn"))) (e-num (value "42")) diff --git a/test/snapshots/lambda_return_lookup_type.md b/test/snapshots/lambda_return_lookup_type.md index 61987556ae3..10d15dc7e9b 100644 --- a/test/snapshots/lambda_return_lookup_type.md +++ b/test/snapshots/lambda_return_lookup_type.md @@ -77,7 +77,7 @@ EndOfFile, (p-assign (ident "x"))))) (d-let (p-assign (ident "y")) - (e-call (constraint-fn-var 71) + (e-call (constraint-fn-var 68) (e-lookup-local (p-assign (ident "f"))) (e-num (value "0"))))) diff --git a/test/snapshots/let_polymorphism_complex.md b/test/snapshots/let_polymorphism_complex.md index 36282d1813b..dd4eba2eec1 100644 --- a/test/snapshots/let_polymorphism_complex.md +++ b/test/snapshots/let_polymorphism_complex.md @@ -851,21 +851,21 @@ main = |_| { (p-assign (ident "val")))))))))) (d-let (p-assign (ident "container1")) - (e-call (constraint-fn-var 1147) + (e-call (constraint-fn-var 1111) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local (p-assign (ident "num"))))) (d-let (p-assign (ident "container2")) - (e-call (constraint-fn-var 1152) + (e-call (constraint-fn-var 1116) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local (p-assign (ident "str"))))) (d-let (p-assign (ident "container3")) - (e-call (constraint-fn-var 1157) + (e-call (constraint-fn-var 1121) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local @@ -894,13 +894,13 @@ main = |_| { (elems (e-lookup-local (p-assign (ident "num"))) - (e-dispatch-call (method "times") (constraint-fn-var 1189) + (e-dispatch-call (method "times") (constraint-fn-var 1153) (receiver (e-lookup-local (p-assign (ident "num")))) (args (e-num (value "2")))) - (e-dispatch-call (method "times") (constraint-fn-var 1221) + (e-dispatch-call (method "times") (constraint-fn-var 1185) (receiver (e-lookup-local (p-assign (ident "num")))) @@ -944,7 +944,7 @@ main = |_| { (e-literal (string "more")))))))))))) (d-let (p-assign (ident "compute1")) - (e-dispatch-call (method "plus") (constraint-fn-var 1497) + (e-dispatch-call (method "plus") (constraint-fn-var 1452) (receiver (e-lookup-local (p-assign (ident "num")))) @@ -952,7 +952,7 @@ main = |_| { (e-num (value "10"))))) (d-let (p-assign (ident "compute2")) - (e-dispatch-call (method "times") (constraint-fn-var 1529) + (e-dispatch-call (method "times") (constraint-fn-var 1484) (receiver (e-lookup-local (p-assign (ident "num")))) @@ -978,13 +978,13 @@ main = |_| { (elems (e-lookup-local (p-assign (ident "num"))) - (e-dispatch-call (method "plus") (constraint-fn-var 1563) + (e-dispatch-call (method "plus") (constraint-fn-var 1518) (receiver (e-lookup-local (p-assign (ident "num")))) (args (e-num (value "1")))) - (e-dispatch-call (method "plus") (constraint-fn-var 1595) + (e-dispatch-call (method "plus") (constraint-fn-var 1550) (receiver (e-lookup-local (p-assign (ident "num")))) @@ -1044,14 +1044,14 @@ main = |_| { (e-record (fields (field (name "from_num") - (e-dispatch-call (method "times") (constraint-fn-var 1640) + (e-dispatch-call (method "times") (constraint-fn-var 1595) (receiver (e-lookup-local (p-assign (ident "num")))) (args (e-num (value "100"))))) (field (name "from_frac") - (e-dispatch-call (method "times") (constraint-fn-var 1672) + (e-dispatch-call (method "times") (constraint-fn-var 1627) (receiver (e-lookup-local (p-assign (ident "frac")))) @@ -1072,7 +1072,7 @@ main = |_| { (args (p-underscore)) (e-block - (e-dispatch-call (method "plus") (constraint-fn-var 1712) + (e-dispatch-call (method "plus") (constraint-fn-var 1667) (receiver (e-field-access (field "value") (receiver diff --git a/test/snapshots/let_polymorphism_lists.md b/test/snapshots/let_polymorphism_lists.md index 916523a6fb5..b31d1f2c2ec 100644 --- a/test/snapshots/let_polymorphism_lists.md +++ b/test/snapshots/let_polymorphism_lists.md @@ -349,13 +349,13 @@ main = |_| { (e-empty_list))) (d-let (p-assign (ident "empty_int_list")) - (e-call (constraint-fn-var 342) + (e-call (constraint-fn-var 336) (e-lookup-local (p-assign (ident "get_empty"))) (e-num (value "42")))) (d-let (p-assign (ident "empty_str_list")) - (e-call (constraint-fn-var 363) + (e-call (constraint-fn-var 354) (e-lookup-local (p-assign (ident "get_empty"))) (e-string @@ -387,9 +387,9 @@ main = |_| { (builtin)) (e-lookup-local (p-assign (ident "all_float_list"))))) - (e-dispatch-call (method "plus") (constraint-fn-var 398) + (e-dispatch-call (method "plus") (constraint-fn-var 389) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 396) + (e-dispatch-call (method "plus") (constraint-fn-var 387) (receiver (e-lookup-local (p-assign (ident "len1")))) diff --git a/test/snapshots/let_polymorphism_records.md b/test/snapshots/let_polymorphism_records.md index 8e172ecbb95..8875abc759d 100644 --- a/test/snapshots/let_polymorphism_records.md +++ b/test/snapshots/let_polymorphism_records.md @@ -289,21 +289,21 @@ NO CHANGE (e-num (value "1"))))))) (d-let (p-assign (ident "int_container")) - (e-call (constraint-fn-var 235) + (e-call (constraint-fn-var 232) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local (p-assign (ident "num"))))) (d-let (p-assign (ident "str_container")) - (e-call (constraint-fn-var 243) + (e-call (constraint-fn-var 240) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local (p-assign (ident "str"))))) (d-let (p-assign (ident "list_container")) - (e-call (constraint-fn-var 251) + (e-call (constraint-fn-var 248) (e-lookup-local (p-assign (ident "make_container"))) (e-lookup-local @@ -324,7 +324,7 @@ NO CHANGE (p-assign (ident "new_value")))))))) (d-let (p-assign (ident "updated_int")) - (e-call (constraint-fn-var 288) + (e-call (constraint-fn-var 285) (e-lookup-local (p-assign (ident "update_data"))) (e-lookup-local @@ -332,7 +332,7 @@ NO CHANGE (e-num (value "100")))) (d-let (p-assign (ident "updated_str")) - (e-call (constraint-fn-var 310) + (e-call (constraint-fn-var 304) (e-lookup-local (p-assign (ident "update_data"))) (e-lookup-local @@ -341,7 +341,7 @@ NO CHANGE (e-literal (string "world"))))) (d-let (p-assign (ident "updated_mismatch")) - (e-call (constraint-fn-var 346) + (e-call (constraint-fn-var 340) (e-lookup-local (p-assign (ident "update_data"))) (e-lookup-local @@ -359,20 +359,20 @@ NO CHANGE (p-assign (ident "x")))))))) (d-let (p-assign (ident "int_record")) - (e-call (constraint-fn-var 381) + (e-call (constraint-fn-var 375) (e-lookup-local (p-assign (ident "identity_record"))) (e-num (value "42")))) (d-let (p-assign (ident "str_record")) - (e-call (constraint-fn-var 401) + (e-call (constraint-fn-var 392) (e-lookup-local (p-assign (ident "identity_record"))) (e-string (e-literal (string "test"))))) (d-let (p-assign (ident "list_record")) - (e-call (constraint-fn-var 497) + (e-call (constraint-fn-var 488) (e-lookup-local (p-assign (ident "identity_record"))) (e-list @@ -388,7 +388,7 @@ NO CHANGE (e-block (s-expr (e-runtime-error (tag "erroneous_value_expr"))) - (e-dispatch-call (method "plus") (constraint-fn-var 543) + (e-dispatch-call (method "plus") (constraint-fn-var 534) (receiver (e-field-access (field "count") (receiver diff --git a/test/snapshots/match_expr/complex_list_tags.md b/test/snapshots/match_expr/complex_list_tags.md index 9a33d66553e..b2fc883c996 100644 --- a/test/snapshots/match_expr/complex_list_tags.md +++ b/test/snapshots/match_expr/complex_list_tags.md @@ -169,33 +169,16 @@ match events { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "y"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 401) - (receiver - (e-string - (e-literal (string "single click at (")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 359) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 301) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 237) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ")")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ", ")))))))))))) + (e-interpolation + (first + (e-literal (string "single click at ("))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string ")"))))))) (branch (patterns (pattern (degenerate false) @@ -219,33 +202,16 @@ match events { (builtin)) (e-lookup-local (p-assign (ident "rest")))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 605) - (receiver - (e-string - (e-literal (string "key ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 563) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 505) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 441) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " more events")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string " pressed, ")))))))))))) + (e-interpolation + (first + (e-literal (string "key "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string " pressed, ")) + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " more events"))))))) (branch (patterns (pattern (degenerate false) @@ -281,51 +247,22 @@ match events { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "dy2"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 910) - (receiver - (e-string - (e-literal (string "moved ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 868) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 810) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 752) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 694) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 630) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_7"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_6"))) - (e-string - (e-literal (string ",")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_5"))) - (e-string - (e-literal (string " then ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_4"))) - (e-string - (e-literal (string ",")))))))))))) + (e-interpolation + (first + (e-literal (string "moved "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_4"))) + (e-literal (string ",")) + (e-lookup-local + (p-assign (ident "#interp_5"))) + (e-literal (string " then ")) + (e-lookup-local + (p-assign (ident "#interp_6"))) + (e-literal (string ",")) + (e-lookup-local + (p-assign (ident "#interp_7"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -355,42 +292,19 @@ match events { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "y"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1160) - (receiver - (e-string - (e-literal (string "scroll ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1118) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1060) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1002) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 938) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_10"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_9"))) - (e-string - (e-literal (string ",")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_8"))) - (e-string - (e-literal (string " then click at ")))))))))))) + (e-interpolation + (first + (e-literal (string "scroll "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_8"))) + (e-literal (string " then click at ")) + (e-lookup-local + (p-assign (ident "#interp_9"))) + (e-literal (string ",")) + (e-lookup-local + (p-assign (ident "#interp_10"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -401,5 +315,5 @@ match events { ~~~ # TYPES ~~~clojure -(expr (type "Str")) +(expr (type "Error")) ~~~ diff --git a/test/snapshots/match_expr/guards_1.md b/test/snapshots/match_expr/guards_1.md index c310c4388d9..96717ea4752 100644 --- a/test/snapshots/match_expr/guards_1.md +++ b/test/snapshots/match_expr/guards_1.md @@ -105,31 +105,20 @@ describe = |value| match value { (e-block (s-let (p-assign (ident "#interp_0")) - (e-dispatch-call (method "to_str") (constraint-fn-var 204) + (e-dispatch-call (method "to_str") (constraint-fn-var 200) (receiver (e-lookup-local (p-assign (ident "x")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 345) - (receiver - (e-string - (e-literal (string "positive: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 303) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 239) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 222) + (first + (e-literal (string "positive: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (guard - (e-dispatch-call (method "is_gt") (constraint-fn-var 113) + (e-dispatch-call (method "is_gt") (constraint-fn-var 109) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -143,31 +132,20 @@ describe = |value| match value { (e-block (s-let (p-assign (ident "#interp_1")) - (e-dispatch-call (method "to_str") (constraint-fn-var 469) + (e-dispatch-call (method "to_str") (constraint-fn-var 346) (receiver (e-lookup-local (p-assign (ident "x")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 610) - (receiver - (e-string - (e-literal (string "negative: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 568) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 504) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 368) + (first + (e-literal (string "negative: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) (guard - (e-dispatch-call (method "is_lt") (constraint-fn-var 380) + (e-dispatch-call (method "is_lt") (constraint-fn-var 257) (receiver (e-lookup-local (p-assign (ident "x")))) diff --git a/test/snapshots/match_expr/guards_2.md b/test/snapshots/match_expr/guards_2.md index 8aa7f53b3e4..2e81147824a 100644 --- a/test/snapshots/match_expr/guards_2.md +++ b/test/snapshots/match_expr/guards_2.md @@ -117,33 +117,22 @@ describe = |value| match value { (e-block (s-let (p-assign (ident "#interp_0")) - (e-dispatch-call (method "to_str") (constraint-fn-var 234) + (e-dispatch-call (method "to_str") (constraint-fn-var 230) (receiver (e-lookup-local (p-assign (ident "first")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 375) - (receiver - (e-string - (e-literal (string "long list starting with ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 333) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 269) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 252) + (first + (e-literal (string "long list starting with "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (guard - (e-dispatch-call (method "is_gt") (constraint-fn-var 145) + (e-dispatch-call (method "is_gt") (constraint-fn-var 141) (receiver - (e-call (constraint-fn-var 111) + (e-call (constraint-fn-var 107) (e-lookup-external (builtin)) (e-lookup-local @@ -161,29 +150,18 @@ describe = |value| match value { (e-block (s-let (p-assign (ident "#interp_1")) - (e-dispatch-call (method "to_str") (constraint-fn-var 401) + (e-dispatch-call (method "to_str") (constraint-fn-var 278) (receiver (e-lookup-local (p-assign (ident "x")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 542) - (receiver - (e-string - (e-literal (string "pair of equal values: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 500) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 436) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 300) + (first + (e-literal (string "pair of equal values: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) (guard (e-method-eq (negated "false") (lhs diff --git a/test/snapshots/match_expr/nested_record_patterns.md b/test/snapshots/match_expr/nested_record_patterns.md index 1380e666b17..fe64d28a15f 100644 --- a/test/snapshots/match_expr/nested_record_patterns.md +++ b/test/snapshots/match_expr/nested_record_patterns.md @@ -140,42 +140,19 @@ match ... { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "country")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 381) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 339) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 281) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 223) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 159) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ", ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " lives in ")))))))))))) + (e-interpolation (constraint-fn-var 140) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " lives in ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -206,7 +183,7 @@ match ... { (p-assign (ident "name")))) (s-let (p-assign (ident "#interp_4")) - (e-dispatch-call (method "to_str") (constraint-fn-var 383) + (e-dispatch-call (method "to_str") (constraint-fn-var 142) (receiver (e-lookup-local (p-assign (ident "age")))) @@ -215,42 +192,19 @@ match ... { (p-assign (ident "#interp_5")) (e-lookup-local (p-assign (ident "city")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 626) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 584) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 526) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 468) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 404) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_5"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_4"))) - (e-string - (e-literal (string ") from ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " (")))))))))))) + (e-interpolation (constraint-fn-var 156) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " (")) + (e-lookup-local + (p-assign (ident "#interp_4"))) + (e-literal (string ") from ")) + (e-lookup-local + (p-assign (ident "#interp_5"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -273,24 +227,13 @@ match ... { (p-assign (ident "#interp_6")) (e-lookup-local (p-assign (ident "value")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 753) - (receiver - (e-string - (e-literal (string "Deep nested: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 711) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 647) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_6"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 164) + (first + (e-literal (string "Deep nested: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_6"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -305,24 +248,13 @@ match ... { (p-assign (ident "#interp_7")) (e-lookup-local (p-assign (ident "simple")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 880) - (receiver - (e-string - (e-literal (string "Simple: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 838) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 774) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_7"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 172) + (first + (e-literal (string "Simple: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_7"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) diff --git a/test/snapshots/match_expr/record_destructure.md b/test/snapshots/match_expr/record_destructure.md index 29803c7fa57..9d7b60b584f 100644 --- a/test/snapshots/match_expr/record_destructure.md +++ b/test/snapshots/match_expr/record_destructure.md @@ -93,38 +93,21 @@ match ... { (p-assign (ident "name")))) (s-let (p-assign (ident "#interp_1")) - (e-dispatch-call (method "to_str") (constraint-fn-var 74) + (e-dispatch-call (method "to_str") (constraint-fn-var 68) (receiver (e-lookup-local (p-assign (ident "age")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 259) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 217) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 159) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 95) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " years old")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " is ")))))))))))) + (e-interpolation (constraint-fn-var 79) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " is ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " years old"))))))) (branch (patterns (pattern (degenerate false) @@ -150,33 +133,16 @@ match ... { (p-assign (ident "#interp_3")) (e-lookup-local (p-assign (ident "name")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 444) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 402) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 344) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 280) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string " is the city of ")))))))))))) + (e-interpolation (constraint-fn-var 90) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string " is the city of ")) + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) diff --git a/test/snapshots/match_expr/record_pattern_edge_cases.md b/test/snapshots/match_expr/record_pattern_edge_cases.md index 717a3f3e88c..840ea002b9c 100644 --- a/test/snapshots/match_expr/record_pattern_edge_cases.md +++ b/test/snapshots/match_expr/record_pattern_edge_cases.md @@ -154,24 +154,13 @@ match ... { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "c")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 297) - (receiver - (e-string - (e-literal (string "deeply nested: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 255) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 191) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 163) + (first + (e-literal (string "deeply nested: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -190,24 +179,13 @@ match ... { (p-assign (ident "#interp_1")) (e-lookup-local (p-assign (ident "x")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 424) - (receiver - (e-string - (e-literal (string "mixed with empty: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 382) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 318) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 171) + (first + (e-literal (string "mixed with empty: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -233,33 +211,16 @@ match ... { (p-assign (ident "#interp_3")) (e-lookup-local (p-assign (ident "simple")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 609) - (receiver - (e-string - (e-literal (string "mixed: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 567) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 509) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 445) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string " and ")))))))))))) + (e-interpolation (constraint-fn-var 182) + (first + (e-literal (string "mixed: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string " and ")) + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -289,33 +250,16 @@ match ... { (p-assign (ident "#interp_5")) (e-lookup-local (p-assign (ident "d")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 794) - (receiver - (e-string - (e-literal (string "multiple nested: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 752) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 694) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 630) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_5"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_4"))) - (e-string - (e-literal (string ", ")))))))))))) + (e-interpolation (constraint-fn-var 193) + (first + (e-literal (string "multiple nested: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_4"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_5"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -330,24 +274,13 @@ match ... { (p-assign (ident "#interp_6")) (e-lookup-local (p-assign (ident "x")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 921) - (receiver - (e-string - (e-literal (string "renamed: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 879) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 815) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_6"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 201) + (first + (e-literal (string "renamed: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_6"))) + (e-literal (string ""))))))) (branch (patterns (pattern (degenerate false) @@ -371,38 +304,21 @@ match ... { (p-assign (ident "firstName")))) (s-let (p-assign (ident "#interp_8")) - (e-dispatch-call (method "to_str") (constraint-fn-var 923) + (e-dispatch-call (method "to_str") (constraint-fn-var 203) (receiver (e-lookup-local (p-assign (ident "userAge")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1108) - (receiver - (e-string - (e-literal (string "renamed nested: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1066) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1008) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 944) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_8"))) - (e-string - (e-literal (string ")")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_7"))) - (e-string - (e-literal (string " (")))))))))))) + (e-interpolation (constraint-fn-var 214) + (first + (e-literal (string "renamed nested: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_7"))) + (e-literal (string " (")) + (e-lookup-local + (p-assign (ident "#interp_8"))) + (e-literal (string ")"))))))) (branch (patterns (pattern (degenerate false) diff --git a/test/snapshots/multiline_string_complex.md b/test/snapshots/multiline_string_complex.md index 1511600c947..ac5b859a6a2 100644 --- a/test/snapshots/multiline_string_complex.md +++ b/test/snapshots/multiline_string_complex.md @@ -285,26 +285,15 @@ x = { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "value1")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 231) - (receiver - (e-string - (e-literal (string "This is a string + (e-interpolation (constraint-fn-var 102) + (first + (e-literal (string "This is a string With multiple lines -")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 189) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 125) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) +"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (d-let (p-assign (ident "value4")) (e-block @@ -312,26 +301,15 @@ With multiple lines (p-assign (ident "#interp_1")) (e-lookup-local (p-assign (ident "value2")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 358) - (receiver - (e-string - (e-literal (string "This is a string + (e-interpolation (constraint-fn-var 110) + (first + (e-literal (string "This is a string With multiple lines -")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 316) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 252) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ""))))))))))) +"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) (d-let (p-assign (ident "value5")) (e-record @@ -352,13 +330,13 @@ With multiple lines (e-string (e-literal (string "multiline")))))) (field (name "d") - (e-dispatch-call (method "minus") (constraint-fn-var 469) + (e-dispatch-call (method "minus") (constraint-fn-var 206) (receiver (e-num (value "0"))) (args (e-string)))) (field (name "e") - (e-dispatch-call (method "not") (constraint-fn-var 484) + (e-dispatch-call (method "not") (constraint-fn-var 218) (receiver (e-string)) (args)))))) diff --git a/test/snapshots/nested_try_interpolation_recursive_dispatch.md b/test/snapshots/nested_try_interpolation_recursive_dispatch.md new file mode 100644 index 00000000000..fca3fcd1c0c --- /dev/null +++ b/test/snapshots/nested_try_interpolation_recursive_dispatch.md @@ -0,0 +1,243 @@ +# META +~~~ini +description=Nested Try interpolation reports recursive dispatch +type=snippet +~~~ +# SOURCE +~~~roc +Url := [Url(Str)].{ + from_interpolation : Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl]) + from_interpolation = |first, rest| Ok(Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment)))) +} + +main = { + domain = "example" + url : Try(Try(Url, [InvalidUrl]), [Outer]) + url = "https://${domain}.com" + url +} +~~~ +# EXPECTED +RECURSIVE DISPATCH - nested_try_interpolation_recursive_dispatch.md:9:11:9:34 +# PROBLEMS +**RECURSIVE DISPATCH** +This **from_interpolation** dispatch would have to call itself to satisfy its own type: +**nested_try_interpolation_recursive_dispatch.md:9:11:9:34:** +```roc + url = "https://${domain}.com" +``` + ^^^^^^^^^^^^^^^^^^^^^^^ + +The dispatcher type is: + + Try(Url, [InvalidUrl]) + +**Hint:** Use a more specific result type, or add an associated function whose **from_interpolation** implementation does not require the same dispatch on the same type. + +# TOKENS +~~~zig +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,CloseSquare,Dot,OpenCurly, +LowerIdent,OpColon,UpperIdent,Comma,UpperIdent,NoSpaceOpenRound,NoSpaceOpenRound,UpperIdent,Comma,UpperIdent,CloseRound,CloseRound,OpArrow,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,OpenSquare,UpperIdent,CloseSquare,CloseRound, +LowerIdent,OpAssign,OpBar,LowerIdent,Comma,LowerIdent,OpBar,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceDotUpperIdent,NoSpaceOpenRound,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,LowerIdent,Comma,OpBar,LowerIdent,Comma,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpBar,LowerIdent,NoSpaceDotLowerIdent,NoSpaceOpenRound,LowerIdent,CloseRound,NoSpaceDotLowerIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseRound,CloseRound,CloseRound, +CloseCurly, +LowerIdent,OpAssign,OpenCurly, +LowerIdent,OpAssign,StringStart,StringPart,StringEnd, +LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,OpenSquare,UpperIdent,CloseSquare,CloseRound,Comma,OpenSquare,UpperIdent,CloseSquare,CloseRound, +LowerIdent,OpAssign,StringStart,StringPart,OpenStringInterpolation,LowerIdent,CloseStringInterpolation,StringPart,StringEnd, +LowerIdent, +CloseCurly, +EndOfFile, +~~~ +# PARSE +~~~clojure +(file + (type-module) + (statements + (s-type-decl + (header (name "Url") + (args)) + (ty-tag-union + (tags + (ty-apply + (ty (name "Url")) + (ty (name "Str"))))) + (associated + (s-type-anno (name "from_interpolation") + (ty-fn + (ty (name "Str")) + (ty-apply + (ty (name "Iter")) + (ty-tuple + (ty (name "Str")) + (ty (name "Str")))) + (ty-apply + (ty (name "Try")) + (ty (name "Url")) + (ty-tag-union + (tags + (ty (name "InvalidUrl"))))))) + (s-decl + (p-ident (raw "from_interpolation")) + (e-lambda + (args + (p-ident (raw "first")) + (p-ident (raw "rest"))) + (e-apply + (e-tag (raw "Ok")) + (e-apply + (e-tag (raw "Url.Url")) + (e-method-call (method ".fold") + (receiver + (e-ident (raw "rest"))) + (args + (e-ident (raw "first")) + (e-lambda + (args + (p-ident (raw "acc")) + (p-tuple + (p-ident (raw "interpolated")) + (p-ident (raw "segment")))) + (e-method-call (method ".concat") + (receiver + (e-method-call (method ".concat") + (receiver + (e-ident (raw "acc"))) + (args + (e-ident (raw "interpolated"))))) + (args + (e-ident (raw "segment"))))))))))))) + (s-decl + (p-ident (raw "main")) + (e-block + (statements + (s-decl + (p-ident (raw "domain")) + (e-string + (e-string-part (raw "example")))) + (s-type-anno (name "url") + (ty-apply + (ty (name "Try")) + (ty-apply + (ty (name "Try")) + (ty (name "Url")) + (ty-tag-union + (tags + (ty (name "InvalidUrl"))))) + (ty-tag-union + (tags + (ty (name "Outer")))))) + (s-decl + (p-ident (raw "url")) + (e-string + (e-string-part (raw "https://")) + (e-ident (raw "domain")) + (e-string-part (raw ".com")))) + (e-ident (raw "url"))))))) +~~~ +# FORMATTED +~~~roc +Url := [Url(Str)].{ + from_interpolation : Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl]) + from_interpolation = |first, rest| Ok(Url.Url(rest.fold(first, |acc, (interpolated, segment)| acc.concat(interpolated).concat(segment)))) +} + +main = { + domain = "example" + url : Try(Try(Url, [InvalidUrl]), [Outer]) + url = "https://${domain}.com" + url +} +~~~ +# CANONICALIZE +~~~clojure +(can-ir + (d-let + (p-assign (ident "nested_try_interpolation_recursive_dispatch.Url.from_interpolation")) + (e-lambda + (args + (p-assign (ident "first")) + (p-assign (ident "rest"))) + (e-tag (name "Ok") + (args + (e-nominal (nominal "Url") + (e-tag (name "Url") + (args + (e-dispatch-call (method "fold") (constraint-fn-var 187) + (receiver + (e-lookup-local + (p-assign (ident "rest")))) + (args + (e-lookup-local + (p-assign (ident "first"))) + (e-lambda + (args + (p-assign (ident "acc")) + (p-tuple + (patterns + (p-assign (ident "interpolated")) + (p-assign (ident "segment"))))) + (e-dispatch-call (method "concat") (constraint-fn-var 185) + (receiver + (e-dispatch-call (method "concat") (constraint-fn-var 183) + (receiver + (e-lookup-local + (p-assign (ident "acc")))) + (args + (e-lookup-local + (p-assign (ident "interpolated")))))) + (args + (e-lookup-local + (p-assign (ident "segment")))))))))))))) + (annotation + (ty-fn (effectful false) + (ty-lookup (name "Str") (builtin)) + (ty-apply (name "Iter") (builtin) + (ty-tuple + (ty-lookup (name "Str") (builtin)) + (ty-lookup (name "Str") (builtin)))) + (ty-apply (name "Try") (builtin) + (ty-lookup (name "Url") (local)) + (ty-tag-union + (ty-tag-name (name "InvalidUrl"))))))) + (d-let + (p-assign (ident "main")) + (e-block + (s-let + (p-assign (ident "domain")) + (e-string + (e-literal (string "example")))) + (s-let + (p-assign (ident "url")) + (e-block + (s-let + (p-assign (ident "#interp_0")) + (e-lookup-local + (p-assign (ident "domain")))) + (e-interpolation (constraint-fn-var 349) + (first + (e-literal (string "https://"))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ".com")))))) + (e-lookup-local + (p-assign (ident "url"))))) + (s-nominal-decl + (ty-header (name "Url")) + (ty-tag-union + (ty-tag-name (name "Url") + (ty-lookup (name "Str") (builtin)))))) +~~~ +# TYPES +~~~clojure +(inferred-types + (defs + (patt (type "Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl])")) + (patt (type "Try(Try(Url, [InvalidUrl]), [Outer])"))) + (type_decls + (nominal (type "Url") + (ty-header (name "Url")))) + (expressions + (expr (type "Str, Iter((Str, Str)) -> Try(Url, [InvalidUrl])")) + (expr (type "Try(Try(Url, [InvalidUrl]), [Outer])")))) +~~~ diff --git a/test/snapshots/nominal_type_origin_mismatch.md b/test/snapshots/nominal_type_origin_mismatch.md index 783fb3e5fa2..98e7151a880 100644 --- a/test/snapshots/nominal_type_origin_mismatch.md +++ b/test/snapshots/nominal_type_origin_mismatch.md @@ -103,7 +103,7 @@ main = (ty-lookup (name "Str") (builtin))))) (d-let (p-assign (ident "main")) - (e-call (constraint-fn-var 108) + (e-call (constraint-fn-var 90) (e-lookup-local (p-assign (ident "expectsPerson"))) (e-string diff --git a/test/snapshots/plume_package/Color.md b/test/snapshots/plume_package/Color.md index b45224e9127..eb2b759784f 100644 --- a/test/snapshots/plume_package/Color.md +++ b/test/snapshots/plume_package/Color.md @@ -810,9 +810,9 @@ is_named_color = |str| { (e-block (s-let (p-assign (ident "rounded")) - (e-dispatch-call (method "div_by") (constraint-fn-var 679) + (e-dispatch-call (method "div_by") (constraint-fn-var 664) (receiver - (e-dispatch-call (method "to_frac") (constraint-fn-var 646) + (e-dispatch-call (method "to_frac") (constraint-fn-var 631) (receiver (e-lookup-local (p-assign (ident "a")))) @@ -845,7 +845,7 @@ is_named_color = |str| { (e-block (s-let (p-assign (ident "bytes")) - (e-dispatch-call (method "to_utf8") (constraint-fn-var 801) + (e-dispatch-call (method "to_utf8") (constraint-fn-var 786) (receiver (e-lookup-local (p-assign (ident "str")))) @@ -861,13 +861,13 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gte") (constraint-fn-var 856) + (e-dispatch-call (method "is_gte") (constraint-fn-var 841) (receiver (e-lookup-local (p-assign (ident "b")))) (args (e-num (value "48")))) - (e-dispatch-call (method "is_lte") (constraint-fn-var 894) + (e-dispatch-call (method "is_lte") (constraint-fn-var 879) (receiver (e-lookup-local (p-assign (ident "b")))) @@ -887,13 +887,13 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gte") (constraint-fn-var 945) + (e-dispatch-call (method "is_gte") (constraint-fn-var 930) (receiver (e-lookup-local (p-assign (ident "b")))) (args (e-num (value "97")))) - (e-dispatch-call (method "is_lte") (constraint-fn-var 983) + (e-dispatch-call (method "is_lte") (constraint-fn-var 968) (receiver (e-lookup-local (p-assign (ident "b")))) @@ -910,13 +910,13 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gte") (constraint-fn-var 1031) + (e-dispatch-call (method "is_gte") (constraint-fn-var 1016) (receiver (e-lookup-local (p-assign (ident "b")))) (args (e-num (value "65")))) - (e-dispatch-call (method "is_lte") (constraint-fn-var 1069) + (e-dispatch-call (method "is_lte") (constraint-fn-var 1054) (receiver (e-lookup-local (p-assign (ident "b")))) @@ -951,7 +951,7 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1198) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1183) (receiver (e-lookup-local (p-assign (ident "a")))) @@ -959,7 +959,7 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1204) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1189) (receiver (e-lookup-local (p-assign (ident "b")))) @@ -967,7 +967,7 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1210) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1195) (receiver (e-lookup-local (p-assign (ident "c")))) @@ -975,7 +975,7 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1216) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1201) (receiver (e-lookup-local (p-assign (ident "d")))) @@ -983,12 +983,12 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1222) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1207) (receiver (e-lookup-local (p-assign (ident "e")))) (args)) - (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1228) + (e-dispatch-call (method "is_char_in_hex_range") (constraint-fn-var 1213) (receiver (e-lookup-local (p-assign (ident "f")))) @@ -1035,24 +1035,13 @@ is_named_color = |str| { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "str")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1418) - (receiver - (e-string - (e-literal (string "Expected Hex to be in the range 0-9, a-f, A-F, got ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1376) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1312) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))))))))))) + (e-interpolation (constraint-fn-var 1284) + (first + (e-literal (string "Expected Hex to be in the range 0-9, a-f, A-F, got "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))))))))))) (branch (patterns (pattern (degenerate false) @@ -1067,24 +1056,13 @@ is_named_color = |str| { (p-assign (ident "#interp_1")) (e-lookup-local (p-assign (ident "str")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 1672) - (receiver - (e-string - (e-literal (string "Expected Hex must start with # and be 7 characters long, got ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 1630) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1566) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string ""))))))))))))))))))))) + (e-interpolation (constraint-fn-var 1300) + (first + (e-literal (string "Expected Hex must start with # and be 7 characters long, got "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))))))))))))) (annotation (ty-fn (effectful false) (ty-lookup (name "Str") (builtin)) @@ -1129,42 +1107,19 @@ is_named_color = |str| { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "b"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2141) - (receiver - (e-string - (e-literal (string "rgb(")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2099) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2041) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 1983) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 1919) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_4"))) - (e-string - (e-literal (string ")")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string ", ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string ", ")))))))))))) + (e-interpolation + (first + (e-literal (string "rgb("))) + (parts + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_4"))) + (e-literal (string ")"))))))) (branch (patterns (pattern (degenerate false) @@ -1196,51 +1151,22 @@ is_named_color = |str| { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "a"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2474) - (receiver - (e-string - (e-literal (string "rgba(")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2432) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2374) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2316) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2258) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2194) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_8"))) - (e-string - (e-literal (string ")")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_7"))) - (e-string - (e-literal (string ", ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_6"))) - (e-string - (e-literal (string ", ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_5"))) - (e-string - (e-literal (string ", ")))))))))))) + (e-interpolation + (first + (e-literal (string "rgba("))) + (parts + (e-lookup-local + (p-assign (ident "#interp_5"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_6"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_7"))) + (e-literal (string ", ")) + (e-lookup-local + (p-assign (ident "#interp_8"))) + (e-literal (string ")"))))))) (branch (patterns (pattern (degenerate false) @@ -1269,7 +1195,7 @@ is_named_color = |str| { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_named_color") (constraint-fn-var 2710) + (e-dispatch-call (method "is_named_color") (constraint-fn-var 1616) (receiver (e-lookup-local (p-assign (ident "str")))) @@ -1291,24 +1217,13 @@ is_named_color = |str| { (p-assign (ident "#interp_9")) (e-lookup-local (p-assign (ident "str")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2874) - (receiver - (e-string - (e-literal (string "Unknown color ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2832) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2768) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_9"))) - (e-string - (e-literal (string ""))))))))))))))))) + (e-interpolation (constraint-fn-var 1661) + (first + (e-literal (string "Unknown color "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_9"))) + (e-literal (string "")))))))))))) (annotation (ty-fn (effectful false) (ty-lookup (name "Str") (builtin)) @@ -1325,7 +1240,7 @@ is_named_color = |str| { (e-block (s-let (p-assign (ident "colors")) - (e-call (constraint-fn-var 3083) + (e-call (constraint-fn-var 1742) (e-lookup-external (builtin)) (e-list @@ -1336,7 +1251,7 @@ is_named_color = |str| { (e-literal (string "AntiqueWhite"))) (e-string (e-literal (string "Aqua"))))))) - (e-dispatch-call (method "contains") (constraint-fn-var 3084) + (e-dispatch-call (method "contains") (constraint-fn-var 1743) (receiver (e-lookup-local (p-assign (ident "colors")))) @@ -1362,9 +1277,9 @@ is_named_color = |str| { (s-expect (e-method-eq (negated "false") (lhs - (e-dispatch-call (method "to_str") (constraint-fn-var 3417) + (e-dispatch-call (method "to_str") (constraint-fn-var 2076) (receiver - (e-call (constraint-fn-var 3206) + (e-call (constraint-fn-var 1865) (e-lookup-local (p-assign (ident "rgb"))) (e-num (value "124")) @@ -1377,9 +1292,9 @@ is_named_color = |str| { (s-expect (e-method-eq (negated "false") (lhs - (e-dispatch-call (method "to_str") (constraint-fn-var 3845) + (e-dispatch-call (method "to_str") (constraint-fn-var 2501) (receiver - (e-call (constraint-fn-var 3564) + (e-call (constraint-fn-var 2220) (e-lookup-local (p-assign (ident "rgba"))) (e-num (value "124")) @@ -1393,9 +1308,9 @@ is_named_color = |str| { (s-expect (e-method-eq (negated "false") (lhs - (e-dispatch-call (method "map_ok") (constraint-fn-var 3925) + (e-dispatch-call (method "map_ok") (constraint-fn-var 2563) (receiver - (e-call (constraint-fn-var 3888) + (e-call (constraint-fn-var 2538) (e-lookup-local (p-assign (ident "hex"))) (e-string @@ -1418,7 +1333,7 @@ is_named_color = |str| { (patt (type "Str -> Try(Color, [InvalidHex(Str)])")) (patt (type "Color -> Str")) (patt (type "Str -> Try(Color, [UnknownColor(Str)])")) - (patt (type "a -> Bool where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), a.is_eq : a, a -> Bool]"))) + (patt (type "a -> Bool where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), a.is_eq : a, a -> Bool]"))) (type_decls (nominal (type "Color") (ty-header (name "Color")))) @@ -1428,5 +1343,5 @@ is_named_color = |str| { (expr (type "Str -> Try(Color, [InvalidHex(Str)])")) (expr (type "Color -> Str")) (expr (type "Str -> Try(Color, [UnknownColor(Str)])")) - (expr (type "a -> Bool where [a.from_quote : List(U8) -> Try(a, [BadQuotedBytes(Str)]), a.is_eq : a, a -> Bool]")))) + (expr (type "a -> Bool where [a.from_quote : Str -> Try(a, [BadQuotedBytes(Str)]), a.is_eq : a, a -> Bool]")))) ~~~ diff --git a/test/snapshots/primitive/expr_string.md b/test/snapshots/primitive/expr_string.md index 85e6d8d11ce..13b198f9508 100644 --- a/test/snapshots/primitive/expr_string.md +++ b/test/snapshots/primitive/expr_string.md @@ -53,24 +53,13 @@ NO CHANGE (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "name")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 167) - (receiver - (e-string - (e-literal (string "hello ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 125) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 61) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 43) + (first + (e-literal (string "hello "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ""))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/pure_annotation_effectful_body_error.md b/test/snapshots/pure_annotation_effectful_body_error.md index 939aeb074a1..3f06da4ee12 100644 --- a/test/snapshots/pure_annotation_effectful_body_error.md +++ b/test/snapshots/pure_annotation_effectful_body_error.md @@ -95,7 +95,7 @@ NO CHANGE (ty-record)))) (d-let (p-assign (ident "main!")) - (e-call (constraint-fn-var 55) + (e-call (constraint-fn-var 52) (e-lookup-local (p-assign (ident "bad_function"))) (e-string diff --git a/test/snapshots/question_in_expect_err_type_unbound.md b/test/snapshots/question_in_expect_err_type_unbound.md index 32003593c4c..00973aa4cc7 100644 --- a/test/snapshots/question_in_expect_err_type_unbound.md +++ b/test/snapshots/question_in_expect_err_type_unbound.md @@ -124,7 +124,7 @@ expect parse("5")? == 5 (e-match (match (cond - (e-call (constraint-fn-var 285) + (e-call (constraint-fn-var 267) (e-lookup-local (p-assign (ident "parse"))) (e-string diff --git a/test/snapshots/question_in_expect_mixed_err_types.md b/test/snapshots/question_in_expect_mixed_err_types.md index 02f6717344d..0f79ad351e0 100644 --- a/test/snapshots/question_in_expect_mixed_err_types.md +++ b/test/snapshots/question_in_expect_mixed_err_types.md @@ -124,7 +124,7 @@ NO CHANGE (e-match (match (cond - (e-call (constraint-fn-var 351) + (e-call (constraint-fn-var 348) (e-lookup-local (p-assign (ident "parse_a"))) (e-string @@ -151,7 +151,7 @@ NO CHANGE (e-match (match (cond - (e-call (constraint-fn-var 428) + (e-call (constraint-fn-var 410) (e-lookup-local (p-assign (ident "parse_b"))) (e-string diff --git a/test/snapshots/records/function_record_parameter.md b/test/snapshots/records/function_record_parameter.md index 781d27e3d42..2d317371620 100644 --- a/test/snapshots/records/function_record_parameter.md +++ b/test/snapshots/records/function_record_parameter.md @@ -56,38 +56,21 @@ NO CHANGE (p-assign (ident "name")))) (s-let (p-assign (ident "#interp_1")) - (e-dispatch-call (method "to_str") (constraint-fn-var 35) + (e-dispatch-call (method "to_str") (constraint-fn-var 32) (receiver (e-lookup-local (p-assign (ident "age")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 220) - (receiver - (e-string - (e-literal (string "Hello ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 178) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 120) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 56) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " years old")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ", you are "))))))))))) + (e-interpolation (constraint-fn-var 43) + (first + (e-literal (string "Hello "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ", you are ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " years old")))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/records/function_record_parameter_capture.md b/test/snapshots/records/function_record_parameter_capture.md index 3e97804144a..9e6b888b9d6 100644 --- a/test/snapshots/records/function_record_parameter_capture.md +++ b/test/snapshots/records/function_record_parameter_capture.md @@ -66,24 +66,13 @@ NO CHANGE (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "name")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 163) - (receiver - (e-string - (e-literal (string "Hello ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 121) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 57) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 42) + (first + (e-literal (string "Hello "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (field (name "full_record") (e-lookup-local (p-as (as "person") @@ -99,7 +88,7 @@ NO CHANGE (rest-pattern (p-assign (ident "a"))))))))) (field (name "is_adult") - (e-dispatch-call (method "is_gte") (constraint-fn-var 198) + (e-dispatch-call (method "is_gte") (constraint-fn-var 77) (receiver (e-lookup-local (p-assign (ident "age")))) diff --git a/test/snapshots/records/function_record_parameter_rest.md b/test/snapshots/records/function_record_parameter_rest.md index 183fd835722..5dc181a1f2d 100644 --- a/test/snapshots/records/function_record_parameter_rest.md +++ b/test/snapshots/records/function_record_parameter_rest.md @@ -59,33 +59,16 @@ NO CHANGE (receiver (e-lookup-local (p-assign (ident "rest")))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 221) - (receiver - (e-string - (e-literal (string "Hello ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 179) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 121) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 57) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " "))))))))))) + (e-interpolation (constraint-fn-var 44) + (first + (e-literal (string "Hello "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string "")))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/records/pattern_destructure_nested.md b/test/snapshots/records/pattern_destructure_nested.md index 444295a26ee..2bf0a7f6088 100644 --- a/test/snapshots/records/pattern_destructure_nested.md +++ b/test/snapshots/records/pattern_destructure_nested.md @@ -114,42 +114,19 @@ match person { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "city")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 294) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 252) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 194) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 136) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 72) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " in ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " lives on "))))))))))))))) + (e-interpolation (constraint-fn-var 61) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " lives on ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " in ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string "")))))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/records/pattern_destructure_rename.md b/test/snapshots/records/pattern_destructure_rename.md index c075028a329..40e4e305b03 100644 --- a/test/snapshots/records/pattern_destructure_rename.md +++ b/test/snapshots/records/pattern_destructure_rename.md @@ -73,38 +73,21 @@ match person { (p-assign (ident "userName")))) (s-let (p-assign (ident "#interp_1")) - (e-dispatch-call (method "to_str") (constraint-fn-var 39) + (e-dispatch-call (method "to_str") (constraint-fn-var 36) (receiver (e-lookup-local (p-assign (ident "userAge")))) (args))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 224) - (receiver - (e-string - (e-literal (string "User ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 182) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 124) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 60) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " years old")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " is "))))))))))))))) + (e-interpolation (constraint-fn-var 47) + (first + (e-literal (string "User "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " is ")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " years old")))))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/records/pattern_function_parameter.md b/test/snapshots/records/pattern_function_parameter.md index f1ff78c5038..ad02a28b604 100644 --- a/test/snapshots/records/pattern_function_parameter.md +++ b/test/snapshots/records/pattern_function_parameter.md @@ -82,42 +82,19 @@ NO CHANGE (e-lookup-local (p-assign (ident "email")))) (args))) - (e-method-call (method "from_interpolation") - (receiver - (e-string - (e-literal (string "User: ")))) - (args - (e-method-call (method "prepended") - (receiver - (e-method-call (method "prepended") - (receiver - (e-method-call (method "prepended") - (receiver - (e-method-call (method "iter") - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " years old) - Contact: ")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " ("))))))))))))) + (e-interpolation + (first + (e-literal (string "User: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " (")) + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " years old) - Contact: ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string "")))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/records/polymorphism.md b/test/snapshots/records/polymorphism.md index ec0b326ed4f..604c92ae282 100644 --- a/test/snapshots/records/polymorphism.md +++ b/test/snapshots/records/polymorphism.md @@ -29,8 +29,8 @@ The value's type, which does not have a method named **to_str**, is: { pair1: { first: a, second: b }, pair2: { first: c, second: d }, pair3: { first: [True, ..], second: [False, ..] } } where [ a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)]), - b.from_quote : List(U8) -> Try(b, [BadQuotedBytes(Str)]), - c.from_quote : List(U8) -> Try(c, [BadQuotedBytes(Str)]), + b.from_quote : Str -> Try(b, [BadQuotedBytes(Str)]), + c.from_quote : Str -> Try(c, [BadQuotedBytes(Str)]), d.from_numeral : Numeral -> Try(d, [InvalidNumeral(Str)]), ] @@ -117,7 +117,7 @@ EndOfFile, (p-assign (ident "y")))))))) (s-let (p-assign (ident "pair1")) - (e-call (constraint-fn-var 96) + (e-call (constraint-fn-var 93) (e-lookup-local (p-assign (ident "make_pair"))) (e-num (value "1")) @@ -125,7 +125,7 @@ EndOfFile, (e-literal (string "a"))))) (s-let (p-assign (ident "pair2")) - (e-call (constraint-fn-var 147) + (e-call (constraint-fn-var 141) (e-lookup-local (p-assign (ident "make_pair"))) (e-string @@ -133,12 +133,12 @@ EndOfFile, (e-num (value "42")))) (s-let (p-assign (ident "pair3")) - (e-call (constraint-fn-var 154) + (e-call (constraint-fn-var 148) (e-lookup-local (p-assign (ident "make_pair"))) (e-tag (name "True")) (e-tag (name "False")))) - (e-dispatch-call (method "to_str") (constraint-fn-var 156) + (e-dispatch-call (method "to_str") (constraint-fn-var 150) (receiver (e-record (fields diff --git a/test/snapshots/records/record_different_fields_error.md b/test/snapshots/records/record_different_fields_error.md index e6ca4014aa5..a3888b1f81a 100644 --- a/test/snapshots/records/record_different_fields_error.md +++ b/test/snapshots/records/record_different_fields_error.md @@ -450,7 +450,7 @@ EndOfFile, (s-expr (e-runtime-error (tag "ident_not_in_scope"))) (s-expr - (e-dispatch-call (method "negate") (constraint-fn-var 131) + (e-dispatch-call (method "negate") (constraint-fn-var 128) (receiver (e-runtime-error (tag "ident_not_in_scope"))) (args))) diff --git a/test/snapshots/records/record_with_complex_types.md b/test/snapshots/records/record_with_complex_types.md index ba0eebd2bc8..f366e99eb74 100644 --- a/test/snapshots/records/record_with_complex_types.md +++ b/test/snapshots/records/record_with_complex_types.md @@ -198,7 +198,7 @@ EndOfFile, (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "plus") (constraint-fn-var 342) + (e-dispatch-call (method "plus") (constraint-fn-var 324) (receiver (e-lookup-local (p-assign (ident "x")))) diff --git a/test/snapshots/rigid_var_instantiation.md b/test/snapshots/rigid_var_instantiation.md index a43ad2c06a5..2ce0f812510 100644 --- a/test/snapshots/rigid_var_instantiation.md +++ b/test/snapshots/rigid_var_instantiation.md @@ -182,14 +182,14 @@ main! = |_| { (e-num (value "42")))) (s-let (p-assign (ident "str")) - (e-call (constraint-fn-var 97) + (e-call (constraint-fn-var 94) (e-lookup-local (p-assign (ident "identity"))) (e-string (e-literal (string "hello"))))) (s-let (p-assign (ident "lst")) - (e-call (constraint-fn-var 192) + (e-call (constraint-fn-var 189) (e-lookup-local (p-assign (ident "identity"))) (e-list diff --git a/test/snapshots/rigid_var_no_instantiation_error.md b/test/snapshots/rigid_var_no_instantiation_error.md index f128c3eb669..31de4e2c355 100644 --- a/test/snapshots/rigid_var_no_instantiation_error.md +++ b/test/snapshots/rigid_var_no_instantiation_error.md @@ -240,7 +240,7 @@ main! = |_| { (e-block (s-let (p-assign (ident "result1")) - (e-call (constraint-fn-var 121) + (e-call (constraint-fn-var 118) (e-lookup-local (p-assign (ident "swap"))) (e-tuple @@ -250,7 +250,7 @@ main! = |_| { (e-literal (string "hello"))))))) (s-let (p-assign (ident "result2")) - (e-call (constraint-fn-var 219) + (e-call (constraint-fn-var 216) (e-lookup-local (p-assign (ident "swap"))) (e-tuple @@ -263,7 +263,7 @@ main! = |_| { (e-num (value "3")))))))) (s-let (p-assign (ident "result3")) - (e-call (constraint-fn-var 257) + (e-call (constraint-fn-var 248) (e-lookup-local (p-assign (ident "swap"))) (e-tuple diff --git a/test/snapshots/shorthand_polymorphic_method.md b/test/snapshots/shorthand_polymorphic_method.md index f64b03a6046..984855efdd8 100644 --- a/test/snapshots/shorthand_polymorphic_method.md +++ b/test/snapshots/shorthand_polymorphic_method.md @@ -163,7 +163,7 @@ main = { (e-num (value "3")))))) (s-let (p-assign (ident "string_list")) - (e-call (constraint-fn-var 234) + (e-call (constraint-fn-var 225) (e-lookup-local (p-assign (ident "shorthand"))) (e-list diff --git a/test/snapshots/statement/for_loop_list_str.md b/test/snapshots/statement/for_loop_list_str.md index 1915ec11ea9..52d379312fb 100644 --- a/test/snapshots/statement/for_loop_list_str.md +++ b/test/snapshots/statement/for_loop_list_str.md @@ -94,7 +94,7 @@ NO CHANGE (e-block (s-reassign (p-assign (ident "counter_")) - (e-dispatch-call (method "plus") (constraint-fn-var 280) + (e-dispatch-call (method "plus") (constraint-fn-var 271) (receiver (e-lookup-local (p-assign (ident "counter_")))) diff --git a/test/snapshots/static_dispatch/Adv.md b/test/snapshots/static_dispatch/Adv.md index 28500280429..2d499c89d43 100644 --- a/test/snapshots/static_dispatch/Adv.md +++ b/test/snapshots/static_dispatch/Adv.md @@ -401,7 +401,7 @@ main = { (e-literal (string "hello"))))))) (s-let (p-assign (ident "next_val")) - (e-dispatch-call (method "update_str") (constraint-fn-var 538) + (e-dispatch-call (method "update_str") (constraint-fn-var 523) (receiver (e-lookup-local (p-assign (ident "val")))) @@ -417,7 +417,7 @@ main = { (e-block (s-let (p-assign (ident "next_val")) - (e-dispatch-call (method "update") (constraint-fn-var 782) + (e-dispatch-call (method "update") (constraint-fn-var 749) (receiver (e-string (e-literal (string "Hello")))) @@ -437,9 +437,9 @@ main = { (e-literal (string "hello"))))))) (s-let (p-assign (ident "next_val")) - (e-dispatch-call (method "update_u64") (constraint-fn-var 1043) + (e-dispatch-call (method "update_u64") (constraint-fn-var 980) (receiver - (e-dispatch-call (method "update_str") (constraint-fn-var 975) + (e-dispatch-call (method "update_str") (constraint-fn-var 924) (receiver (e-lookup-local (p-assign (ident "val")))) @@ -450,12 +450,12 @@ main = { (e-num (value "20"))))) (e-tuple (elems - (e-dispatch-call (method "to_str") (constraint-fn-var 1130) + (e-dispatch-call (method "to_str") (constraint-fn-var 1067) (receiver (e-lookup-local (p-assign (ident "next_val")))) (args)) - (e-dispatch-call (method "to_u64") (constraint-fn-var 1132) + (e-dispatch-call (method "to_u64") (constraint-fn-var 1069) (receiver (e-lookup-local (p-assign (ident "next_val")))) diff --git a/test/snapshots/static_dispatch/Basic.md b/test/snapshots/static_dispatch/Basic.md index 84c41e7923d..ef6ad9cfa89 100644 --- a/test/snapshots/static_dispatch/Basic.md +++ b/test/snapshots/static_dispatch/Basic.md @@ -245,12 +245,12 @@ main = (helper1(val), helper2(val)) (p-assign (ident "main")) (e-tuple (elems - (e-call (constraint-fn-var 243) + (e-call (constraint-fn-var 228) (e-lookup-local (p-assign (ident "helper1"))) (e-lookup-local (p-assign (ident "val")))) - (e-call (constraint-fn-var 248) + (e-call (constraint-fn-var 233) (e-lookup-local (p-assign (ident "helper2"))) (e-lookup-local diff --git a/test/snapshots/static_dispatch/BasicNoAnno.md b/test/snapshots/static_dispatch/BasicNoAnno.md index af2f2a3c2a3..851cf0621cf 100644 --- a/test/snapshots/static_dispatch/BasicNoAnno.md +++ b/test/snapshots/static_dispatch/BasicNoAnno.md @@ -174,12 +174,12 @@ main = (helper1(val), helper2(val)) (p-assign (ident "main")) (e-tuple (elems - (e-call (constraint-fn-var 152) + (e-call (constraint-fn-var 137) (e-lookup-local (p-assign (ident "helper1"))) (e-lookup-local (p-assign (ident "val")))) - (e-call (constraint-fn-var 157) + (e-call (constraint-fn-var 142) (e-lookup-local (p-assign (ident "helper2"))) (e-lookup-local diff --git a/test/snapshots/static_dispatch/MethodDispatch.md b/test/snapshots/static_dispatch/MethodDispatch.md index fee6cf4d06b..095a0ca16e4 100644 --- a/test/snapshots/static_dispatch/MethodDispatch.md +++ b/test/snapshots/static_dispatch/MethodDispatch.md @@ -253,7 +253,7 @@ NO CHANGE (e-nominal (nominal "Container") (e-tag (name "Box") (args - (e-call (constraint-fn-var 225) + (e-call (constraint-fn-var 223) (e-lookup-local (p-assign (ident "fn"))) (e-lookup-local @@ -271,7 +271,7 @@ NO CHANGE (e-lambda (args (p-assign (ident "x"))) - (e-dispatch-call (method "get_value") (constraint-fn-var 250) + (e-dispatch-call (method "get_value") (constraint-fn-var 248) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -291,7 +291,7 @@ NO CHANGE (args (p-assign (ident "x")) (p-assign (ident "fn"))) - (e-dispatch-call (method "transform") (constraint-fn-var 283) + (e-dispatch-call (method "transform") (constraint-fn-var 281) (receiver (e-lookup-local (p-assign (ident "x")))) @@ -335,7 +335,7 @@ NO CHANGE (ty-lookup (name "Container") (local)))) (d-let (p-assign (ident "directCall")) - (e-dispatch-call (method "get_value") (constraint-fn-var 436) + (e-dispatch-call (method "get_value") (constraint-fn-var 404) (receiver (e-lookup-local (p-assign (ident "myContainer")))) @@ -344,7 +344,7 @@ NO CHANGE (ty-lookup (name "Str") (builtin)))) (d-let (p-assign (ident "result1")) - (e-call (constraint-fn-var 448) + (e-call (constraint-fn-var 416) (e-lookup-local (p-assign (ident "extract"))) (e-lookup-local @@ -353,7 +353,7 @@ NO CHANGE (ty-lookup (name "Str") (builtin)))) (d-let (p-assign (ident "result2")) - (e-call (constraint-fn-var 592) + (e-call (constraint-fn-var 441) (e-lookup-local (p-assign (ident "modify"))) (e-lookup-local @@ -366,24 +366,13 @@ NO CHANGE (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "s")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 590) - (receiver - (e-string - (e-literal (string "")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 548) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 484) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " world")))))))))))) + (e-interpolation (constraint-fn-var 439) + (first + (e-literal (string ""))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " world"))))))) (annotation (ty-lookup (name "Container") (local)))) (d-let @@ -394,7 +383,7 @@ NO CHANGE (p-assign (ident "directCall"))) (e-lookup-local (p-assign (ident "result1"))) - (e-call (constraint-fn-var 738) + (e-call (constraint-fn-var 468) (e-lookup-local (p-assign (ident "extract"))) (e-lookup-local diff --git a/test/snapshots/static_dispatch_concrete_ok.md b/test/snapshots/static_dispatch_concrete_ok.md index ae6ef0c82d5..3187fc0d5e0 100644 --- a/test/snapshots/static_dispatch_concrete_ok.md +++ b/test/snapshots/static_dispatch_concrete_ok.md @@ -130,7 +130,7 @@ NO CHANGE (p-assign (ident "x"))))) (d-let (p-assign (ident "poly_no_dispatch")) - (e-call (constraint-fn-var 234) + (e-call (constraint-fn-var 231) (e-lookup-local (p-assign (ident "id"))) (e-string diff --git a/test/snapshots/str_interp_int_debug.md b/test/snapshots/str_interp_int_debug.md index db9d82292df..696694e6132 100644 --- a/test/snapshots/str_interp_int_debug.md +++ b/test/snapshots/str_interp_int_debug.md @@ -34,28 +34,17 @@ NO CHANGE (e-block (s-let (p-assign (ident "#interp_0")) - (e-call (constraint-fn-var 66) + (e-call (constraint-fn-var 64) (e-lookup-external (builtin)) (e-num (value "0")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 262) - (receiver - (e-string - (e-literal (string "zero: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 220) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 156) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "")))))))))) + (e-interpolation (constraint-fn-var 141) + (first + (e-literal (string "zero: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ""))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/string_interpolation_desugar.md b/test/snapshots/string_interpolation_desugar.md index 2eeecdbf054..e337484104f 100644 --- a/test/snapshots/string_interpolation_desugar.md +++ b/test/snapshots/string_interpolation_desugar.md @@ -54,24 +54,13 @@ NO CHANGE (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "name")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 170) - (receiver - (e-string - (e-literal (string "Hello, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 128) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 64) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "!"))))))))))) + (e-interpolation (constraint-fn-var 49) + (first + (e-literal (string "Hello, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "!")))))) (annotation (ty-fn (effectful false) (ty-lookup (name "Str") (builtin)) diff --git a/test/snapshots/string_interpolation_type_mismatch.md b/test/snapshots/string_interpolation_type_mismatch.md index d760aa5fb96..42316e0b0fb 100644 --- a/test/snapshots/string_interpolation_type_mismatch.md +++ b/test/snapshots/string_interpolation_type_mismatch.md @@ -11,23 +11,23 @@ x = 42 y = "value: ${x}" ~~~ # EXPECTED -TYPE MISMATCH - string_interpolation_type_mismatch.md:1:1:1:1 +TYPE MISMATCH - string_interpolation_type_mismatch.md:4:15:4:16 # PROBLEMS **TYPE MISMATCH** -The `from_interpolation` method on `Str` has an incompatible type: -**string_interpolation_type_mismatch.md:1:1:1:1:** +This expression is used in an unexpected way: +**string_interpolation_type_mismatch.md:4:15:4:16:** ```roc -x : U8 +y = "value: ${x}" ``` -^ + ^ -The method `from_interpolation` has the type: +It has the type: - Str, Iter((Str, Str)) -> Str + U8 -But I need it to have the type: +But you are trying to use it as: - Str, Iter((U8, Str)) -> Str + Str # TOKENS ~~~zig @@ -72,24 +72,13 @@ NO CHANGE (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "x")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 258) - (receiver - (e-string - (e-literal (string "value: ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 216) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 152) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string "")))))))))))) + (e-interpolation (constraint-fn-var 137) + (first + (e-literal (string "value: "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string ""))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_1.md b/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_1.md index 09c3ed9489f..2e62ab8bf04 100644 --- a/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_1.md +++ b/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_1.md @@ -46,26 +46,15 @@ EndOfFile, (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 151) - (receiver - (e-string - (e-literal (string "This is a string with ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 109) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 45) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " lines of text due to the template parts")))))))))) + (e-interpolation + (first + (e-literal (string "This is a string with "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " lines of text due to the template parts"))))) ~~~ # TYPES ~~~clojure -(expr (type "Str")) +(expr (type "Error")) ~~~ diff --git a/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_3.md b/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_3.md index 5956572aac6..a58392d12c2 100644 --- a/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_3.md +++ b/test/snapshots/string_multiline_formatting_(due_to_templating_not_multiline_string_literal)_3.md @@ -49,26 +49,15 @@ NO CHANGE (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")) (e-runtime-error (tag "ident_not_in_scope")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 151) - (receiver - (e-string - (e-literal (string "This is a string with ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 109) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 45) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string " lines of text due to the template parts")))))))))) + (e-interpolation + (first + (e-literal (string "This is a string with "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string " lines of text due to the template parts"))))) ~~~ # TYPES ~~~clojure -(expr (type "Str")) +(expr (type "Error")) ~~~ diff --git a/test/snapshots/syntax_grab_bag.md b/test/snapshots/syntax_grab_bag.md index 17502ab0865..a11d83c8a9b 100644 --- a/test/snapshots/syntax_grab_bag.md +++ b/test/snapshots/syntax_grab_bag.md @@ -2251,7 +2251,7 @@ expect { (s-expr (e-not-implemented)) (s-expr - (e-call (constraint-fn-var 2526) + (e-call (constraint-fn-var 2501) (e-lookup-local (p-assign (ident "match_time"))) (e-not-implemented))) @@ -2274,24 +2274,13 @@ expect { (p-assign (ident "#interp_0")) (e-lookup-local (p-assign (ident "world")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 2685) - (receiver - (e-string - (e-literal (string "Hello, ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 2643) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2579) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_0"))) - (e-string - (e-literal (string ""))))))))))) + (e-interpolation (constraint-fn-var 2541) + (first + (e-literal (string "Hello, "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_0"))) + (e-literal (string "")))))) (s-let (p-assign (ident "list")) (e-list @@ -2321,36 +2310,19 @@ expect { (p-assign (ident "#interp_2")) (e-lookup-local (p-assign (ident "number")))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 3062) - (receiver - (e-string - (e-literal (string "Adding ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 3020) - (receiver - (e-dispatch-call (method "prepended") (constraint-fn-var 2962) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 2898) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_2"))) - (e-string - (e-literal (string "")))))))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_1"))) - (e-string - (e-literal (string " to ")))))))))))) + (e-interpolation + (first + (e-literal (string "Adding "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_1"))) + (e-literal (string " to ")) + (e-lookup-local + (p-assign (ident "#interp_2"))) + (e-literal (string ""))))))) (s-reassign (p-assign (ident "number")) - (e-dispatch-call (method "plus") (constraint-fn-var 3065) + (e-dispatch-call (method "plus") (constraint-fn-var 2745) (receiver (e-lookup-local (p-assign (ident "number")))) @@ -2426,7 +2398,7 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_gt") (constraint-fn-var 3505) + (e-dispatch-call (method "is_gt") (constraint-fn-var 3176) (receiver (e-match (match @@ -2451,7 +2423,7 @@ expect { (value (e-num (value "12")))))))) (args - (e-dispatch-call (method "times") (constraint-fn-var 3500) + (e-dispatch-call (method "times") (constraint-fn-var 3171) (receiver (e-num (value "5"))) (args @@ -2466,18 +2438,18 @@ expect { (e-if (if-branches (if-branch - (e-dispatch-call (method "is_lt") (constraint-fn-var 3613) + (e-dispatch-call (method "is_lt") (constraint-fn-var 3284) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 3578) + (e-dispatch-call (method "plus") (constraint-fn-var 3249) (receiver (e-num (value "13"))) (args (e-num (value "2"))))) (args (e-num (value "5")))) - (e-dispatch-call (method "is_gte") (constraint-fn-var 3713) + (e-dispatch-call (method "is_gte") (constraint-fn-var 3384) (receiver - (e-dispatch-call (method "minus") (constraint-fn-var 3678) + (e-dispatch-call (method "minus") (constraint-fn-var 3349) (receiver (e-num (value "10"))) (args @@ -2492,11 +2464,11 @@ expect { (builtin) (e-tag (name "True"))))) (if-else - (e-dispatch-call (method "is_lte") (constraint-fn-var 3823) + (e-dispatch-call (method "is_lte") (constraint-fn-var 3494) (receiver (e-num (value "12"))) (args - (e-dispatch-call (method "div_by") (constraint-fn-var 3818) + (e-dispatch-call (method "div_by") (constraint-fn-var 3489) (receiver (e-num (value "3"))) (args @@ -2511,12 +2483,12 @@ expect { (e-match (match (cond - (e-dispatch-call (method "next_static_dispatch_method") (constraint-fn-var 3889) + (e-dispatch-call (method "next_static_dispatch_method") (constraint-fn-var 3560) (receiver (e-match (match (cond - (e-dispatch-call (method "static_dispatch_method") (constraint-fn-var 3856) + (e-dispatch-call (method "static_dispatch_method") (constraint-fn-var 3527) (receiver (e-match (match @@ -2651,24 +2623,13 @@ expect { (e-runtime-error (tag "qualified_ident_does_not_exist")) (e-lookup-local (p-assign (ident "number"))))) - (e-dispatch-call (method "from_interpolation") (constraint-fn-var 4113) - (receiver - (e-string - (e-literal (string "How about ")))) - (args - (e-dispatch-call (method "prepended") (constraint-fn-var 4071) - (receiver - (e-dispatch-call (method "iter") (constraint-fn-var 4007) - (receiver - (e-empty_list)) - (args))) - (args - (e-tuple - (elems - (e-lookup-local - (p-assign (ident "#interp_3"))) - (e-string - (e-literal (string " as a string?"))))))))))))) + (e-interpolation + (first + (e-literal (string "How about "))) + (parts + (e-lookup-local + (p-assign (ident "#interp_3"))) + (e-literal (string " as a string?")))))))) (annotation (ty-fn (effectful false) (ty-apply (name "List") (builtin) diff --git a/test/snapshots/test_instantiated_arg_mismatch.md b/test/snapshots/test_instantiated_arg_mismatch.md index f7af8d32c35..0c35e78ac6d 100644 --- a/test/snapshots/test_instantiated_arg_mismatch.md +++ b/test/snapshots/test_instantiated_arg_mismatch.md @@ -86,7 +86,7 @@ EndOfFile, (p-assign (ident "x"))) (e-lookup-local (p-assign (ident "y"))))))) - (e-call (constraint-fn-var 80) + (e-call (constraint-fn-var 77) (e-lookup-local (p-assign (ident "pair"))) (e-num (value "42")) diff --git a/test/snapshots/test_instantiated_return_crash.md b/test/snapshots/test_instantiated_return_crash.md index 1eaa6e277d6..e7fe6a5c418 100644 --- a/test/snapshots/test_instantiated_return_crash.md +++ b/test/snapshots/test_instantiated_return_crash.md @@ -28,7 +28,7 @@ The first argument being passed to this function has the wrong type: This argument has the type: - List(b) where [b.from_quote : List(U8) -> Try(b, [BadQuotedBytes(Str)])] + List(b) where [b.from_quote : Str -> Try(b, [BadQuotedBytes(Str)])] But `f` needs the first argument to be: @@ -113,7 +113,7 @@ EndOfFile, (elems (e-string (e-literal (string "hello")))))))) - (e-call (constraint-fn-var 83) + (e-call (constraint-fn-var 80) (e-lookup-local (p-assign (ident "needs_string"))) (e-lookup-local diff --git a/test/snapshots/test_nested_instantiation_crash.md b/test/snapshots/test_nested_instantiation_crash.md index 99cba5bf35a..8a6bdd1ad21 100644 --- a/test/snapshots/test_nested_instantiation_crash.md +++ b/test/snapshots/test_nested_instantiation_crash.md @@ -185,10 +185,10 @@ answer = composed([42]) (e-lambda (args (p-assign (ident "n"))) - (e-call (constraint-fn-var 164) + (e-call (constraint-fn-var 149) (e-lookup-local (p-assign (ident "get_value"))) - (e-call (constraint-fn-var 163) + (e-call (constraint-fn-var 148) (e-lookup-local (p-assign (ident "make_record"))) (e-runtime-error (tag "erroneous_value_use"))))) @@ -199,7 +199,7 @@ answer = composed([42]) (ty-lookup (name "Str") (builtin))))) (d-let (p-assign (ident "answer")) - (e-call (constraint-fn-var 200) + (e-call (constraint-fn-var 185) (e-lookup-local (p-assign (ident "composed"))) (e-list diff --git a/test/snapshots/type_alias_simple.md b/test/snapshots/type_alias_simple.md index d87ff06ce19..1472333e171 100644 --- a/test/snapshots/type_alias_simple.md +++ b/test/snapshots/type_alias_simple.md @@ -108,7 +108,7 @@ NO CHANGE (e-lambda (args (p-underscore)) - (e-call (constraint-fn-var 275) + (e-call (constraint-fn-var 257) (e-lookup-local (p-assign (ident "getUser"))) (e-num (value "100"))))) diff --git a/test/snapshots/type_annotation_basic.md b/test/snapshots/type_annotation_basic.md index 17b13336ab0..2bcfbf5c032 100644 --- a/test/snapshots/type_annotation_basic.md +++ b/test/snapshots/type_annotation_basic.md @@ -242,14 +242,14 @@ main! = |_| { (e-num (value "42")))) (s-let (p-assign (ident "text")) - (e-call (constraint-fn-var 251) + (e-call (constraint-fn-var 248) (e-lookup-local (p-assign (ident "identity"))) (e-string (e-literal (string "hello"))))) (s-let (p-assign (ident "pair")) - (e-call (constraint-fn-var 256) + (e-call (constraint-fn-var 253) (e-lookup-local (p-assign (ident "combine"))) (e-lookup-local @@ -258,7 +258,7 @@ main! = |_| { (p-assign (ident "text"))))) (s-let (p-assign (ident "result")) - (e-call (constraint-fn-var 287) + (e-call (constraint-fn-var 284) (e-lookup-local (p-assign (ident "addOne"))) (e-num (value "5")))) diff --git a/test/snapshots/type_app_multiple_args.md b/test/snapshots/type_app_multiple_args.md index 14509cca4b4..d907bb50e43 100644 --- a/test/snapshots/type_app_multiple_args.md +++ b/test/snapshots/type_app_multiple_args.md @@ -95,10 +95,10 @@ NO CHANGE (e-lambda (args (p-underscore)) - (e-call (constraint-fn-var 326) + (e-call (constraint-fn-var 323) (e-lookup-local (p-assign (ident "processDict"))) - (e-dispatch-call (method "insert") (constraint-fn-var 222) + (e-dispatch-call (method "insert") (constraint-fn-var 219) (receiver (e-call (constraint-fn-var 175) (e-lookup-external diff --git a/test/snapshots/type_app_nested.md b/test/snapshots/type_app_nested.md index 8a97c42a9c5..be61dae7682 100644 --- a/test/snapshots/type_app_nested.md +++ b/test/snapshots/type_app_nested.md @@ -115,7 +115,7 @@ main! = |_| processNested([]) (e-lambda (args (p-underscore)) - (e-call (constraint-fn-var 151) + (e-call (constraint-fn-var 133) (e-lookup-local (p-assign (ident "processNested"))) (e-empty_list))))) diff --git a/test/snapshots/type_app_single_arg.md b/test/snapshots/type_app_single_arg.md index dc022f8a142..5cdb6d022bd 100644 --- a/test/snapshots/type_app_single_arg.md +++ b/test/snapshots/type_app_single_arg.md @@ -99,7 +99,7 @@ main! = |_| processList(["one", "two"]) (e-lambda (args (p-underscore)) - (e-call (constraint-fn-var 102) + (e-call (constraint-fn-var 96) (e-lookup-local (p-assign (ident "processList"))) (e-list diff --git a/test/snapshots/type_application_basic.md b/test/snapshots/type_application_basic.md index c118f2437ce..d91ee33ae34 100644 --- a/test/snapshots/type_application_basic.md +++ b/test/snapshots/type_application_basic.md @@ -101,7 +101,7 @@ main! = |_| processList(["one", "two", "three"]) (e-lambda (args (p-underscore)) - (e-call (constraint-fn-var 120) + (e-call (constraint-fn-var 111) (e-lookup-local (p-assign (ident "processList"))) (e-list diff --git a/test/snapshots/type_multiple_aliases.md b/test/snapshots/type_multiple_aliases.md index 67973c13c5d..d981293ab98 100644 --- a/test/snapshots/type_multiple_aliases.md +++ b/test/snapshots/type_multiple_aliases.md @@ -184,14 +184,14 @@ NO CHANGE (e-block (s-let (p-assign (ident "user")) - (e-call (constraint-fn-var 269) + (e-call (constraint-fn-var 266) (e-lookup-local (p-assign (ident "create_user"))) (e-num (value "123")) (e-string (e-literal (string "Alice"))) (e-num (value "25")))) - (e-call (constraint-fn-var 446) + (e-call (constraint-fn-var 431) (e-lookup-local (p-assign (ident "get_user_name"))) (e-lookup-local diff --git a/test/snapshots/type_record_basic.md b/test/snapshots/type_record_basic.md index 86efe806ce6..d583b3f3f13 100644 --- a/test/snapshots/type_record_basic.md +++ b/test/snapshots/type_record_basic.md @@ -28,7 +28,7 @@ This argument has the type: { age: a, namee: b } where [ a.from_numeral : Numeral -> Try(a, [InvalidNumeral(Str)]), - b.from_quote : List(U8) -> Try(b, [BadQuotedBytes(Str)]), + b.from_quote : Str -> Try(b, [BadQuotedBytes(Str)]), ] But `getName` needs the first argument to be: diff --git a/test/snapshots/type_var_collision_simple.md b/test/snapshots/type_var_collision_simple.md index 0d5992c4f84..28250f92432 100644 --- a/test/snapshots/type_var_collision_simple.md +++ b/test/snapshots/type_var_collision_simple.md @@ -216,23 +216,23 @@ main! = |_| { (e-num (value "42")))) (s-let (p-assign (ident "result2")) - (e-call (constraint-fn-var 202) + (e-call (constraint-fn-var 199) (e-lookup-local (p-assign (ident "identity2"))) (e-string (e-literal (string "hello"))))) (s-let (p-assign (ident "result3")) - (e-call (constraint-fn-var 207) + (e-call (constraint-fn-var 204) (e-lookup-local (p-assign (ident "pair"))) (e-lookup-local (p-assign (ident "result1"))) (e-lookup-local (p-assign (ident "result2"))))) - (e-dispatch-call (method "plus") (constraint-fn-var 210) + (e-dispatch-call (method "plus") (constraint-fn-var 207) (receiver - (e-dispatch-call (method "plus") (constraint-fn-var 208) + (e-dispatch-call (method "plus") (constraint-fn-var 205) (receiver (e-lookup-local (p-assign (ident "a")))) diff --git a/test/snapshots/type_var_name_avoids_collision.md b/test/snapshots/type_var_name_avoids_collision.md index afd90d87198..9bdbb479446 100644 --- a/test/snapshots/type_var_name_avoids_collision.md +++ b/test/snapshots/type_var_name_avoids_collision.md @@ -557,20 +557,20 @@ main! = |_| { (e-block (s-let (p-assign (ident "result1")) - (e-call (constraint-fn-var 957) + (e-call (constraint-fn-var 954) (e-lookup-local (p-assign (ident "identity"))) (e-num (value "123")))) (s-let (p-assign (ident "result2")) - (e-call (constraint-fn-var 976) + (e-call (constraint-fn-var 970) (e-lookup-local (p-assign (ident "anotherIdentity"))) (e-string (e-literal (string "test"))))) (s-let (p-assign (ident "result3")) - (e-call (constraint-fn-var 981) + (e-call (constraint-fn-var 975) (e-lookup-local (p-assign (ident "combine"))) (e-lookup-local @@ -579,17 +579,17 @@ main! = |_| { (p-assign (ident "result2"))))) (s-let (p-assign (ident "result4")) - (e-call (constraint-fn-var 985) + (e-call (constraint-fn-var 979) (e-lookup-local (p-assign (ident "yetAnotherIdentity"))) (e-tag (name "True")))) (s-let (p-assign (ident "result5")) - (e-call (constraint-fn-var 1018) + (e-call (constraint-fn-var 1012) (e-lookup-local (p-assign (ident "finalIdentity"))) (e-dec-small (numerator "314") (denominator-power-of-ten "2") (value "3.14")))) - (e-dispatch-call (method "plus") (constraint-fn-var 1019) + (e-dispatch-call (method "plus") (constraint-fn-var 1013) (receiver (e-lookup-local (p-assign (ident "a")))) diff --git a/test/snapshots/typed_string_suffix.md b/test/snapshots/typed_string_suffix.md index 27103301a60..b42a9036290 100644 --- a/test/snapshots/typed_string_suffix.md +++ b/test/snapshots/typed_string_suffix.md @@ -5,9 +5,9 @@ type=file ~~~ # SOURCE ~~~roc -Tag := [Tag(List(U8))].{ - from_quote : List(U8) -> Try(Tag, [BadQuotedBytes(Str)]) - from_quote = |bytes| Ok(Tag(bytes)) +Tag := [Tag(Str)].{ + from_quote : Str -> Try(Tag, [BadQuotedBytes(Str)]) + from_quote = |str| Ok(Tag(str)) } single = "Roc".Tag @@ -23,8 +23,8 @@ NIL NIL # TOKENS ~~~zig -UpperIdent,OpColonEqual,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,CloseRound,CloseSquare,Dot,OpenCurly, -LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,OpArrow,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,CloseSquare,CloseRound, +UpperIdent,OpColonEqual,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,CloseSquare,Dot,OpenCurly, +LowerIdent,OpColon,UpperIdent,OpArrow,UpperIdent,NoSpaceOpenRound,UpperIdent,Comma,OpenSquare,UpperIdent,NoSpaceOpenRound,UpperIdent,CloseRound,CloseSquare,CloseRound, LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,UpperIdent,NoSpaceOpenRound,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,CloseRound, CloseCurly, LowerIdent,OpAssign,StringStart,StringPart,StringEnd,NoSpaceDotUpperIdent, @@ -46,15 +46,11 @@ EndOfFile, (tags (ty-apply (ty (name "Tag")) - (ty-apply - (ty (name "List")) - (ty (name "U8")))))) + (ty (name "Str"))))) (associated (s-type-anno (name "from_quote") (ty-fn - (ty-apply - (ty (name "List")) - (ty (name "U8"))) + (ty (name "Str")) (ty-apply (ty (name "Try")) (ty (name "Tag")) @@ -67,12 +63,12 @@ EndOfFile, (p-ident (raw "from_quote")) (e-lambda (args - (p-ident (raw "bytes"))) + (p-ident (raw "str"))) (e-apply (e-tag (raw "Ok")) (e-apply (e-tag (raw "Tag")) - (e-ident (raw "bytes")))))))) + (e-ident (raw "str")))))))) (s-decl (p-ident (raw "single")) (e-typed-string (type "Tag") @@ -85,9 +81,9 @@ EndOfFile, ~~~ # FORMATTED ~~~roc -Tag := [Tag(List(U8))].{ - from_quote : List(U8) -> Try(Tag, [BadQuotedBytes(Str)]) - from_quote = |bytes| Ok(Tag(bytes)) +Tag := [Tag(Str)].{ + from_quote : Str -> Try(Tag, [BadQuotedBytes(Str)]) + from_quote = |str| Ok(Tag(str)) } single = "Roc".Tag @@ -104,17 +100,16 @@ multi = (p-assign (ident "typed_string_suffix.Tag.from_quote")) (e-lambda (args - (p-assign (ident "bytes"))) + (p-assign (ident "str"))) (e-tag (name "Ok") (args (e-tag (name "Tag") (args (e-lookup-local - (p-assign (ident "bytes")))))))) + (p-assign (ident "str")))))))) (annotation (ty-fn (effectful false) - (ty-apply (name "List") (builtin) - (ty-lookup (name "U8") (builtin))) + (ty-lookup (name "Str") (builtin)) (ty-apply (name "Try") (builtin) (ty-lookup (name "Tag") (local)) (ty-tag-union @@ -133,21 +128,20 @@ line two")))) (ty-header (name "Tag")) (ty-tag-union (ty-tag-name (name "Tag") - (ty-apply (name "List") (builtin) - (ty-lookup (name "U8") (builtin))))))) + (ty-lookup (name "Str") (builtin)))))) ~~~ # TYPES ~~~clojure (inferred-types (defs - (patt (type "List(U8) -> Try(Tag, [BadQuotedBytes(Str)])")) + (patt (type "Str -> Try(Tag, [BadQuotedBytes(Str)])")) (patt (type "Tag")) (patt (type "Tag"))) (type_decls (nominal (type "Tag") (ty-header (name "Tag")))) (expressions - (expr (type "List(U8) -> Try(Tag, [BadQuotedBytes(Str)])")) + (expr (type "Str -> Try(Tag, [BadQuotedBytes(Str)])")) (expr (type "Tag")) (expr (type "Tag")))) ~~~ diff --git a/test/snapshots/unused_vars_block.md b/test/snapshots/unused_vars_block.md index 2efbfff959b..f53ec203f40 100644 --- a/test/snapshots/unused_vars_block.md +++ b/test/snapshots/unused_vars_block.md @@ -160,7 +160,7 @@ main! = |_| { (e-num (value "999"))) (s-let (p-assign (ident "result")) - (e-dispatch-call (method "plus") (constraint-fn-var 168) + (e-dispatch-call (method "plus") (constraint-fn-var 165) (receiver (e-lookup-local (p-assign (ident "used_var"))))