From c6d9c72714cfaf1552213fafb5df48edc3911abd Mon Sep 17 00:00:00 2001 From: Kevin Silmore Date: Mon, 8 Jun 2026 17:30:05 -0500 Subject: [PATCH 1/5] feat: add docstrings to generated rust code --- .gitignore | 2 + capnpc/src/codegen.rs | 147 +++++++++++++++++++++++++++++++++++------- 2 files changed, 125 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 49bdc4424..f2a77b70d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,5 @@ Cargo.lock /target/ +# IDEs +.idea diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index 761d78a19..e5ed0eba5 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -199,6 +199,8 @@ pub struct GeneratorContext<'a> { pub request: schema_capnp::code_generator_request::Reader<'a>, pub node_map: collections::hash_map::HashMap>, pub scope_map: collections::hash_map::HashMap>, + pub source_info_map: + collections::hash_map::HashMap>, /// Map from node ID to the node ID of its parent scope. This is equal to node.scope_id /// for all nodes except for autogenerated interface Param and Result structs; @@ -228,6 +230,10 @@ impl<'a> GeneratorContext<'a> { request: message.get_root()?, node_map: collections::hash_map::HashMap::>::new(), scope_map: collections::hash_map::HashMap::>::new(), + source_info_map: collections::hash_map::HashMap::< + u64, + schema_capnp::node::source_info::Reader<'a>, + >::new(), node_parents: collections::hash_map::HashMap::new(), capnp_root: code_generation_command.capnp_root.clone(), }; @@ -239,6 +245,13 @@ impl<'a> GeneratorContext<'a> { ctx.node_parents.insert(node.get_id(), node.get_scope_id()); } + if ctx.request.has_source_info() { + for source_info in ctx.request.get_source_info()? { + ctx.source_info_map + .insert(source_info.get_id(), source_info); + } + } + // Fix up "anonymous" method params and results scopes. for node in ctx.request.get_nodes()? { if let Ok(schema_capnp::node::Interface(interface_reader)) = node.which() { @@ -492,6 +505,57 @@ pub fn line(inner: impl ToString) -> FormattedText { Line(inner.to_string()) } +fn get_node_doc_comment(ctx: &GeneratorContext, node_id: u64) -> Option { + if let Some(source_info) = ctx.source_info_map.get(&node_id) { + if !source_info.has_doc_comment() { + return None; + } + if let Ok(comment) = source_info.get_doc_comment() { + if let Ok(comment_str) = comment.to_string() { + return Some(comment_str); + } + } + } + None +} + +fn get_member_doc_comment( + ctx: &GeneratorContext, + node_id: u64, + member_index: u32, +) -> Option { + if let Some(source_info) = ctx.source_info_map.get(&node_id) { + if !source_info.has_members() { + return None; + } + if let Ok(members) = source_info.get_members() { + if member_index >= members.len() { + return None; + } + let member = members.get(member_index); + if !member.has_doc_comment() { + return None; + } + if let Ok(comment) = member.get_doc_comment() { + if let Ok(comment_str) = comment.to_string() { + return Some(comment_str); + } + } + } + } + None +} + +fn generate_doc_comment(comment: Option) -> Vec { + let mut result = Vec::new(); + if let Some(comment_str) = comment { + for line_str in comment_str.lines() { + result.push(Line(format!("/// {}", line_str))); + } + } + result +} + fn to_lines(ft: &FormattedText, indent: usize) -> Vec { match ft { Indent(ft) => to_lines(ft, indent + 1), @@ -2021,6 +2085,11 @@ fn generate_node( let params = node_reader.parameters_texts(ctx); output.push(BlankLine); + let struct_doc_lines = generate_doc_comment(get_node_doc_comment(ctx, node_id)); + if !struct_doc_lines.is_empty() { + output.push(Branch(struct_doc_lines.clone())); + } + let is_generic = node_reader.get_is_generic(); if is_generic { output.push(Line(format!( @@ -2079,7 +2148,10 @@ fn generate_node( let mut has_pointer_field = false; let fields = struct_reader.get_fields()?; - for field in fields { + for (field_index, field) in fields.iter().enumerate() { + let field_doc_lines = + generate_doc_comment(get_member_doc_comment(ctx, node_id, field_index as u32)); + let name = get_field_name(field)?; let styled_name = camel_to_snake_case(name); @@ -2100,12 +2172,20 @@ fn generate_node( } if !is_union_field { - pipeline_impl_interior.push(generate_pipeline_getter(ctx, field)?); + let mut p_getter = generate_pipeline_getter(ctx, field)?; + if let Branch(ref mut p_vec) = p_getter { + if !p_vec.is_empty() { + p_vec.insert(0, Branch(field_doc_lines.clone())); + } + } + pipeline_impl_interior.push(p_getter); + let (ty, get, default_decl) = getter_text(ctx, &field, true, true)?; if let Some(default) = default_decl { private_mod_interior.push(default.clone()); } reader_members.push(Branch(vec![ + Branch(field_doc_lines.clone()), line("#[inline]"), Line(format!("pub fn get_{styled_name}(self) {ty} {{")), indent(get), @@ -2114,6 +2194,7 @@ fn generate_node( let (ty_b, get_b, _) = getter_text(ctx, &field, false, true)?; builder_members.push(Branch(vec![ + Branch(field_doc_lines.clone()), line("#[inline]"), Line(format!("pub fn get_{styled_name}(self) {ty_b} {{")), indent(get_b), @@ -2123,25 +2204,29 @@ fn generate_node( union_fields.push(field); } - builder_members.push(generate_setter( - ctx, - discriminant_offset, - &styled_name, - &field, - )?); - - reader_members.push(generate_haser( - discriminant_offset, - &styled_name, - &field, - true, - )?); - builder_members.push(generate_haser( - discriminant_offset, - &styled_name, - &field, - false, - )?); + let mut setter = generate_setter(ctx, discriminant_offset, &styled_name, &field)?; + if let Branch(ref mut s_vec) = setter { + if !s_vec.is_empty() { + s_vec.insert(0, Branch(field_doc_lines.clone())); + } + } + builder_members.push(setter); + + let mut r_haser = generate_haser(discriminant_offset, &styled_name, &field, true)?; + if let Branch(ref mut h_vec) = r_haser { + if !h_vec.is_empty() { + h_vec.insert(0, Branch(field_doc_lines.clone())); + } + } + reader_members.push(r_haser); + + let mut b_haser = generate_haser(discriminant_offset, &styled_name, &field, false)?; + if let Branch(ref mut h_vec) = b_haser { + if !h_vec.is_empty() { + h_vec.insert(0, Branch(field_doc_lines.clone())); + } + } + builder_members.push(b_haser); if let Ok(field::Group(group)) = field.which() { let id = group.get_type_id(); @@ -2207,6 +2292,7 @@ fn generate_node( Branch(preamble), (if !is_generic { Branch(vec![ + Branch(struct_doc_lines.clone()), Line("#[derive(Copy, Clone)]".into()), line("pub struct Owned(());"), Line(fmt!(ctx,"impl {capnp}::introspect::Introspect for Owned {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Struct({capnp}::introspect::RawBrandedStructSchema {{ generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }}).into() }} }}")), @@ -2216,6 +2302,7 @@ fn generate_node( ]) } else { Branch(vec![ + Branch(struct_doc_lines.clone()), Line("#[derive(Copy, Clone)]".into()), Line(format!("pub struct Owned<{}> {{", params.params)), indent(Line(params.phantom_data_type.clone())), @@ -2232,9 +2319,13 @@ fn generate_node( }), BlankLine, (if !is_generic { - Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}")) + Branch(vec![ + Branch(struct_doc_lines.clone()), + Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}")) + ]) } else { Branch(vec![ + Branch(struct_doc_lines.clone()), Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)), indent(vec![ Line(fmt!(ctx,"reader: {capnp}::private::layout::StructReader<'a>,")), @@ -2331,9 +2422,13 @@ fn generate_node( line("}"), BlankLine, (if !is_generic { - Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}")) + Branch(vec![ + Branch(struct_doc_lines.clone()), + Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}")) + ]) } else { Branch(vec![ + Branch(struct_doc_lines.clone()), Line(format!("pub struct Builder<'a,{}> {} {{", params.params, params.where_clause)), indent(vec![ @@ -2413,6 +2508,7 @@ fn generate_node( BlankLine, (if is_generic { Branch(vec![ + Branch(struct_doc_lines.clone()), Line(format!("pub struct Pipeline{bracketed_params} {{")), indent(vec![ Line(fmt!(ctx,"_typeless: {capnp}::any_pointer::Pipeline,")), @@ -2421,7 +2517,10 @@ fn generate_node( line("}") ]) } else { - Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}")) + Branch(vec![ + Branch(struct_doc_lines.clone()), + Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}")) + ]) }), Line(fmt!(ctx,"impl{bracketed_params} {capnp}::capability::FromTypelessPipeline for Pipeline{bracketed_params} {{")), indent(vec![ From bf4ceb6c941eac35f40178cc748c7b1b494d37d3 Mon Sep 17 00:00:00 2001 From: Kevin Silmore Date: Mon, 8 Jun 2026 18:22:51 -0500 Subject: [PATCH 2/5] added other comments --- capnpc/src/codegen.rs | 77 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 12 deletions(-) diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index e5ed0eba5..6da08b957 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -2079,6 +2079,12 @@ fn generate_node( match node_reader.which()? { node::File(()) => { + let file_doc_lines = get_node_doc_comment(ctx, node_id); + if let Some(comment_str) = file_doc_lines { + for line_str in comment_str.lines() { + output.push(Line(format!("//! {}", line_str))); + } + } output.push(Branch(nested_output)); } node::Struct(struct_reader) => { @@ -2550,10 +2556,17 @@ fn generate_node( let name_as_mod = module_name(last_name); output.push(BlankLine); + let enum_doc_lines = generate_doc_comment(get_node_doc_comment(ctx, node_id)); + let mut members = Vec::new(); let mut match_branches = Vec::new(); let enumerants = enum_reader.get_enumerants()?; for (ii, enumerant) in enumerants.into_iter().enumerate() { + let enumerant_doc_lines = generate_doc_comment(get_member_doc_comment(ctx, node_id, ii as u32)); + if !enumerant_doc_lines.is_empty() { + members.push(Branch(enumerant_doc_lines)); + } + let enumerant = capitalize_first_letter(get_enumerant_name(enumerant)?); members.push(Line(format!("{enumerant} = {ii},"))); match_branches.push(Line(format!( @@ -2565,13 +2578,17 @@ fn generate_node( "n => ::core::result::Result::Err({capnp}::NotInSchema(n))," ))); - output.push(Branch(vec![ - line("#[repr(u16)]"), - line("#[derive(Clone, Copy, Debug, PartialEq, Eq)]"), - Line(format!("pub enum {last_name} {{")), - indent(members), - line("}"), - ])); + let mut enum_declaration = vec![]; + if !enum_doc_lines.is_empty() { + enum_declaration.push(Branch(enum_doc_lines)); + } + enum_declaration.push(line("#[repr(u16)]")); + enum_declaration.push(line("#[derive(Clone, Copy, Debug, PartialEq, Eq)]")); + enum_declaration.push(Line(format!("pub enum {last_name} {{"))); + enum_declaration.push(indent(members)); + enum_declaration.push(line("}")); + + output.push(Branch(enum_declaration)); output.push(BlankLine); output.push(Branch(vec![ @@ -2648,6 +2665,8 @@ fn generate_node( let params = node_reader.parameters_texts(ctx); output.push(BlankLine); + let interface_doc_lines = generate_doc_comment(get_node_doc_comment(ctx, node_id)); + let is_generic = node_reader.get_is_generic(); let names = &ctx.scope_map[&node_id]; @@ -2704,6 +2723,8 @@ fn generate_node( param_type ))); + let method_doc_lines = generate_doc_comment(get_member_doc_comment(ctx, node_id, ordinal as u32)); + let result_id = method.get_result_struct_type(); if result_id != STREAM_RESULT_ID { dispatch_arms.push( @@ -2738,6 +2759,10 @@ fn generate_node( results_ty_params, result_type ))); + + if !method_doc_lines.is_empty() { + server_interior.push(Branch(method_doc_lines.clone())); + } server_interior.push( Line(fmt!(ctx, "fn {}(self: {capnp}::capability::Rc, _: {}Params<{}>, _: {}Results<{}>) -> impl ::core::future::Future> + 'static {{ ::core::future::ready(Err({capnp}::Error::unimplemented(\"method {}::Server::{} not implemented\".to_string()))) }}", @@ -2747,6 +2772,9 @@ fn generate_node( node_name, module_name(name) ))); + if !method_doc_lines.is_empty() { + client_impl_interior.push(Branch(method_doc_lines.clone())); + } client_impl_interior.push(Line(fmt!( ctx, "pub fn {}_request(&self) -> {capnp}::capability::Request<{},{}> {{", @@ -2767,6 +2795,9 @@ fn generate_node( module_name(name)))); + if !method_doc_lines.is_empty() { + server_interior.push(Branch(method_doc_lines.clone())); + } server_interior.push( Line(fmt!(ctx, "fn {}(self: {capnp}::capability::Rc, _: {}Params<{}>) -> impl ::core::future::Future> + 'static {{ ::core::future::ready(Err({capnp}::Error::unimplemented(\"method {}::Server::{} not implemented\".to_string()))) }}", @@ -2774,6 +2805,10 @@ fn generate_node( capitalize_first_letter(name), params_ty_params, node_name, module_name(name) ))); + + if !method_doc_lines.is_empty() { + client_impl_interior.push(Branch(method_doc_lines.clone())); + } client_impl_interior.push(Line(fmt!( ctx, "pub fn {}_request(&self) -> {capnp}::capability::StreamingRequest<{}> {{", @@ -2838,6 +2873,9 @@ fn generate_node( }; mod_interior.push(BlankLine); + if !interface_doc_lines.is_empty() { + mod_interior.push(Branch(interface_doc_lines.clone())); + } mod_interior.push(Line(format!("pub struct Client{bracketed_params} {{"))); mod_interior.push(indent(Line(fmt!( ctx, @@ -2951,6 +2989,9 @@ fn generate_node( line("}"), ])); + if !interface_doc_lines.is_empty() { + mod_interior.push(Branch(interface_doc_lines.clone())); + } mod_interior.push(Branch(vec![ Line(format!( "pub trait Server<{}> {} {} {{", @@ -3071,6 +3112,8 @@ fn generate_node( node::Const(c) => { let styled_name = snake_to_upper_case(ctx.get_last_name(node_id)?); + let const_doc_lines = generate_doc_comment(get_node_doc_comment(ctx, node_id)); + let typ = c.get_type()?; let formatted_text = match (typ.which()?, c.get_value()?.which()?) { (type_::Void(()), value::Void(())) => { @@ -3195,10 +3238,15 @@ fn generate_node( } }; + if !const_doc_lines.is_empty() { + output.push(Branch(const_doc_lines)); + } output.push(formatted_text); } node::Annotation(annotation_reader) => { + let annotation_doc_lines = generate_doc_comment(get_node_doc_comment(ctx, node_id)); + let is_generic = node_reader.get_is_generic(); let params = node_reader.parameters_texts(ctx); let last_name = ctx.get_last_name(node_id)?; @@ -3212,11 +3260,16 @@ fn generate_node( } else { interior.push(Line(fmt!(ctx,"pub fn get_type<{0}>() -> {capnp}::introspect::Type {1} {{ <{2} as {capnp}::introspect::Introspect>::introspect() }}", params.params, params.where_clause, ty.type_string(ctx, Leaf::Owned)?))); } - output.push(Branch(vec![ - Line(format!("pub mod {last_name} {{")), - indent(interior), - Line("}".into()), - ])); + + let mut annotation_module = vec![]; + if !annotation_doc_lines.is_empty() { + annotation_module.push(Branch(annotation_doc_lines)); + } + annotation_module.push(Line(format!("pub mod {last_name} {{"))); + annotation_module.push(indent(interior)); + annotation_module.push(Line("}".into())); + + output.push(Branch(annotation_module)); } } From f0b0f91849d9441f792c9f4822e2d08de1abd923 Mon Sep 17 00:00:00 2001 From: Kevin Silmore Date: Mon, 8 Jun 2026 18:57:54 -0500 Subject: [PATCH 3/5] fix file-level comments --- capnpc/src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index 6da08b957..7ec30dea4 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -2082,7 +2082,7 @@ fn generate_node( let file_doc_lines = get_node_doc_comment(ctx, node_id); if let Some(comment_str) = file_doc_lines { for line_str in comment_str.lines() { - output.push(Line(format!("//! {}", line_str))); + output.push(Line(format!("// {}", line_str))); } } output.push(Branch(nested_output)); From 22399f9ff63cbcb8b44d4ecc0912a5ba6366db0a Mon Sep 17 00:00:00 2001 From: Kevin Silmore Date: Tue, 16 Jun 2026 17:59:32 -0500 Subject: [PATCH 4/5] removed struct comments for Owned, Reader, Builder, and Pipeline --- capnpc/src/codegen.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index 7ec30dea4..f38e08d47 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -2298,7 +2298,6 @@ fn generate_node( Branch(preamble), (if !is_generic { Branch(vec![ - Branch(struct_doc_lines.clone()), Line("#[derive(Copy, Clone)]".into()), line("pub struct Owned(());"), Line(fmt!(ctx,"impl {capnp}::introspect::Introspect for Owned {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Struct({capnp}::introspect::RawBrandedStructSchema {{ generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }}).into() }} }}")), @@ -2308,7 +2307,6 @@ fn generate_node( ]) } else { Branch(vec![ - Branch(struct_doc_lines.clone()), Line("#[derive(Copy, Clone)]".into()), Line(format!("pub struct Owned<{}> {{", params.params)), indent(Line(params.phantom_data_type.clone())), @@ -2326,12 +2324,10 @@ fn generate_node( BlankLine, (if !is_generic { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}")) ]) } else { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)), indent(vec![ Line(fmt!(ctx,"reader: {capnp}::private::layout::StructReader<'a>,")), @@ -2429,12 +2425,10 @@ fn generate_node( BlankLine, (if !is_generic { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}")) ]) } else { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(format!("pub struct Builder<'a,{}> {} {{", params.params, params.where_clause)), indent(vec![ @@ -2514,7 +2508,6 @@ fn generate_node( BlankLine, (if is_generic { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(format!("pub struct Pipeline{bracketed_params} {{")), indent(vec![ Line(fmt!(ctx,"_typeless: {capnp}::any_pointer::Pipeline,")), @@ -2524,7 +2517,6 @@ fn generate_node( ]) } else { Branch(vec![ - Branch(struct_doc_lines.clone()), Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}")) ]) }), @@ -2562,7 +2554,8 @@ fn generate_node( let mut match_branches = Vec::new(); let enumerants = enum_reader.get_enumerants()?; for (ii, enumerant) in enumerants.into_iter().enumerate() { - let enumerant_doc_lines = generate_doc_comment(get_member_doc_comment(ctx, node_id, ii as u32)); + let enumerant_doc_lines = + generate_doc_comment(get_member_doc_comment(ctx, node_id, ii as u32)); if !enumerant_doc_lines.is_empty() { members.push(Branch(enumerant_doc_lines)); } @@ -2723,7 +2716,8 @@ fn generate_node( param_type ))); - let method_doc_lines = generate_doc_comment(get_member_doc_comment(ctx, node_id, ordinal as u32)); + let method_doc_lines = + generate_doc_comment(get_member_doc_comment(ctx, node_id, ordinal as u32)); let result_id = method.get_result_struct_type(); if result_id != STREAM_RESULT_ID { @@ -2805,7 +2799,7 @@ fn generate_node( capitalize_first_letter(name), params_ty_params, node_name, module_name(name) ))); - + if !method_doc_lines.is_empty() { client_impl_interior.push(Branch(method_doc_lines.clone())); } @@ -3260,7 +3254,7 @@ fn generate_node( } else { interior.push(Line(fmt!(ctx,"pub fn get_type<{0}>() -> {capnp}::introspect::Type {1} {{ <{2} as {capnp}::introspect::Introspect>::introspect() }}", params.params, params.where_clause, ty.type_string(ctx, Leaf::Owned)?))); } - + let mut annotation_module = vec![]; if !annotation_doc_lines.is_empty() { annotation_module.push(Branch(annotation_doc_lines)); From a396442d49a09f250898a6c2eb3ac1add79c5004 Mon Sep 17 00:00:00 2001 From: Kevin Silmore Date: Tue, 16 Jun 2026 18:04:20 -0500 Subject: [PATCH 5/5] removed unnecessary Branch statements --- capnpc/src/codegen.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index f38e08d47..2d19cee4b 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -2323,9 +2323,7 @@ fn generate_node( }), BlankLine, (if !is_generic { - Branch(vec![ - Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}")) - ]) + Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}")) } else { Branch(vec![ Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)), @@ -2424,9 +2422,7 @@ fn generate_node( line("}"), BlankLine, (if !is_generic { - Branch(vec![ - Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}")) - ]) + Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}")) } else { Branch(vec![ Line(format!("pub struct Builder<'a,{}> {} {{", @@ -2516,9 +2512,7 @@ fn generate_node( line("}") ]) } else { - Branch(vec![ - Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}")) - ]) + Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}")) }), Line(fmt!(ctx,"impl{bracketed_params} {capnp}::capability::FromTypelessPipeline for Pipeline{bracketed_params} {{")), indent(vec![