Skip to content

Commit 1dceddf

Browse files
committed
Factor signature type walking out of opaque_types_defined_by
1 parent 2712b3f commit 1dceddf

File tree

4 files changed

+147
-25
lines changed

4 files changed

+147
-25
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,6 +3777,7 @@ impl<'hir> Node<'hir> {
37773777
ItemKind::TyAlias(ty, _)
37783778
| ItemKind::Static(ty, _, _)
37793779
| ItemKind::Const(ty, _, _) => Some(ty),
3780+
ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
37803781
_ => None,
37813782
},
37823783
Node::TraitItem(it) => match it.kind {

compiler/rustc_ty_utils/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
77
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
88
#![feature(assert_matches)]
9+
#![feature(associated_type_defaults)]
910
#![feature(iterator_try_collect)]
1011
#![feature(let_chains)]
1112
#![feature(if_let_guard)]
@@ -36,6 +37,7 @@ mod layout_sanity_check;
3637
mod needs_drop;
3738
mod opaque_types;
3839
pub mod representability;
40+
pub mod sig_types;
3941
mod structural_match;
4042
mod ty;
4143

compiler/rustc_ty_utils/src/opaque_types.rs

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,10 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
5353

5454
fn parent(&self) -> Option<LocalDefId> {
5555
match self.tcx.def_kind(self.item) {
56-
DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias { .. } => {
57-
None
58-
}
5956
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
6057
Some(self.tcx.local_parent(self.item))
6158
}
62-
other => span_bug!(
63-
self.tcx.def_span(self.item),
64-
"unhandled item with opaque types: {other:?}"
65-
),
59+
_ => None,
6660
}
6761
}
6862

@@ -134,6 +128,13 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
134128
}
135129
}
136130

131+
impl<'tcx> super::sig_types::Spanned<'tcx> for OpaqueTypeCollector<'tcx> {
132+
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
133+
self.visit_spanned(span, value);
134+
ControlFlow::Continue(())
135+
}
136+
}
137+
137138
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
138139
#[instrument(skip(self), ret, level = "trace")]
139140
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
@@ -275,25 +276,14 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
275276
let kind = tcx.def_kind(item);
276277
trace!(?kind);
277278
let mut collector = OpaqueTypeCollector::new(tcx, item);
279+
super::sig_types::walk_types(tcx, item, &mut collector);
278280
match kind {
279-
// Walk over the signature of the function-like to find the opaques.
280-
DefKind::AssocFn | DefKind::Fn => {
281-
let ty_sig = tcx.fn_sig(item).instantiate_identity();
282-
let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
283-
// Walk over the inputs and outputs manually in order to get good spans for them.
284-
collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
285-
for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
286-
collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
287-
}
288-
collector.collect_body_and_predicate_taits();
289-
}
290-
// Walk over the type of the item to find opaques.
291-
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
292-
let span = match tcx.hir().get_by_def_id(item).ty() {
293-
Some(ty) => ty.span,
294-
_ => tcx.def_span(item),
295-
};
296-
collector.visit_spanned(span, tcx.type_of(item).instantiate_identity());
281+
DefKind::AssocFn
282+
| DefKind::Fn
283+
| DefKind::Static(_)
284+
| DefKind::Const
285+
| DefKind::AssocConst
286+
| DefKind::AnonConst => {
297287
collector.collect_body_and_predicate_taits();
298288
}
299289
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//! This module contains helpers for walking all types of
2+
//! a signature, while preserving spans as much as possible
3+
4+
use std::ops::ControlFlow;
5+
6+
use rustc_hir::{def::DefKind, def_id::LocalDefId};
7+
use rustc_middle::ty::{self, TyCtxt};
8+
use rustc_span::Span;
9+
use rustc_type_ir::visit::TypeVisitable;
10+
11+
pub trait Spanned<'tcx> {
12+
type BreakTy = !;
13+
fn visit(
14+
&mut self,
15+
span: Span,
16+
value: impl TypeVisitable<TyCtxt<'tcx>>,
17+
) -> ControlFlow<Self::BreakTy>;
18+
}
19+
20+
pub fn walk_types<'tcx, V: Spanned<'tcx>>(
21+
tcx: TyCtxt<'tcx>,
22+
item: LocalDefId,
23+
visitor: &mut V,
24+
) -> ControlFlow<V::BreakTy> {
25+
let kind = tcx.def_kind(item);
26+
trace!(?kind);
27+
match kind {
28+
DefKind::Generator => {
29+
match tcx.type_of(item).instantiate_identity().kind() {
30+
ty::Generator(_, args, _) => visitor.visit(tcx.def_span(item), args.as_generator().sig())?,
31+
_ => bug!(),
32+
}
33+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
34+
visitor.visit(span, pred)?;
35+
}
36+
}
37+
// Walk over the signature of the function-like to find the opaques.
38+
DefKind::Closure | DefKind::AssocFn | DefKind::Fn => {
39+
let ty_sig = match kind {
40+
DefKind::Closure => match tcx.type_of(item).instantiate_identity().kind() {
41+
ty::Closure(_, args) => args.as_closure().sig(),
42+
_ => bug!(),
43+
},
44+
_ => tcx.fn_sig(item).instantiate_identity(),
45+
};
46+
let hir_sig = tcx.hir().get_by_def_id(item).fn_decl().unwrap();
47+
// Walk over the inputs and outputs manually in order to get good spans for them.
48+
visitor.visit(hir_sig.output.span(), ty_sig.output());
49+
for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) {
50+
visitor.visit(hir.span, ty.map_bound(|x| *x))?;
51+
}
52+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
53+
visitor.visit(span, pred)?;
54+
}
55+
}
56+
// Walk over the type behind the alias
57+
DefKind::TyAlias {..} | DefKind::AssocTy |
58+
// Walk over the type of the item to find opaques.
59+
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
60+
let span = match tcx.hir().get_by_def_id(item).ty() {
61+
Some(ty) => ty.span,
62+
_ => tcx.def_span(item),
63+
};
64+
visitor.visit(span, tcx.type_of(item).instantiate_identity());
65+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
66+
visitor.visit(span, pred)?;
67+
}
68+
}
69+
DefKind::OpaqueTy => {
70+
for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
71+
visitor.visit(span, pred)?;
72+
}
73+
}
74+
// Look at field types
75+
DefKind::Struct | DefKind::Union | DefKind::Enum => {
76+
let span = tcx.def_ident_span(item).unwrap();
77+
visitor.visit(span, tcx.type_of(item).instantiate_identity());
78+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
79+
visitor.visit(span, pred)?;
80+
}
81+
}
82+
// Does not have a syntactical signature
83+
DefKind::InlineConst => {}
84+
DefKind::Impl { of_trait } => {
85+
if of_trait {
86+
let span = tcx.hir().get_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span;
87+
let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..];
88+
visitor.visit(span, args)?;
89+
}
90+
let span = match tcx.hir().get_by_def_id(item).ty() {
91+
Some(ty) => ty.span,
92+
_ => tcx.def_span(item),
93+
};
94+
visitor.visit(span, tcx.type_of(item).instantiate_identity());
95+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
96+
visitor.visit(span, pred)?;
97+
}}
98+
DefKind::Trait => {
99+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
100+
visitor.visit(span, pred)?;
101+
}
102+
}
103+
DefKind::TraitAlias => {
104+
for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) {
105+
visitor.visit(span, pred)?;
106+
}
107+
}
108+
| DefKind::Variant
109+
| DefKind::ForeignTy
110+
| DefKind::TyParam
111+
| DefKind::ConstParam
112+
| DefKind::Ctor(_, _)
113+
| DefKind::Field
114+
| DefKind::LifetimeParam => {
115+
span_bug!(
116+
tcx.def_span(item),
117+
"{kind:?} has not seen any uses of `walk_types` yet, ping oli-obk if you'd like any help"
118+
)
119+
}
120+
// These don't have any types.
121+
| DefKind::ExternCrate
122+
| DefKind::ForeignMod
123+
| DefKind::Macro(_)
124+
| DefKind::GlobalAsm
125+
| DefKind::Mod
126+
| DefKind::Use => {}
127+
}
128+
ControlFlow::Continue(())
129+
}

0 commit comments

Comments
 (0)