about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-07-27 01:00:01 +0000
committerMichael Goulet <michael@errs.io>2023-08-03 18:21:11 +0000
commit238beae5e588fb3dc4550d970085b5bf29f40776 (patch)
tree0f89ca79139d71d70ef6ef50ec5eefcb3e6265c4
parent4cc659eb3fc99cd44457616b17d390488e80fcb0 (diff)
downloadrust-238beae5e588fb3dc4550d970085b5bf29f40776.tar.gz
rust-238beae5e588fb3dc4550d970085b5bf29f40776.zip
Fix upcasting with normalization in old solver, add a test
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs14
-rw-r--r--tests/ui/traits/trait-upcasting/normalization.rs20
2 files changed, 32 insertions, 2 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 3cf2735b46b..3d6df08f6db 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -887,9 +887,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { bug!() };
 
         let source_principal = a_data.principal().unwrap().with_self_ty(tcx, a_ty);
-        let upcast_principal = util::supertraits(tcx, source_principal).nth(idx).unwrap();
+        let unnormalized_upcast_principal =
+            util::supertraits(tcx, source_principal).nth(idx).unwrap();
 
         let mut nested = vec![];
+        let upcast_principal = normalize_with_depth_to(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            unnormalized_upcast_principal,
+            &mut nested,
+        );
+
         for bound in b_data {
             match bound.skip_binder() {
                 // Check that a's supertrait (upcast_principal) is compatible
@@ -973,7 +983,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     }
                     VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
                         vptr_offset += count_own_vtable_entries(tcx, trait_ref);
-                        if trait_ref == upcast_principal {
+                        if trait_ref == unnormalized_upcast_principal {
                             if emit_vptr {
                                 return ControlFlow::Break(Some(vptr_offset));
                             } else {
diff --git a/tests/ui/traits/trait-upcasting/normalization.rs b/tests/ui/traits/trait-upcasting/normalization.rs
new file mode 100644
index 00000000000..c78338b0da9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/normalization.rs
@@ -0,0 +1,20 @@
+// check-pass
+// issue: 114113
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
+#![feature(trait_upcasting)]
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+trait Bar<T> {}
+trait Foo<T>: Bar<<T as Mirror>::Assoc> {}
+
+fn upcast<T>(x: &dyn Foo<T>) -> &dyn Bar<T> { x }
+
+fn main() {}