about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-16 22:11:03 +0000
committerMichael Goulet <michael@errs.io>2023-07-25 15:15:25 +0000
commit24eefd08e25b8ffec2df092f0add812ed58875a0 (patch)
treebae3d7c004922f168bbe608b950ce74addd10174
parent7e66c0b7edaf680f26c6170d81ce18869345046e (diff)
downloadrust-24eefd08e25b8ffec2df092f0add812ed58875a0.tar.gz
rust-24eefd08e25b8ffec2df092f0add812ed58875a0.zip
Make sure to detect trait upcasting coercion even after normalization
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs37
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs8
-rw-r--r--tests/ui/traits/new-solver/normalize-unsize-rhs.rs2
-rw-r--r--tests/ui/traits/new-solver/trait-upcast-lhs-needs-normalization.rs2
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 {}