Skip to content

Commit 0928a1f

Browse files
committed
Auto merge of rust-lang#112914 - matthiaskrgr:rollup-f0kdqh9, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - rust-lang#112876 (Don't substitute a GAT that has mismatched generics in `OpaqueTypeCollector`) - rust-lang#112906 (rustdoc: render the body of associated types before the where-clause) - rust-lang#112907 (Update cargo) - rust-lang#112908 (Print def_id on EarlyBoundRegion debug) r? `@ghost` `@rustbot` modify labels: rollup
2 parents fba636a + b13c941 commit 0928a1f

File tree

13 files changed

+207
-82
lines changed

13 files changed

+207
-82
lines changed

compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ pub struct EarlyBoundRegion {
15841584

15851585
impl fmt::Debug for EarlyBoundRegion {
15861586
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1587-
write!(f, "{}, {}", self.index, self.name)
1587+
write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
15881588
}
15891589
}
15901590

compiler/rustc_trait_selection/src/traits/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ pub use self::specialize::{
6565
pub use self::structural_match::search_for_structural_match_violation;
6666
pub use self::structural_normalize::StructurallyNormalizeExt;
6767
pub use self::util::elaborate;
68-
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
69-
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
7068
pub use self::util::{
71-
supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
72-
SupertraitDefIds,
69+
check_substs_compatible, supertrait_def_ids, supertraits, transitive_bounds,
70+
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
7371
};
72+
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
73+
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
7474

7575
pub use self::chalk_fulfill::FulfillmentContext as ChalkFulfillmentContext;
7676

compiler/rustc_trait_selection/src/traits/project.rs

+1-41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Code for projecting associated types out of trait references.
22
3+
use super::check_substs_compatible;
34
use super::specialization_graph;
45
use super::translate_substs;
56
use super::util;
@@ -2378,47 +2379,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
23782379
}
23792380
}
23802381

2381-
// Verify that the trait item and its implementation have compatible substs lists
2382-
fn check_substs_compatible<'tcx>(
2383-
tcx: TyCtxt<'tcx>,
2384-
assoc_item: ty::AssocItem,
2385-
substs: ty::SubstsRef<'tcx>,
2386-
) -> bool {
2387-
fn check_substs_compatible_inner<'tcx>(
2388-
tcx: TyCtxt<'tcx>,
2389-
generics: &'tcx ty::Generics,
2390-
args: &'tcx [ty::GenericArg<'tcx>],
2391-
) -> bool {
2392-
if generics.count() != args.len() {
2393-
return false;
2394-
}
2395-
2396-
let (parent_args, own_args) = args.split_at(generics.parent_count);
2397-
2398-
if let Some(parent) = generics.parent
2399-
&& let parent_generics = tcx.generics_of(parent)
2400-
&& !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
2401-
return false;
2402-
}
2403-
2404-
for (param, arg) in std::iter::zip(&generics.params, own_args) {
2405-
match (&param.kind, arg.unpack()) {
2406-
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
2407-
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
2408-
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
2409-
_ => return false,
2410-
}
2411-
}
2412-
2413-
true
2414-
}
2415-
2416-
let generics = tcx.generics_of(assoc_item.def_id);
2417-
// Chop off any additional substs (RPITIT) substs
2418-
let substs = &substs[0..generics.count().min(substs.len())];
2419-
check_substs_compatible_inner(tcx, generics, substs)
2420-
}
2421-
24222382
fn confirm_impl_trait_in_trait_candidate<'tcx>(
24232383
selcx: &mut SelectionContext<'_, 'tcx>,
24242384
obligation: &ProjectionTyObligation<'tcx>,

compiler/rustc_trait_selection/src/traits/util.rs

+41
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,44 @@ pub enum TupleArgumentsFlag {
302302
Yes,
303303
No,
304304
}
305+
306+
// Verify that the trait item and its implementation have compatible substs lists
307+
pub fn check_substs_compatible<'tcx>(
308+
tcx: TyCtxt<'tcx>,
309+
assoc_item: ty::AssocItem,
310+
substs: ty::SubstsRef<'tcx>,
311+
) -> bool {
312+
fn check_substs_compatible_inner<'tcx>(
313+
tcx: TyCtxt<'tcx>,
314+
generics: &'tcx ty::Generics,
315+
args: &'tcx [ty::GenericArg<'tcx>],
316+
) -> bool {
317+
if generics.count() != args.len() {
318+
return false;
319+
}
320+
321+
let (parent_args, own_args) = args.split_at(generics.parent_count);
322+
323+
if let Some(parent) = generics.parent
324+
&& let parent_generics = tcx.generics_of(parent)
325+
&& !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
326+
return false;
327+
}
328+
329+
for (param, arg) in std::iter::zip(&generics.params, own_args) {
330+
match (&param.kind, arg.unpack()) {
331+
(ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
332+
| (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
333+
| (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
334+
_ => return false,
335+
}
336+
}
337+
338+
true
339+
}
340+
341+
let generics = tcx.generics_of(assoc_item.def_id);
342+
// Chop off any additional substs (RPITIT) substs
343+
let substs = &substs[0..generics.count().min(substs.len())];
344+
check_substs_compatible_inner(tcx, generics, substs)
345+
}

compiler/rustc_ty_utils/src/opaque_types.rs

+50-30
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
66
use rustc_middle::ty::{self, Ty, TyCtxt};
77
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
88
use rustc_span::Span;
9-
use rustc_type_ir::AliasKind;
9+
use rustc_trait_selection::traits::check_substs_compatible;
1010
use std::ops::ControlFlow;
1111

1212
use crate::errors::{DuplicateArg, NotParam};
@@ -36,6 +36,15 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
3636
self.tcx.def_span(self.item)
3737
}
3838

39+
fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
40+
let parent = self.parent()?;
41+
if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
42+
Some(self.tcx.impl_trait_ref(parent)?.subst_identity())
43+
} else {
44+
None
45+
}
46+
}
47+
3948
fn parent(&self) -> Option<LocalDefId> {
4049
match self.tcx.def_kind(self.item) {
4150
DefKind::Fn => None,
@@ -56,7 +65,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
5665
#[instrument(skip(self), ret, level = "trace")]
5766
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<ErrorGuaranteed> {
5867
match t.kind() {
59-
ty::Alias(AliasKind::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
68+
ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
6069
if !self.seen.insert(alias_ty.def_id.expect_local()) {
6170
return ControlFlow::Continue(());
6271
}
@@ -98,37 +107,48 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
98107
}
99108
}
100109
}
101-
ty::Alias(AliasKind::Projection, alias_ty) => {
102-
if let Some(parent) = self.parent() {
103-
trace!(?alias_ty);
104-
let (trait_ref, own_substs) = alias_ty.trait_ref_and_own_substs(self.tcx);
105-
106-
trace!(?trait_ref, ?own_substs);
107-
// This avoids having to do normalization of `Self::AssocTy` by only
108-
// supporting the case of a method defining opaque types from assoc types
109-
// in the same impl block.
110-
if trait_ref.self_ty() == self.tcx.type_of(parent).subst_identity() {
111-
for assoc in self.tcx.associated_items(parent).in_definition_order() {
110+
ty::Alias(ty::Projection, alias_ty) => {
111+
// This avoids having to do normalization of `Self::AssocTy` by only
112+
// supporting the case of a method defining opaque types from assoc types
113+
// in the same impl block.
114+
if let Some(parent_trait_ref) = self.parent_trait_ref() {
115+
// If the trait ref of the associated item and the impl differs,
116+
// then we can't use the impl's identity substitutions below, so
117+
// just skip.
118+
if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
119+
let parent = self.parent().expect("we should have a parent here");
120+
121+
for &assoc in self.tcx.associated_items(parent).in_definition_order() {
112122
trace!(?assoc);
113-
if assoc.trait_item_def_id == Some(alias_ty.def_id) {
114-
// We reconstruct the generic args of the associated type within the impl
115-
// from the impl's generics and the generic args passed to the type via the
116-
// projection.
117-
let substs = ty::InternalSubsts::identity_for_item(
118-
self.tcx,
119-
parent.to_def_id(),
123+
if assoc.trait_item_def_id != Some(alias_ty.def_id) {
124+
continue;
125+
}
126+
127+
// If the type is further specializable, then the type_of
128+
// is not actually correct below.
129+
if !assoc.defaultness(self.tcx).is_final() {
130+
continue;
131+
}
132+
133+
let impl_substs = alias_ty.substs.rebase_onto(
134+
self.tcx,
135+
parent_trait_ref.def_id,
136+
ty::InternalSubsts::identity_for_item(self.tcx, parent),
137+
);
138+
139+
if !check_substs_compatible(self.tcx, assoc, impl_substs) {
140+
self.tcx.sess.delay_span_bug(
141+
self.tcx.def_span(assoc.def_id),
142+
"item had incorrect substs",
120143
);
121-
trace!(?substs);
122-
let substs: Vec<_> =
123-
substs.iter().chain(own_substs.iter().copied()).collect();
124-
trace!(?substs);
125-
// Find opaque types in this associated type.
126-
return self
127-
.tcx
128-
.type_of(assoc.def_id)
129-
.subst(self.tcx, &substs)
130-
.visit_with(self);
144+
return ControlFlow::Continue(());
131145
}
146+
147+
return self
148+
.tcx
149+
.type_of(assoc.def_id)
150+
.subst(self.tcx, impl_substs)
151+
.visit_with(self);
132152
}
133153
}
134154
}

src/librustdoc/html/render/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -799,10 +799,11 @@ fn assoc_type(
799799
if !bounds.is_empty() {
800800
write!(w, ": {}", print_generic_bounds(bounds, cx))
801801
}
802-
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
802+
// Render the default before the where-clause which aligns with the new recommended style. See #89122.
803803
if let Some(default) = default {
804804
write!(w, " = {}", default.print(cx))
805805
}
806+
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
806807
}
807808

808809
fn assoc_method(

tests/rustdoc/generic-associated-types/gats.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ impl LendingIterator for () {
2323
pub struct Infinite<T>(T);
2424

2525
// @has foo/trait.LendingIterator.html
26-
// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T"
26+
// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> = &'a T where Self: 'a"
2727
impl<T> LendingIterator for Infinite<T> {
28-
type Item<'a> where Self: 'a = &'a T;
28+
type Item<'a> = &'a T where Self: 'a;
2929

3030
fn next<'a>(&'a self) -> Self::Item<'a> {
3131
&self.0

tests/ui/nll/ty-outlives/impl-trait-captures.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
1+
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds
22
--> $DIR/impl-trait-captures.rs:11:5
33
|
44
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
@@ -8,7 +8,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
88
LL | x
99
| ^
1010
|
11-
help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
11+
help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
1212
|
1313
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) {
1414
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(impl_trait_in_assoc_type)]
2+
3+
// We weren't checking that the trait and impl generics line up in the
4+
// normalization-shortcut code in `OpaqueTypeCollector`.
5+
6+
use std::ops::Deref;
7+
8+
trait Foo {
9+
type Bar<'a>;
10+
11+
type Baz<'a>;
12+
13+
fn test<'a>() -> Self::Bar<'a>;
14+
}
15+
16+
impl Foo for () {
17+
type Bar<'a> = impl Deref<Target = Self::Baz<'a>>;
18+
19+
type Baz<T> = impl Sized;
20+
//~^ ERROR type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
21+
//~| ERROR unconstrained opaque type
22+
23+
fn test<'a>() -> Self::Bar<'a> {
24+
&()
25+
}
26+
}
27+
28+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0049]: type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
2+
--> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:14
3+
|
4+
LL | type Baz<'a>;
5+
| -- expected 0 type parameters
6+
...
7+
LL | type Baz<T> = impl Sized;
8+
| ^ found 1 type parameter
9+
10+
error: unconstrained opaque type
11+
--> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:19
12+
|
13+
LL | type Baz<T> = impl Sized;
14+
| ^^^^^^^^^^
15+
|
16+
= note: `Baz` must be used in combination with a concrete type within the same impl
17+
18+
error: aborting due to 2 previous errors
19+
20+
For more information about this error, try `rustc --explain E0049`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#![feature(impl_trait_in_assoc_type)]
2+
3+
trait Foo<T> {
4+
type Assoc;
5+
6+
fn test() -> u32;
7+
}
8+
9+
struct DefinesOpaque;
10+
impl Foo<DefinesOpaque> for () {
11+
type Assoc = impl Sized;
12+
13+
// This test's return type is `u32`, *not* the opaque that is defined above.
14+
// Previously we were only checking that the self type of the assoc matched,
15+
// but this doesn't account for other impls with different trait substs.
16+
fn test() -> <() as Foo<NoOpaques>>::Assoc {
17+
let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
18+
//~^ ERROR mismatched types
19+
20+
1
21+
}
22+
}
23+
24+
struct NoOpaques;
25+
impl Foo<NoOpaques> for () {
26+
type Assoc = u32;
27+
28+
fn test() -> u32 {
29+
1
30+
}
31+
}
32+
33+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/not-matching-trait-refs-isnt-defining.rs:17:54
3+
|
4+
LL | type Assoc = impl Sized;
5+
| ---------- the expected opaque type
6+
...
7+
LL | let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
8+
| ----------------------------------- ^^ expected opaque type, found `&str`
9+
| |
10+
| expected due to this
11+
|
12+
= note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc`
13+
found reference `&'static str`
14+
note: this item must have the opaque type in its signature in order to be able to register hidden types
15+
--> $DIR/not-matching-trait-refs-isnt-defining.rs:16:5
16+
|
17+
LL | fn test() -> <() as Foo<NoOpaques>>::Assoc {
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
20+
error: aborting due to previous error
21+
22+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)