From 24eefd08e25b8ffec2df092f0add812ed58875a0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 16 Jul 2023 22:11:03 +0000 Subject: [PATCH] Make sure to detect trait upcasting coercion even after normalization --- compiler/rustc_hir_typeck/src/coercion.rs | 37 +++++-------------- .../src/solve/eval_ctxt/select.rs | 8 +++- .../traits/new-solver/normalize-unsize-rhs.rs | 2 + .../trait-upcast-lhs-needs-normalization.rs | 2 + 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 3b1d9c8905b..f8efe4ad585 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -622,7 +622,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ty::TraitRef::new(self.tcx, coerce_unsized_did, [coerce_source, coerce_target]) )]; - let mut has_unsized_tuple_coercion = false; let mut has_trait_upcasting_coercion = None; // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid @@ -636,22 +635,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) if traits.contains(&trait_pred.def_id()) => { - let trait_pred = self.resolve_vars_if_possible(trait_pred); - if unsize_did == trait_pred.def_id() { - let self_ty = trait_pred.self_ty(); - let unsize_ty = trait_pred.trait_ref.args[1].expect_ty(); - if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) = - (self_ty.kind(), unsize_ty.kind()) - && data_a.principal_def_id() != data_b.principal_def_id() - { - debug!("coerce_unsized: found trait upcasting coercion"); - has_trait_upcasting_coercion = Some((self_ty, unsize_ty)); - } - if let ty::Tuple(..) = unsize_ty.kind() { - debug!("coerce_unsized: found unsized tuple coercion"); - has_unsized_tuple_coercion = true; - } - } trait_pred } _ => { @@ -659,6 +642,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { continue; } }; + let trait_pred = self.resolve_vars_if_possible(trait_pred); match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) { // Uncertain or unimplemented. Ok(None) => { @@ -701,18 +685,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // be silent, as it causes a type mismatch later. } - Ok(Some(impl_source)) => queue.extend(impl_source.nested_obligations()), - } - } + Ok(Some(impl_source)) => { + if matches!(impl_source, traits::ImplSource::TraitUpcasting(..)) { + has_trait_upcasting_coercion = + Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1))); + } - if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { - feature_err( - &self.tcx.sess.parse_sess, - sym::unsized_tuple_coercion, - self.cause.span, - "unsized tuple coercion is not stable enough for use and is subject to change", - ) - .emit(); + queue.extend(impl_source.nested_obligations()) + } + } } if let Some((sub, sup)) = has_trait_upcasting_coercion diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 27d877b84dd..1cedbb6b761 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -315,7 +315,13 @@ fn rematch_object<'tcx>( // If we're upcasting, get the offset of the vtable pointer, otherwise get // the base of the vtable. Ok(Some(if is_upcasting { - ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) + // If source and target trait def ids are identical, + // then we are simply removing auto traits. + if source_trait_ref.def_id() == target_trait_ref.def_id() { + ImplSource::Builtin(nested) + } else { + ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) + } } else { ImplSource::Object(ImplSourceObjectData { vtable_base, nested }) })) diff --git a/tests/ui/traits/new-solver/normalize-unsize-rhs.rs b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs index 1bb5c9b4111..a398ab4f2f2 100644 --- a/tests/ui/traits/new-solver/normalize-unsize-rhs.rs +++ b/tests/ui/traits/new-solver/normalize-unsize-rhs.rs @@ -1,6 +1,8 @@ // compile-flags: -Ztrait-solver=next // check-pass +#![feature(trait_upcasting)] + trait A {} trait B: A {} diff --git a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs index 79114b93b78..43cd773bf3c 100644 --- a/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs +++ b/tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs @@ -1,6 +1,8 @@ // check-pass // compile-flags: -Ztrait-solver=next +#![feature(trait_upcasting)] + pub trait A {} pub trait B: A {}