diff options
| author | Stuart Cook <Zalathar@users.noreply.github.com> | 2025-04-08 20:55:09 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-08 20:55:09 +1000 |
| commit | 056756c7c4db570f93f8586828648fe02480dcb4 (patch) | |
| tree | 296476047e75fc891e2173ed9d278e81ca7da0b8 | |
| parent | ab80f575c485eccd57a86a92a7aabad5815270d7 (diff) | |
| parent | 45afefa7c025f3847439822b053edf76ae62e561 (diff) | |
| download | rust-056756c7c4db570f93f8586828648fe02480dcb4.tar.gz rust-056756c7c4db570f93f8586828648fe02480dcb4.zip | |
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 a2a0cfe82563146325674b8d437f9f9f6e703703, 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)
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/confirmation.rs | 38 | ||||
| -rw-r--r-- | tests/ui/traits/dyn-drop-principal-with-projections.rs | 13 |
2 files changed, 37 insertions, 14 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2cb7d2d8931..9d5eb551fe6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1090,26 +1090,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { // See `assemble_candidates_for_unsizing` for more info. // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. - let iter = data_a - .principal() - .filter(|_| { - // optionally drop the principal, if we're unsizing to no principal - data_b.principal().is_some() - }) - .map(|b| b.map_bound(ty::ExistentialPredicate::Trait)) - .into_iter() - .chain( + let existential_predicates = if data_b.principal().is_some() { + tcx.mk_poly_existential_predicates_from_iter( data_a - .projection_bounds() - .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)), + .principal() + .map(|b| b.map_bound(ty::ExistentialPredicate::Trait)) + .into_iter() + .chain( + data_a + .projection_bounds() + .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)), + ) + .chain( + data_b + .auto_traits() + .map(ty::ExistentialPredicate::AutoTrait) + .map(ty::Binder::dummy), + ), ) - .chain( + } else { + // If we're unsizing to a dyn type that has no principal, then drop + // the principal and projections from the type. We use the auto traits + // from the RHS type since as we noted that we've checked for auto + // trait compatibility during unsizing. + tcx.mk_poly_existential_predicates_from_iter( data_b .auto_traits() .map(ty::ExistentialPredicate::AutoTrait) .map(ty::Binder::dummy), - ); - let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter); + ) + }; let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a); // Require that the traits involved in this upcast are **equal**; diff --git a/tests/ui/traits/dyn-drop-principal-with-projections.rs b/tests/ui/traits/dyn-drop-principal-with-projections.rs new file mode 100644 index 00000000000..912061847c6 --- /dev/null +++ b/tests/ui/traits/dyn-drop-principal-with-projections.rs @@ -0,0 +1,13 @@ +//@ check-pass + +trait Tr { + type Assoc; +} + +impl Tr for () { + type Assoc = (); +} + +fn main() { + let x = &() as &(dyn Tr<Assoc = ()> + Send) as &dyn Send; +} |
