@@ -8,9 +8,13 @@ use rustc_middle::ty::{self, TyCtxt};
8
8
use rustc_span::Span;
9
9
use rustc_type_ir::visit::TypeVisitable;
10
10
11
- pub trait SpannedTypeVisitor<'tcx> {
11
+ pub trait SpannedTypeVisitor<'tcx>: Sized {
12
12
type Result: VisitorResult = ();
13
- fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result;
13
+ fn visit(
14
+ &mut self,
15
+ get_span: impl Fn() -> Span,
16
+ value: impl TypeVisitable<TyCtxt<'tcx>>,
17
+ ) -> Self::Result;
14
18
}
15
19
16
20
pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
@@ -24,48 +28,61 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
24
28
// Walk over the signature of the function
25
29
DefKind::AssocFn | DefKind::Fn => {
26
30
let ty_sig = tcx.fn_sig(item).instantiate_identity();
27
- let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap();
31
+ let hir_sig = || tcx.hir_node_by_def_id(item).fn_decl().unwrap();
28
32
// Walk over the inputs and outputs manually in order to get good spans for them.
29
- try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output()));
30
- for (hir, ty) in hir_sig.inputs.iter().zip( ty_sig.inputs().iter()) {
31
- try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x)));
33
+ try_visit!(visitor.visit(|| hir_sig() .output.span(), ty_sig.output()));
34
+ for (hir, ty) in ty_sig.inputs().iter().enumerate( ) {
35
+ try_visit!(visitor.visit(|| hir_sig().inputs[ hir] .span, ty.map_bound(|x| *x)));
32
36
}
33
37
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
34
- try_visit!(visitor.visit(span, pred));
38
+ try_visit!(visitor.visit(|| span, pred));
35
39
}
36
40
}
37
- // Walk over the type behind the alias
38
- DefKind::TyAlias {..} | DefKind::AssocTy |
39
- // Walk over the type of the item
40
- DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
41
+ DefKind::AssocTy => {
41
42
if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
42
43
// Associated types in traits don't necessarily have a type that we can visit
43
- try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity()));
44
+ try_visit!(visitor.visit(|| ty.span, tcx.type_of(item).instantiate_identity()));
45
+ }
46
+ for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
47
+ try_visit!(visitor.visit(|| span, pred));
48
+ }
49
+ }
50
+ // Walk over the type behind the alias
51
+ DefKind::TyAlias { .. } |
52
+ // Walk over the type of the item
53
+ DefKind::Static(_) | DefKind::Const | DefKind::AssocConst => {
54
+ let span = || tcx.hir_node_by_def_id(item).ty().unwrap().span;
55
+ try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity()));
56
+
57
+ for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
58
+ try_visit!(visitor.visit(|| span, pred));
44
59
}
60
+ }
61
+ DefKind::AnonConst => {
45
62
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
46
- try_visit!(visitor.visit(span, pred));
63
+ try_visit!(visitor.visit(|| span, pred));
47
64
}
48
65
}
49
66
DefKind::OpaqueTy => {
50
67
for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
51
- try_visit!(visitor.visit(span, pred));
68
+ try_visit!(visitor.visit(|| span, pred));
52
69
}
53
70
}
54
71
// Look at field types
55
72
DefKind::Struct | DefKind::Union | DefKind::Enum => {
56
- let span = tcx.def_ident_span(item).unwrap();
73
+ let span = || tcx.def_ident_span(item).unwrap();
57
74
let ty = tcx.type_of(item).instantiate_identity();
58
75
try_visit!(visitor.visit(span, ty));
59
76
let ty::Adt(def, args) = ty.kind() else {
60
- span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind())
77
+ span_bug!(span() , "invalid type for {kind:?}: {:#?}", ty.kind())
61
78
};
62
79
for field in def.all_fields() {
63
- let span = tcx.def_ident_span(field.did).unwrap();
80
+ let span = || tcx.def_ident_span(field.did).unwrap();
64
81
let ty = field.ty(tcx, args);
65
82
try_visit!(visitor.visit(span, ty));
66
83
}
67
84
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
68
- try_visit!(visitor.visit(span, pred));
85
+ try_visit!(visitor.visit(|| span, pred));
69
86
}
70
87
}
71
88
// These are not part of a public API, they can only appear as hidden types, and there
@@ -74,25 +91,33 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
74
91
DefKind::InlineConst | DefKind::Closure => {}
75
92
DefKind::Impl { of_trait } => {
76
93
if of_trait {
77
- let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
94
+ let span = || {
95
+ tcx.hir_node_by_def_id(item)
96
+ .expect_item()
97
+ .expect_impl()
98
+ .of_trait
99
+ .unwrap()
100
+ .path
101
+ .span
102
+ };
78
103
let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..];
79
104
try_visit!(visitor.visit(span, args));
80
105
}
81
- let span = match tcx.hir_node_by_def_id(item).ty() {
106
+ let span = || match tcx.hir_node_by_def_id(item).ty() {
82
107
Some(ty) => ty.span,
83
108
_ => tcx.def_span(item),
84
109
};
85
110
try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity()));
86
111
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
87
- try_visit!(visitor.visit(span, pred));
112
+ try_visit!(visitor.visit(|| span, pred));
88
113
}
89
114
}
90
115
DefKind::TraitAlias | DefKind::Trait => {
91
116
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
92
- try_visit!(visitor.visit(span, pred));
117
+ try_visit!(visitor.visit(|| span, pred));
93
118
}
94
119
}
95
- | DefKind::Variant
120
+ DefKind::Variant
96
121
| DefKind::TyParam
97
122
| DefKind::ConstParam
98
123
| DefKind::Ctor(_, _)
@@ -104,7 +129,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
104
129
)
105
130
}
106
131
// These don't have any types.
107
- | DefKind::ExternCrate
132
+ DefKind::ExternCrate
108
133
| DefKind::ForeignMod
109
134
| DefKind::ForeignTy
110
135
| DefKind::Macro(_)
0 commit comments