Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ab4d88e
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
e9a3f81
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
21fc5c1
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
ae9503c
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
e502d9f
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
3c54472
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
4e33de1
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
05292a8
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
ee1d67a
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
bc57221
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
2d56ebe
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
5952081
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
0f930cb
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
84c15d5
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
8421ce8
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
a14c764
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
4f481d1
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
aaba4f2
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
75bbbbb
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
4c54fd7
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
b703c8a
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
ed50f2e
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
cb9d311
Fix return_type_is_unit authored_name_at argument order in seed emitter.
Jul 25, 2026
39999d1
Merge remote-tracking branch 'origin/main' into session/witty-wolf-289
Jul 25, 2026
7ad69fe
WIP: E0308 mechanical trio: Range-vs-usize + String-vs-str + Unit-vs-…
Jul 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dag/test/retirement/e0308_mechanical_trio_retained.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module test.retirement.e0308_mechanical_trio_retained


data e0308_mechanical_trio_retention: TestModuleRetirement = TestModuleRetirement {
module: "e0308_mechanical_trio_test.rs",
disposition: RetainedNonMigratable {
reason: "The E0308 mechanical-trio witnesses compile minimal .dag fixtures through the v1 seed emitter (compile_dag_target → RenderTarget::Rust) and assert substring properties of the emitted Rust (Range-vs-usize on skip().first() and list slices, String-vs-str borrow at rt_ref_map call sites, Unit-vs-Option tail discard on -> Unit bodies). That host-Rust compile-and-inspect path is the v1 seed-emitter realization surface under repair in src/v1/05_emit_rust.dag; a .dag floor witness cannot reach it without importing the v1 compiler crate (off the compile-clean witness layer roots). Retained until src/v1 deletes at v2 self-host; not migration debt and not a delete candidate."
}
}
11 changes: 8 additions & 3 deletions src/v1/04_access.dag
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,22 @@ fn check_index_access_node(base_type: Node, index_type: Node, span: SourceSpan,
fn check_slice_access_node(base_type: Node, start_type: Node, end_type: Node, span: SourceSpan, module_name: String, source_indices: Map<String, NewlineIndex>) -> AccessCheckResultNode {
let normed_base = normalize_access_type_node(n: base_type)
let base_is_string = node_type_equals(left: normed_base, right: string_type, source_indices: source_indices)
let base_diags = if base_is_string { [] }
else { [access_error(message: "slice is only supported for String values", span: span, module_name: module_name)] }
let base_is_list = is_ordered_element_collection(name: authored_name_at(source_indices: source_indices, node: normed_base))
&& node_is_element_collection(n: normed_base, source_indices: source_indices)
let base_diags = if base_is_string || base_is_list { [] }
else { [access_error(message: "slice is only supported for String and list values", span: span, module_name: module_name)] }
let normed_start = normalize_access_type_node(n: start_type)
let start_diags = if node_type_equals(left: normed_start, right: int_type, source_indices: source_indices) { [] }
else { [access_error(message: "slice start requires an Int index", span: span, module_name: module_name)] }
let normed_end = normalize_access_type_node(n: end_type)
let end_diags = if node_type_equals(left: normed_end, right: int_type, source_indices: source_indices) { [] }
else { [access_error(message: "slice end requires an Int index", span: span, module_name: module_name)] }
let all_diags = concat(base_diags, start_diags, end_diags)
let slice_result_type = if base_is_string { string_type }
else if base_is_list { normed_base }
else { string_type }
access_result(
inferred: string_type,
inferred: slice_result_type,
diagnostics: all_diags,
span: span,
fallback_message: "invalid slice access"
Expand Down
121 changes: 110 additions & 11 deletions src/v1/05_emit_rust.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5109,22 +5109,125 @@ fn emit_fn_def(name: String, params: List<Node>, inferred: Node, body: Node, reg
concat(rust_visibility_prefix(), kw, " ", emit_ident(name: name, target: Rust), type_params_str, "(", tco_params_str, ")", ret_str, " {\n",
make_indent(level: depth + 1),body_str, "\n}")
} else {
emit_fn_def_non_tco(name: name, type_params_str: type_params_str, params_str: params_str, ret_str: ret_str, body: body, registry: registry, scope: body_scope, depth: depth, shared_types: shared_types, emit_info: body_emit_info, needs_stacker: needs_stacker)
let return_is_unit = return_type_is_unit(n: inferred, source_indices: si)
emit_fn_def_non_tco(name: name, type_params_str: type_params_str, params_str: params_str, ret_str: ret_str, body: body, registry: registry, scope: body_scope, depth: depth, shared_types: shared_types, emit_info: body_emit_info, needs_stacker: needs_stacker, return_is_unit: return_is_unit)
}
}
}
}

fn emit_fn_def_non_tco(name: String, type_params_str: String, params_str: String, ret_str: String, body: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo, needs_stacker: Bool) -> String {
fn return_type_is_unit(n: Node, source_indices: Map<String, NewlineIndex>) -> Bool {
let authored = authored_name_at(source_indices: source_indices, node: n)
let name = if authored != "" { authored } else { n.name }
is_unit_like(n: n) && name == "Unit"
}

fn emit_rust_fn_body_expr(texpr: Node, return_is_unit: Bool, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo) -> String {
if return_is_unit {
emit_rust_unit_discarding_stmt(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
} else {
emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
}
}

fn inferred_expr_is_optional(texpr: Node) -> Bool {
match texpr.inferred {
Present { value: Resolved { node: rt } } => rt.return_cardinality == CardOptional
_ => false
}
}

fn emit_rust_unit_discarding_optional_typed(texpr: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo) -> String {
match texpr.expr_data {
ExprLiteral { value: v } =>
match v {
LitNull => "()"
_ => emit_error_expr(message: "unit-discard: optional literal with unexpected value shape", target: Rust)
}
ExprRecordLit { parent_enum: _ } =>
match texpr.children |> count {
0 => "()"
1 =>
match texpr.children |> first {
Present { value: f } =>
emit_rust_unit_discarding_stmt(texpr: field_init_node_value(n: f), registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
Absent => emit_error_expr(message: "unit-discard: optional record literal missing payload field", target: Rust)
}
_ => emit_error_expr(message: "unit-discard: optional record literal with unexpected field count", target: Rust)
}
_ =>
emit_error_expr(message: "unit-discard: unsupported optional expression form for Unit return", target: Rust)
}
}

fn emit_rust_unit_discarding_stmt(texpr: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo) -> String {
let si = scope.type_env.source_indices
match texpr.expr_data {
ExprLet =>
let v = let_value(texpr: texpr)
let inner = let_body(texpr: texpr)
if inferred_expr_is_optional(texpr: v) {
match inner {
Present { value: bd } =>
concat(emit_rust_unit_discarding_stmt(texpr: v, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info), "\n", emit_rust_unit_discarding_stmt(texpr: bd, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info))
Absent => emit_rust_unit_discarding_stmt(texpr: v, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
}
} else {
let n = let_binding_name_at(texpr: texpr, source_indices: si)
let val_str = emit_typed_expr(texpr: v, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
let let_line = emit_let_binding(name: n, value: val_str, target: Rust)
match inner {
Present { value: bd } =>
concat(let_line, "\n", emit_rust_unit_discarding_stmt(texpr: bd, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info))
Absent => let_line
}
}
ExprBlock =>
texpr.children
|> map(child => emit_rust_unit_discarding_stmt(texpr: child, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info))
|> join(separator: "\n")
ExprIf =>
let c = if_condition(texpr: texpr)
let t = if_then_branch(texpr: texpr)
let e = if_else_branch(texpr: texpr)
let cond_str = emit_typed_expr(texpr: c, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
let then_str = emit_rust_unit_discarding_stmt(texpr: t, registry: registry, scope: scope, depth: depth + 1, shared_types: shared_types, emit_info: emit_info)
match e {
Present { value: eb } =>
let else_str = emit_rust_unit_discarding_stmt(texpr: eb, registry: registry, scope: scope, depth: depth + 1, shared_types: shared_types, emit_info: emit_info)
concat("if ", cond_str, " {\n", make_indent(level: depth + 1), then_str, "\n} else {\n", make_indent(level: depth + 1), else_str, "\n}")
Absent =>
concat("if ", cond_str, " {\n", make_indent(level: depth + 1), then_str, "\n}")
}
ExprRecordLit { parent_enum: _ } =>
if inferred_expr_is_optional(texpr: texpr) {
emit_rust_unit_discarding_optional_typed(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
} else {
concat(emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024), ";")
}
ExprLiteral { value: v } =>
if inferred_expr_is_optional(texpr: texpr) {
emit_rust_unit_discarding_optional_typed(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
} else {
match v { LitNull => "()" _ => concat(emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024), ";") }
}
ExprVar { binding_kind: _ } =>
concat(emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024), ";")
_ =>
concat(emit_typed_expr(texpr: texpr, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024), ";")
}
}

fn emit_fn_def_non_tco(name: String, type_params_str: String, params_str: String, ret_str: String, body: Node, registry: Map<String, ItemInfo>, scope: InferScope, depth: Int, shared_types: Set<String>, emit_info: EmitGraphInfo, needs_stacker: Bool, return_is_unit: Bool) -> String {
if needs_stacker {
let body_str = emit_typed_expr(texpr: body, registry: registry, scope: scope, depth: depth + 2, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
let body_str = emit_rust_fn_body_expr(texpr: body, return_is_unit: return_is_unit, registry: registry, scope: scope, depth: depth + 2, shared_types: shared_types, emit_info: emit_info)
let kw = rust_items().func_keyword
concat(rust_visibility_prefix(), kw, " ", emit_ident(name: name, target: Rust), type_params_str, "(", params_str, ")", ret_str, " {\n",
make_indent(level: depth + 1), "stacker::maybe_grow(512 * 1024, 2 * 1024 * 1024, || {\n",
make_indent(level: depth + 2), body_str, "\n",
make_indent(level: depth + 1), "})\n}")
} else {
let body_str = emit_typed_expr(texpr: body, registry: registry, scope: scope, depth: depth + 1, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
let body_str = emit_rust_fn_body_expr(texpr: body, return_is_unit: return_is_unit, registry: registry, scope: scope, depth: depth + 1, shared_types: shared_types, emit_info: emit_info)
let kw = rust_items().func_keyword
concat(rust_visibility_prefix(), kw, " ", emit_ident(name: name, target: Rust), type_params_str, "(", params_str, ")", ret_str, " {\n",
make_indent(level: depth + 1), body_str, "\n}")
Expand Down Expand Up @@ -5261,13 +5364,13 @@ fn emit_rust_param_type(n: Node, generic_param_names: List<String>, shared_types
}

fn emit_param(param: Node, generic_param_names: List<String>, shared_types: Set<String>, corpus_repr: RustCorpusRepr, source_indices: Map<String, NewlineIndex>, read_only_params: Set<String>, variant_to_enum: Map<String, String>, env: TypeEnv) -> String {
let pname = param_node_name_at(n: param, source_indices: source_indices)
let authored = param_node_type_expr(n: param)
let ty = if authored.params |> count > 0 {
emit_rust_param_type(n: authored, generic_param_names: generic_param_names, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: variant_to_enum, env: env)
} else {
render_rust_param_sig_type(param: param, generic_param_names: generic_param_names, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: variant_to_enum, env: env)
}
let pname = param_node_name_at(n: param, source_indices: source_indices)
concat(emit_ident(name: pname, target: Rust), rust_items().param_type_sep, ty)
}

Expand Down Expand Up @@ -6752,16 +6855,12 @@ fn emit_typed_call(func: String, args: List<Node>, registry: Map<String, ItemInf
let filled_args = fill_default_args(ordered: ordered_args, callee: callee, registry: registry, scope: collection_scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
let is_rt = map_contains_key(rt_functions(), func)
let is_rt_ref_map = map_contains_key(rt_ref_map_functions(), func)
let callee_borrow_positions = empty_string_bool_map()
let arg_strs = filled_args |> enumerate |> map(pair =>
let idx = pair.first
let a = pair.second
if is_rt_ref_map && idx == 0 {
let base = emit_typed_expr_base(texpr: arg_value(n: a), registry: registry, scope: collection_scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
concat("&", base)
} else if map_contains_key(callee_borrow_positions, to_string(value: idx)) {
let base = emit_typed_expr_base(texpr: arg_value(n: a), registry: registry, scope: collection_scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
apply_type_template1(template: sharing_for_target(target: Rust).borrow_arg_template, arg0: base)
} else {
let base = emit_cloned_arg(texpr: arg_value(n: a), registry: registry, scope: collection_scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
rust_call_arg_fail_closed_unwrap(arg_str: base, arg: arg_value(n: a), callee: callee, idx: idx, func: func)
Expand Down Expand Up @@ -7339,8 +7438,8 @@ fn emit_rust_first_method_call(receiver: Node, registry: Map<String, ItemInfo>,
let skip_recv = method_receiver(texpr: receiver)
let skip_args = method_arg_nodes(texpr: receiver)
let recv_str = emit_typed_expr(texpr: skip_recv, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
let arg_str = emit_typed_first_arg(args: skip_args, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
concat(recv_str, ".get(", arg_str, " as usize).cloned()")
let n_str = emit_typed_first_arg(args: skip_args, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info)
concat(recv_str, ".iter().cloned().skip(", n_str, " as usize).next()")
} else {
let recv_str = emit_typed_expr(texpr: receiver, registry: registry, scope: scope, depth: depth, shared_types: shared_types, emit_info: emit_info, fuel: 1024)
concat(recv_str, ".first().cloned()")
Expand Down
4 changes: 2 additions & 2 deletions src/v1/languages.dag
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ fn rust_spec() -> LanguageSpec {
list_index: "{0}[({1}) as usize].clone()",
map_index: "({0}).get(&{1}).cloned()",
string_index: "v1_rt::char_at(&{0}, {1})",
list_slice: null,
list_slice: "Rc::new((*{0})[{1} as usize..{2} as usize].to_vec())",
string_slice: "v1_rt::substring(&{0}, {1}, {2})"
},
annotations: AnnotationRequirements {
Expand Down Expand Up @@ -836,7 +836,7 @@ fn dag_spec() -> LanguageSpec {
list_index: "{0}[({1}) as usize].clone()",
map_index: "({0}).get(&{1}).cloned()",
string_index: "v1_rt::char_at(&{0}, {1})",
list_slice: null,
list_slice: "Rc::new((*{0})[{1} as usize..{2} as usize].to_vec())",
string_slice: "v1_rt::substring(&{0}, {1}, {2})"
},
annotations: AnnotationRequirements {
Expand Down
24 changes: 20 additions & 4 deletions src/v1/stage0/src/extdeps_uri_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ pub fn parse_segment_tokens(seg: String) -> Rc<PathSegmentTokensResult> {
})
}
};
let after_open = match before_and_rest.clone().get(1 as usize).cloned() {
let after_open = match before_and_rest
.clone()
.iter()
.cloned()
.skip(1 as usize)
.next()
{
Some(r) => r.clone(),
None => {
return Rc::new(PathSegmentTokensResult::MalformedPathSegment {
Expand Down Expand Up @@ -123,7 +129,13 @@ pub fn parse_segment_tokens(seg: String) -> Rc<PathSegmentTokensResult> {
})
}
};
let suffix = match name_and_suffix.clone().get(1 as usize).cloned() {
let suffix = match name_and_suffix
.clone()
.iter()
.cloned()
.skip(1 as usize)
.next()
{
Some(s) => s.clone(),
None => {
return Rc::new(PathSegmentTokensResult::MalformedPathSegment {
Expand Down Expand Up @@ -439,8 +451,10 @@ pub fn uri_query_string(path: String) -> String {
.map(|s| s.to_string())
.collect::<Vec<_>>(),
)
.get(1 as usize)
.iter()
.cloned()
.skip(1 as usize)
.next()
{
Some(q) => q.clone(),
None => "".to_string(),
Expand Down Expand Up @@ -478,8 +492,10 @@ pub fn uri_query_param(path: String, key: String) -> String {
.map(|s| s.to_string())
.collect::<Vec<_>>(),
)
.get(1 as usize)
.iter()
.cloned()
.skip(1 as usize)
.next()
{
Some(x) => x.clone(),
None => "".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub fn first_or_empty(items: Rc<Vec<String>>) -> String {
}

pub fn second_or_empty(items: Rc<Vec<String>>) -> String {
match items.clone().get(1 as usize).cloned() {
match items.clone().iter().cloned().skip(1 as usize).next() {
Some(v) => v.clone(),
None => "".to_string(),
}
Expand Down
Loading
Loading