Skip to content

Commit 4c24faf

Browse files
committed
Auto merge of rust-lang#124263 - eggyal:tco-derived-visits, r=<try>
Prefer not to early return from derived visitables LLVM is not able to tail-call optimise the final early return, as there instructions that follow it. Making that call the returned expression resolves this. (As identified in rust-lang#117896 (comment)). r? wg-compiler-performance
2 parents 7f2fc33 + 1fa6e5b commit 4c24faf

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

compiler/rustc_macros/src/type_visitable.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,29 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
3232
}
3333

3434
s.add_bounds(synstructure::AddBounds::Generics);
35-
let body_visit = s.each(|bind| {
36-
quote! {
37-
match ::rustc_ast_ir::visit::VisitorResult::branch(
38-
::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
39-
) {
40-
::core::ops::ControlFlow::Continue(()) => {},
41-
::core::ops::ControlFlow::Break(r) => {
42-
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
43-
},
35+
let body_visit =
36+
s.each_variant(|vi| {
37+
if let Some((last, rest)) = vi.bindings().split_last() {
38+
// Avoid early returning after visiting the final binding, so that LLVM can TCO the call.
39+
rest.iter()
40+
.map(|bind| quote! {
41+
match ::rustc_ast_ir::visit::VisitorResult::branch(
42+
::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)
43+
) {
44+
::core::ops::ControlFlow::Continue(()) => {},
45+
::core::ops::ControlFlow::Break(r) => {
46+
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
47+
},
48+
}
49+
})
50+
.chain(std::iter::once(quote! {
51+
::rustc_middle::ty::visit::TypeVisitable::visit_with(#last, __visitor)
52+
}))
53+
.collect()
54+
} else {
55+
quote! { <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() }
4456
}
45-
}
46-
});
57+
});
4758
s.bind_with(|_| synstructure::BindStyle::Move);
4859

4960
s.bound_impl(
@@ -54,7 +65,6 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
5465
__visitor: &mut __V
5566
) -> __V::Result {
5667
match *self { #body_visit }
57-
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
5868
}
5969
},
6070
)

0 commit comments

Comments
 (0)