Skip to content

Commit c2ef351

Browse files
committed
Auto merge of #117076 - oli-obk:privacy_visitor_types, r=petrochenkov
Refactor type visitor walking r? `@petrochenkov` pulling out the uncontroversial parts of #113671
2 parents c716f18 + 3121576 commit c2ef351

File tree

10 files changed

+191
-81
lines changed

10 files changed

+191
-81
lines changed

compiler/rustc_hir/src/hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3781,6 +3781,7 @@ impl<'hir> Node<'hir> {
37813781
ItemKind::TyAlias(ty, _)
37823782
| ItemKind::Static(ty, _, _)
37833783
| ItemKind::Const(ty, _, _) => Some(ty),
3784+
ItemKind::Impl(impl_item) => Some(&impl_item.self_ty),
37843785
_ => None,
37853786
},
37863787
Node::TraitItem(it) => match it.kind {

compiler/rustc_privacy/src/lib.rs

+7-17
Original file line numberDiff line numberDiff line change
@@ -210,22 +210,7 @@ where
210210
}
211211
}
212212
}
213-
ty::Alias(ty::Weak, alias) => {
214-
self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty);
215-
}
216-
ty::Alias(ty::Projection, proj) => {
217-
if V::SKIP_ASSOC_TYS {
218-
// Visitors searching for minimal visibility/reachability want to
219-
// conservatively approximate associated types like `<Type as Trait>::Alias`
220-
// as visible/reachable even if both `Type` and `Trait` are private.
221-
// Ideally, associated types should be substituted in the same way as
222-
// free type aliases, but this isn't done yet.
223-
return ControlFlow::Continue(());
224-
}
225-
// This will also visit args if necessary, so we don't need to recurse.
226-
return self.visit_projection_ty(proj);
227-
}
228-
ty::Alias(ty::Inherent, data) => {
213+
ty::Alias(kind @ (ty::Inherent | ty::Weak | ty::Projection), data) => {
229214
if V::SKIP_ASSOC_TYS {
230215
// Visitors searching for minimal visibility/reachability want to
231216
// conservatively approximate associated types like `Type::Alias`
@@ -235,9 +220,14 @@ where
235220
return ControlFlow::Continue(());
236221
}
237222

223+
let kind = match kind {
224+
ty::Inherent | ty::Projection => "associated type",
225+
ty::Weak => "type alias",
226+
ty::Opaque => unreachable!(),
227+
};
238228
self.def_id_visitor.visit_def_id(
239229
data.def_id,
240-
"associated type",
230+
kind,
241231
&LazyDefPathStr { def_id: data.def_id, tcx },
242232
)?;
243233

compiler/rustc_trait_selection/src/traits/project.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
898898
if debruijn.as_usize() + 1
899899
> self.current_index.as_usize() + self.universe_indices.len() =>
900900
{
901-
bug!("Bound vars outside of `self.universe_indices`");
901+
bug!(
902+
"Bound vars {r:#?} outside of `self.universe_indices`: {:#?}",
903+
self.universe_indices
904+
);
902905
}
903906
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
904907
let universe = self.universe_for(debruijn);
@@ -916,7 +919,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
916919
if debruijn.as_usize() + 1
917920
> self.current_index.as_usize() + self.universe_indices.len() =>
918921
{
919-
bug!("Bound vars outside of `self.universe_indices`");
922+
bug!(
923+
"Bound vars {t:#?} outside of `self.universe_indices`: {:#?}",
924+
self.universe_indices
925+
);
920926
}
921927
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
922928
let universe = self.universe_for(debruijn);
@@ -935,7 +941,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
935941
if debruijn.as_usize() + 1
936942
> self.current_index.as_usize() + self.universe_indices.len() =>
937943
{
938-
bug!("Bound vars outside of `self.universe_indices`");
944+
bug!(
945+
"Bound vars {ct:#?} outside of `self.universe_indices`: {:#?}",
946+
self.universe_indices
947+
);
939948
}
940949
ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
941950
let universe = self.universe_for(debruijn);

compiler/rustc_ty_utils/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
1010
#![cfg_attr(not(bootstrap), allow(internal_features))]
1111
#![feature(assert_matches)]
12+
#![feature(associated_type_defaults)]
1213
#![feature(iterator_try_collect)]
1314
#![feature(let_chains)]
1415
#![feature(if_let_guard)]
@@ -39,6 +40,7 @@ mod layout_sanity_check;
3940
mod needs_drop;
4041
mod opaque_types;
4142
pub mod representability;
43+
pub mod sig_types;
4244
mod structural_match;
4345
mod ty;
4446

compiler/rustc_ty_utils/src/opaque_types.rs

+23-44
Original file line numberDiff line numberDiff line change
@@ -53,14 +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 => None,
5756
DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
5857
Some(self.tcx.local_parent(self.item))
5958
}
60-
other => span_bug!(
61-
self.tcx.def_span(self.item),
62-
"unhandled item with opaque types: {other:?}"
63-
),
59+
_ => None,
6460
}
6561
}
6662

@@ -98,14 +94,6 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
9894
hir_id == scope
9995
}
10096

101-
fn collect_body_and_predicate_taits(&mut self) {
102-
// Look at all where bounds.
103-
self.tcx.predicates_of(self.item).instantiate_identity(self.tcx).visit_with(self);
104-
// An item is allowed to constrain opaques declared within its own body (but not nested within
105-
// nested functions).
106-
self.collect_taits_declared_in_body();
107-
}
108-
10997
#[instrument(level = "trace", skip(self))]
11098
fn collect_taits_declared_in_body(&mut self) {
11199
let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(self.item)).value;
@@ -132,6 +120,13 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
132120
}
133121
}
134122

123+
impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
124+
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<!> {
125+
self.visit_spanned(span, value);
126+
ControlFlow::Continue(())
127+
}
128+
}
129+
135130
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
136131
#[instrument(skip(self), ret, level = "trace")]
137132
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
@@ -273,37 +268,20 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
273268
let kind = tcx.def_kind(item);
274269
trace!(?kind);
275270
let mut collector = OpaqueTypeCollector::new(tcx, item);
271+
super::sig_types::walk_types(tcx, item, &mut collector);
276272
match kind {
277-
// Walk over the signature of the function-like to find the opaques.
278-
DefKind::AssocFn | DefKind::Fn => {
279-
let ty_sig = tcx.fn_sig(item).instantiate_identity();
280-
let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
281-
// Walk over the inputs and outputs manually in order to get good spans for them.
282-
collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
283-
for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
284-
collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
285-
}
286-
collector.collect_body_and_predicate_taits();
287-
}
288-
// Walk over the type of the item to find opaques.
289-
DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
290-
let span = match tcx.hir().get_by_def_id(item).ty() {
291-
Some(ty) => ty.span,
292-
_ => tcx.def_span(item),
293-
};
294-
collector.visit_spanned(span, tcx.type_of(item).instantiate_identity());
295-
collector.collect_body_and_predicate_taits();
296-
}
297-
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
298-
DefKind::TyAlias | DefKind::AssocTy => {
299-
tcx.type_of(item).instantiate_identity().visit_with(&mut collector);
300-
}
301-
DefKind::OpaqueTy => {
302-
for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() {
303-
collector.visit_spanned(span, pred);
304-
}
273+
DefKind::AssocFn
274+
| DefKind::Fn
275+
| DefKind::Static(_)
276+
| DefKind::Const
277+
| DefKind::AssocConst
278+
| DefKind::AnonConst => {
279+
collector.collect_taits_declared_in_body();
305280
}
306-
DefKind::Mod
281+
DefKind::OpaqueTy
282+
| DefKind::TyAlias
283+
| DefKind::AssocTy
284+
| DefKind::Mod
307285
| DefKind::Struct
308286
| DefKind::Union
309287
| DefKind::Enum
@@ -322,9 +300,10 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
322300
| DefKind::LifetimeParam
323301
| DefKind::GlobalAsm
324302
| DefKind::Impl { .. } => {}
325-
// Closures and coroutines are type checked with their parent, so there is no difference here.
303+
// Closures and coroutines are type checked with their parent, so we need to allow all
304+
// opaques from the closure signature *and* from the parent body.
326305
DefKind::Closure | DefKind::Coroutine | DefKind::InlineConst => {
327-
return tcx.opaque_types_defined_by(tcx.local_parent(item));
306+
collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
328307
}
329308
}
330309
tcx.arena.alloc_from_iter(collector.opaques)
+129
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 SpannedTypeVisitor<'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: SpannedTypeVisitor<'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::Coroutine => {
29+
match tcx.type_of(item).instantiate_identity().kind() {
30+
ty::Coroutine(_, args, _) => visitor.visit(tcx.def_span(item), args.as_coroutine().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
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
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+
}

tests/ui/privacy/associated-item-privacy-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod priv_trait {
2323
let _: <Pub as PrivTr>::AssocTy;
2424
//~^ ERROR associated type `PrivTr::AssocTy` is private
2525
pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
26-
//~^ ERROR trait `PrivTr` is private
26+
//~^ ERROR associated type `PrivTr::AssocTy` is private
2727
pub trait InSignatureTr: PrivTr {}
2828
//~^ ERROR trait `PrivTr` is private
2929
impl PrivTr for u8 {}

tests/ui/privacy/associated-item-privacy-trait.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ LL | priv_trait::mac!();
5353
|
5454
= note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
5555

56-
error: trait `PrivTr` is private
56+
error: associated type `PrivTr::AssocTy` is private
5757
--> $DIR/associated-item-privacy-trait.rs:25:34
5858
|
5959
LL | pub type InSignatureTy = <Pub as PrivTr>::AssocTy;
60-
| ^^^^^^^^^^^^^^^^^^^^^^^^ private trait
60+
| ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type
6161
...
6262
LL | priv_trait::mac!();
6363
| ------------------ in this macro invocation

tests/ui/privacy/private-in-public.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ mod aliases_pub {
104104

105105
// This should be OK, but associated type aliases are not substituted yet
106106
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
107-
//~^ WARNING trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3`
108-
//~| WARNING type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
107+
//~^ WARNING type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
108+
//~| WARNING associated type `aliases_pub::PrivTr::Assoc` is more private than the item `aliases_pub::f3`
109109

110110
impl PrivUseAlias {
111111
pub fn f(arg: Priv) {}
@@ -133,8 +133,8 @@ mod aliases_priv {
133133
pub fn f1(arg: PrivUseAlias) {} //~ WARNING type `Priv1` is more private than the item `aliases_priv::f1`
134134
pub fn f2(arg: PrivAlias) {} //~ WARNING type `Priv2` is more private than the item `aliases_priv::f2`
135135
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
136-
//~^ WARNING trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3`
137-
//~| WARNING type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
136+
//~^ WARNING type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
137+
//~| WARNING associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3`
138138
}
139139

140140
mod aliases_params {

0 commit comments

Comments
 (0)