Skip to content

Commit 00287e8

Browse files
Clean up more structural impls
1 parent 13b4734 commit 00287e8

File tree

10 files changed

+398
-156
lines changed

10 files changed

+398
-156
lines changed

Diff for: compiler/rustc_macros/src/type_foldable.rs

+39-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
1414

1515
s.add_bounds(synstructure::AddBounds::Generics);
1616
s.bind_with(|_| synstructure::BindStyle::Move);
17-
let body_fold = s.each_variant(|vi| {
17+
let try_body_fold = s.each_variant(|vi| {
1818
let bindings = vi.bindings();
1919
vi.construct(|_, index| {
2020
let bind = &bindings[index];
@@ -44,14 +44,51 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m
4444
})
4545
});
4646

47+
let body_fold = s.each_variant(|vi| {
48+
let bindings = vi.bindings();
49+
vi.construct(|_, index| {
50+
let bind = &bindings[index];
51+
52+
let mut fixed = false;
53+
54+
// retain value of fields with #[type_foldable(identity)]
55+
bind.ast().attrs.iter().for_each(|x| {
56+
if !x.path().is_ident("type_foldable") {
57+
return;
58+
}
59+
let _ = x.parse_nested_meta(|nested| {
60+
if nested.path.is_ident("identity") {
61+
fixed = true;
62+
}
63+
Ok(())
64+
});
65+
});
66+
67+
if fixed {
68+
bind.to_token_stream()
69+
} else {
70+
quote! {
71+
::rustc_middle::ty::TypeFoldable::fold_with(#bind, __folder)
72+
}
73+
}
74+
})
75+
});
76+
4777
s.bound_impl(
4878
quote!(::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>),
4979
quote! {
5080
fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
5181
self,
5282
__folder: &mut __F
5383
) -> Result<Self, __F::Error> {
54-
Ok(match self { #body_fold })
84+
Ok(match self { #try_body_fold })
85+
}
86+
87+
fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(
88+
self,
89+
__folder: &mut __F
90+
) -> Self {
91+
match self { #body_fold }
5592
}
5693
},
5794
)

Diff for: compiler/rustc_middle/src/infer/canonical.rs

-9
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,6 @@ pub type CanonicalVarInfo<'tcx> = ir::CanonicalVarInfo<TyCtxt<'tcx>>;
3939
pub type CanonicalVarValues<'tcx> = ir::CanonicalVarValues<TyCtxt<'tcx>>;
4040
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
4141

42-
impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
43-
fn try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>(
44-
self,
45-
folder: &mut F,
46-
) -> Result<Self, F::Error> {
47-
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v))
48-
}
49-
}
50-
5142
/// When we canonicalize a value to form a query, we wind up replacing
5243
/// various parts of it with canonical variables. This struct stores
5344
/// those replaced bits to remember for when we process the query

Diff for: compiler/rustc_middle/src/mir/syntax.rs

+4
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,8 @@ pub enum TerminatorKind<'tcx> {
931931
asm_macro: InlineAsmMacro,
932932

933933
/// The template for the inline assembly, with placeholders.
934+
#[type_foldable(identity)]
935+
#[type_visitable(ignore)]
934936
template: &'tcx [InlineAsmTemplatePiece],
935937

936938
/// The operands for the inline assembly, as `Operand`s or `Place`s.
@@ -941,6 +943,8 @@ pub enum TerminatorKind<'tcx> {
941943

942944
/// Source spans for each line of the inline assembly code. These are
943945
/// used to map assembler errors back to the line in the source code.
946+
#[type_foldable(identity)]
947+
#[type_visitable(ignore)]
944948
line_spans: &'tcx [Span],
945949

946950
/// Valid targets for the inline assembly.

Diff for: compiler/rustc_middle/src/ty/generic_args.rs

+65-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use smallvec::SmallVec;
1717
use crate::ty::codec::{TyDecoder, TyEncoder};
1818
use crate::ty::{
1919
self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs,
20-
Lift, List, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, VisitorResult,
20+
Lift, List, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, VisitorResult,
2121
walk_visitable_list,
2222
};
2323

@@ -337,6 +337,14 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
337337
GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
338338
}
339339
}
340+
341+
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
342+
match self.unpack() {
343+
GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(),
344+
GenericArgKind::Type(ty) => ty.fold_with(folder).into(),
345+
GenericArgKind::Const(ct) => ct.fold_with(folder).into(),
346+
}
347+
}
340348
}
341349

342350
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
@@ -606,6 +614,32 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> {
606614
}
607615
}
608616
0 => Ok(self),
617+
_ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
618+
}
619+
}
620+
621+
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
622+
// This code is hot enough that it's worth specializing for the most
623+
// common length lists, to avoid the overhead of `SmallVec` creation.
624+
// The match arms are in order of frequency. The 1, 2, and 0 cases are
625+
// typically hit in 90--99.99% of cases. When folding doesn't change
626+
// the args, it's faster to reuse the existing args rather than
627+
// calling `mk_args`.
628+
match self.len() {
629+
1 => {
630+
let param0 = self[0].fold_with(folder);
631+
if param0 == self[0] { self } else { folder.cx().mk_args(&[param0]) }
632+
}
633+
2 => {
634+
let param0 = self[0].fold_with(folder);
635+
let param1 = self[1].fold_with(folder);
636+
if param0 == self[0] && param1 == self[1] {
637+
self
638+
} else {
639+
folder.cx().mk_args(&[param0, param1])
640+
}
641+
}
642+
0 => self,
609643
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
610644
}
611645
}
@@ -641,6 +675,36 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
641675
Ok(folder.cx().mk_type_list(&[param0, param1]))
642676
}
643677
}
678+
_ => ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
679+
}
680+
}
681+
682+
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
683+
// This code is fairly hot, though not as hot as `GenericArgsRef`.
684+
//
685+
// When compiling stage 2, I get the following results:
686+
//
687+
// len | total | %
688+
// --- | --------- | -----
689+
// 2 | 15083590 | 48.1
690+
// 3 | 7540067 | 24.0
691+
// 1 | 5300377 | 16.9
692+
// 4 | 1351897 | 4.3
693+
// 0 | 1256849 | 4.0
694+
//
695+
// I've tried it with some private repositories and got
696+
// close to the same result, with 4 and 0 swapping places
697+
// sometimes.
698+
match self.len() {
699+
2 => {
700+
let param0 = self[0].fold_with(folder);
701+
let param1 = self[1].fold_with(folder);
702+
if param0 == self[0] && param1 == self[1] {
703+
self
704+
} else {
705+
folder.cx().mk_type_list(&[param0, param1])
706+
}
707+
}
644708
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
645709
}
646710
}

Diff for: compiler/rustc_middle/src/ty/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,13 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Term<'tcx> {
537537
ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
538538
}
539539
}
540+
541+
fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
542+
match self.unpack() {
543+
ty::TermKind::Ty(ty) => ty.fold_with(folder).into(),
544+
ty::TermKind::Const(ct) => ct.fold_with(folder).into(),
545+
}
546+
}
540547
}
541548

542549
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> {

0 commit comments

Comments
 (0)