Skip to content

Commit 056756c

Browse files
authored
Rollup merge of #139421 - compiler-errors:upcast-no-principal-with-proj, r=oli-obk
Fix trait upcasting to dyn type with no principal when there are projections #126660 (which I had originally authored, lol) had a subtle bug that is the moral equivalent of #114036, which is that when upcasting from `dyn Principal<Projection = Ty> + AutoTrait` to `dyn AutoTrait`, we were dropping the trait ref for `Principal` but not its projections (if there were any). With debug assertions enabled, this triggers the assertion I luckily added in a2a0cfe, but even without debug assertions this is a logical bug since we had a dyn type with just a projection bound but no principal, so it caused a type mismatch. This does not need an FCP because this should've been covered by the FCP in #126660, but we just weren't testing a case when casting from a `dyn` type with projections 😸 Fixes #139418 r? ````@oli-obk```` (or anyone)
2 parents ab80f57 + 45afefa commit 056756c

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -1090,26 +1090,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10901090
{
10911091
// See `assemble_candidates_for_unsizing` for more info.
10921092
// We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
1093-
let iter = data_a
1094-
.principal()
1095-
.filter(|_| {
1096-
// optionally drop the principal, if we're unsizing to no principal
1097-
data_b.principal().is_some()
1098-
})
1099-
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
1100-
.into_iter()
1101-
.chain(
1093+
let existential_predicates = if data_b.principal().is_some() {
1094+
tcx.mk_poly_existential_predicates_from_iter(
11021095
data_a
1103-
.projection_bounds()
1104-
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
1096+
.principal()
1097+
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
1098+
.into_iter()
1099+
.chain(
1100+
data_a
1101+
.projection_bounds()
1102+
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
1103+
)
1104+
.chain(
1105+
data_b
1106+
.auto_traits()
1107+
.map(ty::ExistentialPredicate::AutoTrait)
1108+
.map(ty::Binder::dummy),
1109+
),
11051110
)
1106-
.chain(
1111+
} else {
1112+
// If we're unsizing to a dyn type that has no principal, then drop
1113+
// the principal and projections from the type. We use the auto traits
1114+
// from the RHS type since as we noted that we've checked for auto
1115+
// trait compatibility during unsizing.
1116+
tcx.mk_poly_existential_predicates_from_iter(
11071117
data_b
11081118
.auto_traits()
11091119
.map(ty::ExistentialPredicate::AutoTrait)
11101120
.map(ty::Binder::dummy),
1111-
);
1112-
let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
1121+
)
1122+
};
11131123
let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
11141124

11151125
// Require that the traits involved in this upcast are **equal**;
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ check-pass
2+
3+
trait Tr {
4+
type Assoc;
5+
}
6+
7+
impl Tr for () {
8+
type Assoc = ();
9+
}
10+
11+
fn main() {
12+
let x = &() as &(dyn Tr<Assoc = ()> + Send) as &dyn Send;
13+
}

0 commit comments

Comments
 (0)