Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 13 additions & 9 deletions src/v1/05_emit_rust.dag
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,14 @@ fn render_rust_shared_type_if_needed(type_name: String, rendered: String, shared
} else { rendered }
}

fn render_rust_shared_type_with_optional(n: Node, type_name: String, rendered: String, shared_types: Set<String>) -> String {
rust_carrier_optional_wrap(n: n, rendered: render_rust_shared_type_if_needed(type_name: type_name, rendered: rendered, shared_types: shared_types))
}

fn render_rust_applied_type_shared(n: Node, generic_param_names: List<String>, shared_types: Set<String>, corpus_repr: RustCorpusRepr, source_indices: Map<String, NewlineIndex>, variant_to_enum: Map<String, String>, env: TypeEnv) -> String {
let rendered = render_rust_applied_type(n: n, 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 type_name = authored_name_at(source_indices: source_indices, node: n)
render_rust_shared_type_if_needed(type_name: type_name, rendered: rendered, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: type_name, rendered: rendered, shared_types: shared_types)
}

fn render_rust_decl_type(n: Node, generic_param_names: List<String>, shared_types: Set<String>, corpus_repr: RustCorpusRepr, source_indices: Map<String, NewlineIndex>, variant_to_enum: Map<String, String>, env: TypeEnv) -> String {
Expand All @@ -535,10 +539,10 @@ fn render_rust_decl_type(n: Node, generic_param_names: List<String>, shared_type
rust_carrier_optional_wrap(n: n, rendered: render_rust_text_carrier(shared_types: shared_types))
} else if n.connective == NoConnective && n.children |> count == 0 && applied_prop == none && set_contains(shared_types, name) {
let rendered = rust_render_type_leaf_name(name: name, variant_to_enum: variant_to_enum)
render_rust_shared_type_if_needed(type_name: name, rendered: rendered, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: name, rendered: rendered, shared_types: shared_types)
} else if n.connective == NoConnective && n.children |> count > 0 {
if !is_container_type(name: name) && rust_fn_sig_peel_closed_alias(env: env, n: n) {
render_rust_shared_type_if_needed(type_name: name, rendered: name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: name, rendered: name, shared_types: shared_types)
} else {
let base = rust_applied_type_base(name: name, corpus_repr: corpus_repr)
let peel = is_parametric_opaque_type_by_name(env: env, type_name: name)
Expand Down Expand Up @@ -569,7 +573,7 @@ fn render_rust_decl_type(n: Node, generic_param_names: List<String>, shared_type
} else {
concat(base, "<", arg_list |> join(separator: ", "), ">")
}
render_rust_shared_type_if_needed(type_name: name, rendered: applied_ty, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: name, rendered: applied_ty, shared_types: shared_types)
}
} else {
render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices)
Expand Down Expand Up @@ -622,9 +626,9 @@ fn render_rust_fn_sig_type(n: Node, generic_param_names: List<String>, shared_ty
if n.connective == NoConnective && n.children |> count == 0 && name == "String" && corpus_repr_is_faithful(corpus_repr: corpus_repr) {
rust_carrier_optional_wrap(n: n, rendered: render_rust_text_carrier(shared_types: shared_types))
} else if n.connective == NoConnective && n.children |> count == 0 && name != "" && name != "String" && !is_container_type(name: name) && rust_fn_sig_peel_closed_alias(env: env, n: n) && rust_fn_sig_preserves_authored_alias_leaf(name: name, corpus_repr: corpus_repr) {
render_rust_shared_type_if_needed(type_name: name, rendered: name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: name, rendered: name, shared_types: shared_types)
} else if n.connective == NoConnective && n.children |> count > 0 && !is_container_type(name: name) && rust_fn_sig_peel_closed_alias(env: env, n: n) {
render_rust_shared_type_if_needed(type_name: name, rendered: name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: name, rendered: name, shared_types: shared_types)
} else if generic_param_names |> count > 0 {
render_rust_decl_type(n: n, 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 {
Expand All @@ -638,7 +642,7 @@ fn render_rust_fn_sig_type_applied_binding(n: Node, shared_types: Set<String>, c
if applied.children |> count > 0 {
let outer_name = authored_name_at(source_indices: source_indices, node: n)
if outer_name != "" && n.connective == NoConnective && (n.children |> count) == 0 && rust_fn_sig_peel_closed_alias(env: env, n: n) && rust_fn_sig_preserves_authored_alias_leaf(name: outer_name, corpus_repr: corpus_repr) {
render_rust_shared_type_if_needed(type_name: outer_name, rendered: outer_name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: outer_name, rendered: outer_name, shared_types: shared_types)
} else {
render_rust_type_with_applied_binding(n: n, shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices)
}
Expand Down Expand Up @@ -3391,9 +3395,9 @@ fn render_rust_type_with_applied_binding(n: Node, shared_types: Set<String>, cor
let applied_name = authored_name_at(source_indices: source_indices, node: applied)
if outer_name != "" && n.connective == NoConnective && (n.children |> count) == 0 {
if outer_name != applied_name {
render_rust_shared_type_if_needed(type_name: outer_name, rendered: outer_name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: outer_name, rendered: outer_name, shared_types: shared_types)
} else if set_contains(shared_types, outer_name) {
render_rust_shared_type_if_needed(type_name: outer_name, rendered: outer_name, shared_types: shared_types)
render_rust_shared_type_with_optional(n: n, type_name: outer_name, rendered: outer_name, shared_types: shared_types)
} else {
render_rust_applied_type_shared(n: applied, generic_param_names: [], shared_types: shared_types, corpus_repr: corpus_repr, source_indices: source_indices, variant_to_enum: empty_map(), env: TypeEnv { bindings: empty_map(), str_bindings: empty_map(), ancestry_str_bindings: empty_map(), parents: [], recursive_types: [], recursive_type_set: empty_map(), inductive_fields: empty_map(), source_indices: source_indices, intern_table: empty_intern_table() })
}
Expand Down
46 changes: 37 additions & 9 deletions src/v1/stage0/src/v1_compiler_emit_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,18 @@ pub fn render_rust_shared_type_if_needed(
}
}

pub fn render_rust_shared_type_with_optional(
n: Rc<Node>,
type_name: String,
rendered: String,
shared_types: Rc<std::collections::BTreeSet<String>>,
) -> String {
rust_carrier_optional_wrap(
n.clone(),
render_rust_shared_type_if_needed(type_name, rendered, shared_types),
)
}

pub fn render_rust_applied_type_shared(
n: Rc<Node>,
generic_param_names: Rc<Vec<String>>,
Expand All @@ -912,7 +924,7 @@ pub fn render_rust_applied_type_shared(
env,
);
let type_name = authored_name_at(source_indices.clone(), n.clone());
render_rust_shared_type_if_needed(type_name, rendered, shared_types.clone())
render_rust_shared_type_with_optional(n.clone(), type_name, rendered, shared_types.clone())
}
}

Expand Down Expand Up @@ -992,7 +1004,8 @@ pub fn render_rust_decl_type(
name.clone(),
variant_to_enum.clone(),
);
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
name.clone(),
rendered,
shared_types.clone(),
Expand All @@ -1005,7 +1018,8 @@ pub fn render_rust_decl_type(
if (!is_container_type(name.clone())
&& rust_fn_sig_peel_closed_alias(env.clone(), n.clone()))
{
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
name.clone(),
name.clone(),
shared_types.clone(),
Expand Down Expand Up @@ -1135,7 +1149,8 @@ pub fn render_rust_decl_type(
}
}
};
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
name.clone(),
applied_ty,
shared_types.clone(),
Expand Down Expand Up @@ -1249,13 +1264,23 @@ pub fn render_rust_fn_sig_type(
&& rust_fn_sig_peel_closed_alias(env.clone(), n.clone())
&& rust_fn_sig_preserves_authored_alias_leaf(name.clone(), corpus_repr.clone())
{
render_rust_shared_type_if_needed(name.clone(), name.clone(), shared_types.clone())
render_rust_shared_type_with_optional(
n.clone(),
name.clone(),
name.clone(),
shared_types.clone(),
)
} else if (n.connective.clone() == Connective::NoConnective)
&& ((n.children.clone().len() as i64) > 0)
&& !is_container_type(name.clone())
&& rust_fn_sig_peel_closed_alias(env.clone(), n.clone())
{
render_rust_shared_type_if_needed(name.clone(), name.clone(), shared_types.clone())
render_rust_shared_type_with_optional(
n.clone(),
name.clone(),
name.clone(),
shared_types.clone(),
)
} else if ((generic_param_names.clone().len() as i64) > 0) {
render_rust_decl_type(
n.clone(),
Expand Down Expand Up @@ -1303,7 +1328,8 @@ pub fn render_rust_fn_sig_type_applied_binding(
corpus_repr.clone(),
)
{
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
outer_name.clone(),
outer_name.clone(),
shared_types,
Expand Down Expand Up @@ -8173,14 +8199,16 @@ pub fn render_rust_type_with_applied_binding(
&& ((n.children.clone().len() as i64) == 0))
{
if (outer_name.clone() != applied_name) {
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
outer_name.clone(),
outer_name.clone(),
shared_types.clone(),
)
} else {
if v1_rt::set_contains(&shared_types, outer_name.clone()) {
render_rust_shared_type_if_needed(
render_rust_shared_type_with_optional(
n.clone(),
outer_name.clone(),
outer_name.clone(),
shared_types.clone(),
Expand Down
23 changes: 23 additions & 0 deletions src/v1/tests/src/optional_carrier_signature_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,26 @@ fn non_optional_string_return_stays_bare() {
"a non-optional `-> String` must NOT be wrapped in Option, got:\n{sig}"
);
}

#[test]
fn optional_shared_type_return_renders_option_rc_signature() {
// Recursive struct so `Node` is in `shared_types` and fn-sig emission applies Rc.
let source = "module optsig.fixture\n\ntype Node = Product { child: Node? }\n\nfn maybe_node(flag: Bool) -> Node? {\n if flag { Present { value: Node { child: none } } } else { none }\n}\n";
let emitted = emit(source);
let sig = return_sig(&emitted, "maybe_node");
assert!(
sig.contains("Option<") && sig.contains("Rc<"),
"a `-> Node?` return on a shared type must render `Option<Rc<..>>`, got:\n{sig}"
);
}

#[test]
fn non_optional_shared_type_return_stays_bare_rc() {
let source = "module optsig.fixture\n\ntype Node = Product { child: Node? }\n\nfn always_node(_flag: Bool) -> Node {\n Node { child: none }\n}\n";
let emitted = emit(source);
let sig = return_sig(&emitted, "always_node");
assert!(
sig.contains("Rc<") && !sig.contains("Option<"),
"a non-optional `-> Node` must render bare `Rc<..>` without Option, got:\n{sig}"
);
}
Loading