Skip to content

Commit 1d67eba

Browse files
committed
Auto merge of #112891 - oli-obk:impl_trait_in_assoc_tys_cleanup, r=compiler-errors
Various impl trait in assoc tys cleanups r? `@compiler-errors` All commits except for the last are pure refactorings. 274dab5bd658c97886a8987340bf50ae57900c39 allows struct fields to participate in deciding whether a function has an opaque in its signature. best reviewed commit by commit
2 parents 22e9fe6 + 27b386a commit 1d67eba

29 files changed

+377
-109
lines changed

compiler/rustc_hir/src/hir.rs

+23
Original file line numberDiff line numberDiff line change
@@ -3743,6 +3743,29 @@ impl<'hir> Node<'hir> {
37433743
}
37443744
}
37453745

3746+
/// Get the type for constants, assoc types, type aliases and statics.
3747+
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
3748+
match self {
3749+
Node::Item(it) => match it.kind {
3750+
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
3751+
Some(ty)
3752+
}
3753+
_ => None,
3754+
},
3755+
Node::TraitItem(it) => match it.kind {
3756+
TraitItemKind::Const(ty, _) => Some(ty),
3757+
TraitItemKind::Type(_, ty) => ty,
3758+
_ => None,
3759+
},
3760+
Node::ImplItem(it) => match it.kind {
3761+
ImplItemKind::Const(ty, _) => Some(ty),
3762+
ImplItemKind::Type(ty) => Some(ty),
3763+
_ => None,
3764+
},
3765+
_ => None,
3766+
}
3767+
}
3768+
37463769
pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
37473770
match self {
37483771
Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),

compiler/rustc_hir_analysis/src/check/check.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
563563
check_union(tcx, id.owner_id.def_id);
564564
}
565565
DefKind::OpaqueTy => {
566-
let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
567-
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
566+
let origin = tcx.opaque_type_origin(id.owner_id.def_id);
567+
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
568568
&& let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
569569
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
570570
{

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1543,8 +1543,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
15431543
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
15441544
&& self.seen.insert(unshifted_opaque_ty.def_id)
15451545
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
1546-
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
1547-
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
1546+
&& let origin = tcx.opaque_type_origin(opaque_def_id)
1547+
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
15481548
&& source == self.fn_def_id
15491549
{
15501550
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {

compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ impl<T> Trait<T> for X {
260260
(ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => {
261261
if tcx.is_type_alias_impl_trait(alias.def_id) {
262262
if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) {
263-
diag.span_note(tcx.def_span(body_owner_def_id), "\
263+
let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id));
264+
diag.span_note(sp, "\
264265
this item must have the opaque type in its signature \
265266
in order to be able to register hidden types");
266267
}

compiler/rustc_infer/src/infer/opaque_types.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> {
378378
DefiningAnchor::Bind(bind) => bind,
379379
};
380380

381-
let origin = self.opaque_type_origin_unchecked(def_id);
381+
let origin = self.tcx.opaque_type_origin(def_id);
382382
let in_definition_scope = match origin {
383383
// Async `impl Trait`
384384
hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
@@ -395,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> {
395395
};
396396
in_definition_scope.then_some(origin)
397397
}
398-
399-
/// Returns the origin of the opaque type `def_id` even if we are not in its
400-
/// defining scope.
401-
#[instrument(skip(self), level = "trace", ret)]
402-
fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin {
403-
self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin
404-
}
405398
}
406399

407400
/// Visitor that requires that (almost) all regions in the type visited outlive

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1138,8 +1138,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
11381138
| DefKind::InlineConst => true,
11391139

11401140
DefKind::OpaqueTy => {
1141-
let opaque = tcx.hir().expect_item(def_id).expect_opaque_ty();
1142-
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
1141+
let origin = tcx.opaque_type_origin(def_id);
1142+
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
11431143
&& let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
11441144
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
11451145
{

compiler/rustc_middle/src/ty/context.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,12 @@ impl<'tcx> TyCtxt<'tcx> {
11921192
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
11931193
self.visibility(def_id).expect_local()
11941194
}
1195+
1196+
/// Returns the origin of the opaque type `def_id`.
1197+
#[instrument(skip(self), level = "trace", ret)]
1198+
pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
1199+
self.hir().expect_item(def_id).expect_opaque_ty().origin
1200+
}
11951201
}
11961202

11971203
/// A trait implemented for all `X<'a>` types that can be safely and

compiler/rustc_ty_utils/src/assoc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ fn associated_type_for_impl_trait_in_trait(
259259
opaque_ty_def_id: LocalDefId,
260260
) -> LocalDefId {
261261
let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
262-
tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
262+
tcx.opaque_type_origin(opaque_ty_def_id)
263263
else {
264264
bug!("expected opaque for {opaque_ty_def_id:?}");
265265
};

compiler/rustc_ty_utils/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub struct DuplicateArg<'tcx> {
113113
}
114114

115115
#[derive(Diagnostic)]
116-
#[diag(ty_utils_impl_trait_not_param)]
116+
#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
117117
pub struct NotParam<'tcx> {
118118
pub arg: GenericArg<'tcx>,
119119
#[primary_span]

compiler/rustc_ty_utils/src/opaque_types.rs

+83-47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use rustc_data_structures::fx::FxHashSet;
2-
use rustc_errors::ErrorGuaranteed;
32
use rustc_hir::{def::DefKind, def_id::LocalDefId};
43
use rustc_middle::query::Providers;
54
use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
@@ -19,21 +18,26 @@ struct OpaqueTypeCollector<'tcx> {
1918

2019
/// Avoid infinite recursion due to recursive declarations.
2120
seen: FxHashSet<LocalDefId>,
21+
22+
span: Option<Span>,
2223
}
2324

2425
impl<'tcx> OpaqueTypeCollector<'tcx> {
25-
fn collect(
26-
tcx: TyCtxt<'tcx>,
27-
item: LocalDefId,
28-
val: ty::Binder<'tcx, impl TypeVisitable<TyCtxt<'tcx>>>,
29-
) -> Vec<LocalDefId> {
30-
let mut collector = Self { tcx, opaques: Vec::new(), item, seen: Default::default() };
31-
val.skip_binder().visit_with(&mut collector);
32-
collector.opaques
26+
fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
27+
Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None }
3328
}
3429

3530
fn span(&self) -> Span {
36-
self.tcx.def_span(self.item)
31+
self.span.unwrap_or_else(|| {
32+
self.tcx.def_ident_span(self.item).unwrap_or_else(|| self.tcx.def_span(self.item))
33+
})
34+
}
35+
36+
fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) {
37+
let old = self.span;
38+
self.span = Some(span);
39+
value.visit_with(self);
40+
self.span = old;
3741
}
3842

3943
fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
@@ -60,53 +64,57 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
6064
}
6165

6266
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
63-
type BreakTy = ErrorGuaranteed;
64-
6567
#[instrument(skip(self), ret, level = "trace")]
66-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
68+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<!> {
69+
t.super_visit_with(self)?;
6770
match t.kind() {
6871
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
6972
if !self.seen.insert(alias_ty.def_id.expect_local()) {
7073
return ControlFlow::Continue(());
7174
}
75+
76+
self.opaques.push(alias_ty.def_id.expect_local());
77+
7278
match self.tcx.uses_unique_generic_params(alias_ty.substs, CheckRegions::Bound) {
7379
Ok(()) => {
7480
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
7581
// supported at all, so this is sound to do, but once we want to support them, you'll
7682
// start seeing the error below.
7783

78-
self.opaques.push(alias_ty.def_id.expect_local());
79-
8084
// Collect opaque types nested within the associated type bounds of this opaque type.
81-
for (pred, _span) in self
85+
// We use identity substs here, because we already know that the opaque type uses
86+
// only generic parameters, and thus substituting would not give us more information.
87+
for (pred, span) in self
8288
.tcx
8389
.explicit_item_bounds(alias_ty.def_id)
84-
.subst_iter_copied(self.tcx, alias_ty.substs)
90+
.subst_identity_iter_copied()
8591
{
8692
trace!(?pred);
87-
pred.visit_with(self)?;
93+
self.visit_spanned(span, pred);
8894
}
89-
90-
ControlFlow::Continue(())
9195
}
9296
Err(NotUniqueParam::NotParam(arg)) => {
93-
let err = self.tcx.sess.emit_err(NotParam {
97+
self.tcx.sess.emit_err(NotParam {
9498
arg,
9599
span: self.span(),
96100
opaque_span: self.tcx.def_span(alias_ty.def_id),
97101
});
98-
ControlFlow::Break(err)
99102
}
100103
Err(NotUniqueParam::DuplicateParam(arg)) => {
101-
let err = self.tcx.sess.emit_err(DuplicateArg {
104+
self.tcx.sess.emit_err(DuplicateArg {
102105
arg,
103106
span: self.span(),
104107
opaque_span: self.tcx.def_span(alias_ty.def_id),
105108
});
106-
ControlFlow::Break(err)
107109
}
108110
}
109111
}
112+
ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
113+
self.tcx
114+
.type_of(alias_ty.def_id)
115+
.subst(self.tcx, alias_ty.substs)
116+
.visit_with(self)?;
117+
}
110118
ty::Alias(ty::Projection, alias_ty) => {
111119
// This avoids having to do normalization of `Self::AssocTy` by only
112120
// supporting the case of a method defining opaque types from assoc types
@@ -136,26 +144,44 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
136144
ty::InternalSubsts::identity_for_item(self.tcx, parent),
137145
);
138146

139-
if !check_substs_compatible(self.tcx, assoc, impl_substs) {
147+
if check_substs_compatible(self.tcx, assoc, impl_substs) {
148+
return self
149+
.tcx
150+
.type_of(assoc.def_id)
151+
.subst(self.tcx, impl_substs)
152+
.visit_with(self);
153+
} else {
140154
self.tcx.sess.delay_span_bug(
141155
self.tcx.def_span(assoc.def_id),
142156
"item had incorrect substs",
143157
);
144-
return ControlFlow::Continue(());
145158
}
146-
147-
return self
148-
.tcx
149-
.type_of(assoc.def_id)
150-
.subst(self.tcx, impl_substs)
151-
.visit_with(self);
152159
}
153160
}
154161
}
155-
t.super_visit_with(self)
156162
}
157-
_ => t.super_visit_with(self),
163+
ty::Adt(def, _) if def.did().is_local() => {
164+
if !self.seen.insert(def.did().expect_local()) {
165+
return ControlFlow::Continue(());
166+
}
167+
for variant in def.variants().iter() {
168+
for field in variant.fields.iter() {
169+
// Don't use the `ty::Adt` substs, we either
170+
// * found the opaque in the substs
171+
// * will find the opaque in the unsubstituted fields
172+
// The only other situation that can occur is that after substituting,
173+
// some projection resolves to an opaque that we would have otherwise
174+
// not found. While we could substitute and walk those, that would mean we
175+
// would have to walk all substitutions of an Adt, which can quickly
176+
// degenerate into looking at an exponential number of types.
177+
let ty = self.tcx.type_of(field.did).subst_identity();
178+
self.visit_spanned(self.tcx.def_span(field.did), ty);
179+
}
180+
}
181+
}
182+
_ => trace!(kind=?t.kind()),
158183
}
184+
ControlFlow::Continue(())
159185
}
160186
}
161187

@@ -166,21 +192,29 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
166192
match kind {
167193
// We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds`
168194
DefKind::Fn | DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => {
169-
let defined_opaques = match kind {
170-
DefKind::Fn => {
171-
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
195+
let mut collector = OpaqueTypeCollector::new(tcx, item);
196+
match kind {
197+
// Walk over the signature of the function-like to find the opaques.
198+
DefKind::AssocFn | DefKind::Fn => {
199+
let ty_sig = tcx.fn_sig(item).subst_identity();
200+
let hir_sig = tcx.hir().get_by_def_id(item).fn_sig().unwrap();
201+
// Walk over the inputs and outputs manually in order to get good spans for them.
202+
collector.visit_spanned(hir_sig.decl.output.span(), ty_sig.output());
203+
for (hir, ty) in hir_sig.decl.inputs.iter().zip(ty_sig.inputs().iter()) {
204+
collector.visit_spanned(hir.span, ty.map_bound(|x| *x));
205+
}
172206
}
173-
DefKind::AssocFn => {
174-
OpaqueTypeCollector::collect(tcx, item, tcx.fn_sig(item).subst_identity())
207+
// Walk over the type of the item to find opaques.
208+
DefKind::AssocTy | DefKind::AssocConst => {
209+
let span = match tcx.hir().get_by_def_id(item).ty() {
210+
Some(ty) => ty.span,
211+
_ => tcx.def_span(item),
212+
};
213+
collector.visit_spanned(span, tcx.type_of(item).subst_identity());
175214
}
176-
DefKind::AssocTy | DefKind::AssocConst => OpaqueTypeCollector::collect(
177-
tcx,
178-
item,
179-
ty::Binder::dummy(tcx.type_of(item).subst_identity()),
180-
),
181215
_ => unreachable!(),
182-
};
183-
tcx.arena.alloc_from_iter(defined_opaques)
216+
}
217+
tcx.arena.alloc_from_iter(collector.opaques)
184218
}
185219
DefKind::Mod
186220
| DefKind::Struct
@@ -209,7 +243,9 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
209243
| DefKind::GlobalAsm
210244
| DefKind::Impl { .. }
211245
| DefKind::Closure
212-
| DefKind::Generator => &[],
246+
| DefKind::Generator => {
247+
span_bug!(tcx.def_span(item), "{kind:?} is type checked as part of its parent")
248+
}
213249
}
214250
}
215251

tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,19 @@ pub type Type9 = impl Send;
6161
pub type Type10 = impl Send;
6262
pub type Type11 = impl Send;
6363

64-
pub fn fn1<'a>() {
64+
pub fn fn1<'a>() where
65+
Type1: 'static,
66+
Type2: 'static,
67+
Type3: 'static,
68+
Type4: 'static,
69+
Type5: 'static,
70+
Type6: 'static,
71+
Type7: 'static,
72+
Type8: 'static,
73+
Type9: 'static,
74+
Type10: 'static,
75+
Type11: 'static,
76+
{
6577
// Closure
6678
let closure1 = || { };
6779
let _: Type1 = closure1;

tests/ui/generic-associated-types/issue-88595.rs

-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ impl<'a> A<'a> for C {
1919
type B<'b> = impl Clone;
2020

2121
fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
22-
//~^ ERROR: mismatched types
2322
}

0 commit comments

Comments
 (0)