about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs47
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr (renamed from tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr)2
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr15
-rw-r--r--tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs3
6 files changed, 70 insertions, 12 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 86cd8b918fc..2558cf6347d 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -7,6 +7,7 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Upcast};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
+use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
 use rustc_trait_selection::traits::ObligationCause;
 
@@ -166,6 +167,52 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     }
 
     #[instrument(skip(self), level = "debug")]
+    pub(super) fn struct_tail(
+        &mut self,
+        ty: Ty<'tcx>,
+        location: impl NormalizeLocation,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+        if self.infcx.next_trait_solver() {
+            let body = self.body;
+            let param_env = self.param_env;
+            self.fully_perform_op(
+                location.to_locations(),
+                ConstraintCategory::Boring,
+                CustomTypeOp::new(
+                    |ocx| {
+                        let structurally_normalize = |ty| {
+                            ocx.structurally_normalize(
+                                &ObligationCause::misc(
+                                    location.to_locations().span(body),
+                                    body.source.def_id().expect_local(),
+                                ),
+                                param_env,
+                                ty,
+                            )
+                            .unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR"))
+                        };
+
+                        let tail = tcx.struct_tail_with_normalize(
+                            ty,
+                            structurally_normalize,
+                            || {},
+                        );
+
+                        Ok(tail)
+                    },
+                    "normalizing struct tail",
+                ),
+            )
+            .unwrap_or_else(|guar| Ty::new_error(tcx, guar))
+        } else {
+            let mut normalize = |ty| self.normalize(ty, location);
+            let tail = tcx.struct_tail_with_normalize(ty, &mut normalize, || {});
+            normalize(tail)
+        }
+    }
+
+    #[instrument(skip(self), level = "debug")]
     pub(super) fn ascribe_user_type(
         &mut self,
         mir_ty: Ty<'tcx>,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index b13773ffe14..6bab0f33c19 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2329,17 +2329,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
                             (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
-                                let mut normalize = |t| self.normalize(t, location);
-
-                                // N.B. `struct_tail_with_normalize` only "structurally resolves"
-                                // the type. It is not fully normalized, so we have to normalize it
-                                // afterwards.
-                                let src_tail =
-                                    tcx.struct_tail_with_normalize(src.ty, &mut normalize, || ());
-                                let src_tail = normalize(src_tail);
-                                let dst_tail =
-                                    tcx.struct_tail_with_normalize(dst.ty, &mut normalize, || ());
-                                let dst_tail = normalize(dst_tail);
+                                let src_tail = self.struct_tail(src.ty, location);
+                                let dst_tail = self.struct_tail(dst.ty, location);
 
                                 // This checks (lifetime part of) vtable validity for pointer casts,
                                 // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index de702733904..7cd97166ed1 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -97,6 +97,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return Ok(Some(PointerKind::Thin));
         }
 
+        let t = self.try_structurally_resolve_type(span, t);
+
         Ok(match *t.kind() {
             ty::Slice(_) | ty::Str => Some(PointerKind::Length),
             ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)),
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr
index d1d598e603f..5a5b4bfcacf 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.stderr
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.current.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:21:17
+  --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
    |
 LL | fn m<'a>() {
    |      -- lifetime `'a` defined here
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr
new file mode 100644
index 00000000000..5a5b4bfcacf
--- /dev/null
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.next.stderr
@@ -0,0 +1,15 @@
+error: lifetime may not live long enough
+  --> $DIR/ptr-to-trait-obj-different-regions-id-trait.rs:24:17
+   |
+LL | fn m<'a>() {
+   |      -- lifetime `'a` defined here
+LL |     let unsend: *const dyn Cat<'a> = &();
+LL |     let _send = unsend as *const S<dyn Cat<'static>>;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = note: requirement occurs because of the type `S<dyn Cat<'_>>`, which makes the generic argument `dyn Cat<'_>` invariant
+   = note: the struct `S<T>` is invariant over the parameter `T`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
index cdd55e24392..f968dca4fd3 100644
--- a/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
+++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-id-trait.rs
@@ -1,3 +1,6 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 //@ check-fail
 //
 // Make sure we can't trick the compiler by using a projection.