Skip to content

Commit 6345cb0

Browse files
something
1 parent 871926d commit 6345cb0

File tree

7 files changed

+94
-39
lines changed

7 files changed

+94
-39
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
134134
.into_iter()
135135
.filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
136136

137+
let mut implied_projection_bounds = vec![];
137138
for (base_trait_ref, original_span) in regular_traits_refs_spans {
138139
let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx);
139140
for ClauseWithSupertraitSpan { pred, supertrait_span } in
@@ -188,7 +189,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
188189
// the discussion in #56288 for alternatives.
189190
if !references_self {
190191
// Include projections defined on supertraits.
191-
projection_bounds.push((pred, original_span));
192+
implied_projection_bounds.push(pred);
192193
}
193194

194195
self.check_elaborated_projection_mentions_input_lifetimes(
@@ -221,6 +222,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
221222
);
222223
}
223224
}
225+
for projection_bound in &implied_projection_bounds {
226+
let def_id = projection_bound.projection_def_id();
227+
let trait_ref = tcx.anonymize_bound_vars(
228+
projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
229+
);
230+
needed_associated_types.swap_remove(&(def_id, trait_ref));
231+
}
224232

225233
self.complain_about_missing_assoc_tys(
226234
principal_span,

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
pub(super) mod structural_traits;
44

55
use derive_where::derive_where;
6+
use rustc_type_ir::data_structures::HashSet;
67
use rustc_type_ir::fold::TypeFoldable;
78
use rustc_type_ir::inherent::*;
89
use rustc_type_ir::lang_items::TraitSolverLangItem;
@@ -666,13 +667,22 @@ where
666667
// Consider all of the auto-trait and projection bounds, which don't
667668
// need to be recorded as a `BuiltinImplSource::Object` since they don't
668669
// really have a vtable base...
670+
let mut shadowed = HashSet::default();
669671
for bound in bounds.iter() {
670672
match bound.skip_binder() {
671673
ty::ExistentialPredicate::Trait(_) => {
672674
// Skip principal
673675
}
674-
ty::ExistentialPredicate::Projection(_)
675-
| ty::ExistentialPredicate::AutoTrait(_) => {
676+
ty::ExistentialPredicate::Projection(proj) => {
677+
shadowed.insert(proj.def_id);
678+
candidates.extend(G::probe_and_consider_object_bound_candidate(
679+
self,
680+
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
681+
goal,
682+
bound.with_self_ty(cx, self_ty),
683+
));
684+
}
685+
ty::ExistentialPredicate::AutoTrait(_) => {
676686
candidates.extend(G::probe_and_consider_object_bound_candidate(
677687
self,
678688
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
@@ -688,12 +698,19 @@ where
688698
// a projection goal.
689699
if let Some(principal) = bounds.principal() {
690700
let principal_trait_ref = principal.with_self_ty(cx, self_ty);
691-
for (idx, assumption) in elaborate::supertraits(cx, principal_trait_ref).enumerate() {
701+
let principal_clause: I::Clause = principal_trait_ref.upcast(cx);
702+
for (idx, assumption) in elaborate::elaborate(cx, [principal_clause]).enumerate() {
703+
if let Some(proj) = assumption.as_projection_clause() {
704+
if shadowed.contains(&proj.projection_def_id()) {
705+
continue;
706+
}
707+
}
708+
692709
candidates.extend(G::probe_and_consider_object_bound_candidate(
693710
self,
694711
CandidateSource::BuiltinImpl(BuiltinImplSource::Object(idx)),
695712
goal,
696-
assumption.upcast(cx),
713+
assumption,
697714
));
698715
}
699716
}

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
1818
use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
1919
use rustc_middle::{bug, span_bug};
2020
use rustc_span::symbol::sym;
21+
use rustc_type_ir::elaborate;
2122
use tracing::{debug, instrument};
2223

2324
use super::{
@@ -59,7 +60,7 @@ enum ProjectionCandidate<'tcx> {
5960
TraitDef(ty::PolyProjectionPredicate<'tcx>),
6061

6162
/// Bounds specified on an object type
62-
Object(ty::PolyProjectionPredicate<'tcx>),
63+
Object(ty::PolyProjectionPredicate<'tcx>, bool),
6364

6465
/// From an "impl" (or a "pseudo-impl" returned by select)
6566
Select(Selection<'tcx>),
@@ -682,7 +683,7 @@ fn project<'cx, 'tcx>(
682683

683684
assemble_candidates_from_object_ty(selcx, obligation, &mut candidates);
684685

685-
if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(_)) = candidates {
686+
if let ProjectionCandidateSet::Single(ProjectionCandidate::Object(..)) = candidates {
686687
// Avoid normalization cycle from selection (see
687688
// `assemble_candidates_from_object_ty`).
688689
// FIXME(lazy_normalization): Lazy normalization should save us from
@@ -838,6 +839,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
838839
}
839840
_ => return,
840841
};
842+
841843
let env_predicates = data
842844
.projection_bounds()
843845
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
@@ -847,10 +849,30 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
847849
selcx,
848850
obligation,
849851
candidate_set,
850-
ProjectionCandidate::Object,
852+
|c| ProjectionCandidate::Object(c, false),
851853
env_predicates,
852854
false,
853855
);
856+
857+
let shadowed =
858+
data.projection_bounds().any(|bound| bound.item_def_id() == obligation.predicate.def_id);
859+
860+
if !shadowed && let Some(principal) = data.principal() {
861+
let principal: ty::Clause<'tcx> = principal.with_self_ty(tcx, self_ty).upcast(tcx);
862+
let supertrait_projections = elaborate::elaborate(tcx, [principal]).filter(|clause| {
863+
clause
864+
.as_projection_clause()
865+
.is_some_and(|proj| proj.projection_def_id() == obligation.predicate.def_id)
866+
});
867+
assemble_candidates_from_predicates(
868+
selcx,
869+
obligation,
870+
candidate_set,
871+
|c| ProjectionCandidate::Object(c, true),
872+
supertrait_projections,
873+
true,
874+
);
875+
}
854876
}
855877

856878
#[instrument(
@@ -1259,10 +1281,12 @@ fn confirm_candidate<'cx, 'tcx>(
12591281
) -> Progress<'tcx> {
12601282
debug!(?obligation, ?candidate, "confirm_candidate");
12611283
let mut progress = match candidate {
1262-
ProjectionCandidate::ParamEnv(poly_projection)
1263-
| ProjectionCandidate::Object(poly_projection) => {
1284+
ProjectionCandidate::ParamEnv(poly_projection) => {
12641285
confirm_param_env_candidate(selcx, obligation, poly_projection, false)
12651286
}
1287+
ProjectionCandidate::Object(poly_projection, from_super) => {
1288+
confirm_param_env_candidate(selcx, obligation, poly_projection, from_super)
1289+
}
12661290

12671291
ProjectionCandidate::TraitDef(poly_projection) => {
12681292
confirm_param_env_candidate(selcx, obligation, poly_projection, true)

tests/ui/associated-types/issue-59324.stderr

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,6 @@ help: consider further restricting this bound
4343
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
4444
| +++++
4545

46-
error[E0277]: the trait bound `(): Foo` is not satisfied
47-
--> $DIR/issue-59324.rs:23:29
48-
|
49-
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
50-
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
51-
|
52-
help: this trait has no implementations, consider adding one
53-
--> $DIR/issue-59324.rs:3:1
54-
|
55-
LL | pub trait Foo: NotFoo {
56-
| ^^^^^^^^^^^^^^^^^^^^^
57-
5846
error[E0277]: the trait bound `Bug: Foo` is not satisfied
5947
--> $DIR/issue-59324.rs:19:10
6048
|
@@ -66,25 +54,13 @@ help: consider further restricting this bound
6654
LL | pub trait ThriftService<Bug: NotFoo + Foo>:
6755
| +++++
6856

69-
error[E0277]: the trait bound `(): Foo` is not satisfied
70-
--> $DIR/issue-59324.rs:23:52
71-
|
72-
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
73-
| ^^ the trait `Foo` is not implemented for `()`
74-
|
75-
help: this trait has no implementations, consider adding one
76-
--> $DIR/issue-59324.rs:3:1
77-
|
78-
LL | pub trait Foo: NotFoo {
79-
| ^^^^^^^^^^^^^^^^^^^^^
80-
81-
error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
57+
error[E0277]: the size for values of type `(dyn ThriftService<()> + 'static)` cannot be known at compilation time
8258
--> $DIR/issue-59324.rs:23:29
8359
|
8460
LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
8561
| ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
8662
|
87-
= help: the trait `Sized` is not implemented for `(dyn ThriftService<(), AssocType = _> + 'static)`
63+
= help: the trait `Sized` is not implemented for `(dyn ThriftService<()> + 'static)`
8864
= help: unsized fn params are gated as an unstable feature
8965
help: you can use `impl Trait` as the argument type
9066
|
@@ -95,6 +71,6 @@ help: function arguments must have a statically known size, borrowed types alway
9571
LL | fn with_factory<H>(factory: &dyn ThriftService<()>) {}
9672
| +
9773

98-
error: aborting due to 7 previous errors
74+
error: aborting due to 5 previous errors
9975

10076
For more information about this error, try `rustc --explain E0277`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//@ check-pass
2+
3+
trait Sup<T> {
4+
type Assoc;
5+
}
6+
7+
impl<T> Sup<T> for () {
8+
type Assoc = T;
9+
}
10+
11+
trait Trait<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {}
12+
13+
impl<T, U> Trait<T, U> for () {}
14+
15+
fn main() {
16+
let x: &dyn Trait<(), _> = &();
17+
let y: &dyn Trait<_, ()> = x;
18+
}

tests/ui/traits/alias/dont-elaborate-non-self.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error[E0277]: the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
1+
error[E0277]: the size for values of type `(dyn Fn<()> + 'static)` cannot be known at compilation time
22
--> $DIR/dont-elaborate-non-self.rs:7:14
33
|
44
LL | fn f<Fut>(a: dyn F<Fut>) {}
55
| ^^^^^^^^^^ doesn't have a size known at compile-time
66
|
7-
= help: the trait `Sized` is not implemented for `(dyn Fn() -> Fut + 'static)`
7+
= help: the trait `Sized` is not implemented for `(dyn Fn<()> + 'static)`
88
= help: unsized fn params are gated as an unstable feature
99
help: you can use `impl Trait` as the argument type
1010
|

tests/ui/traits/object/redundant.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ check-pass
2+
3+
trait Foo: Bar<Out = ()> {}
4+
trait Bar {
5+
type Out;
6+
}
7+
8+
fn w(x: &dyn Foo<Out = ()>) {
9+
let x: &dyn Foo = x;
10+
}
11+
12+
fn main() {}

0 commit comments

Comments
 (0)