about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs5
-rw-r--r--compiler/rustc_middle/src/hir/place.rs4
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs2
8 files changed, 30 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index 9de4f82a06b..e91103f2130 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -457,7 +457,16 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         ty: Ty<'tcx>,
         kind: ProjectionKind,
     ) -> PlaceWithHirId<'tcx> {
+        let place_ty = base_place.place.ty();
         let mut projections = base_place.place.projections;
+
+        let node_ty = self.typeck_results.node_type(node.hir_id());
+        // Opaque types can't have field projections, but we can instead convert
+        // the current place in-place (heh) to the hidden type, and then apply all
+        // follow up projections on that.
+        if node_ty != place_ty && place_ty.has_opaque_types() {
+            projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty });
+        }
         projections.push(Projection { kind, ty });
         PlaceWithHirId::new(
             node.hir_id(),
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 62eff4bab86..facbb4b3cf8 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -673,6 +673,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     match (p1.kind, p2.kind) {
                         // Paths are the same, continue to next loop.
                         (ProjectionKind::Deref, ProjectionKind::Deref) => {}
+                        (ProjectionKind::OpaqueCast, ProjectionKind::OpaqueCast) => {}
                         (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
                             if i1 == i2 => {}
 
@@ -695,10 +696,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             l @ (ProjectionKind::Index
                             | ProjectionKind::Subslice
                             | ProjectionKind::Deref
+                            | ProjectionKind::OpaqueCast
                             | ProjectionKind::Field(..)),
                             r @ (ProjectionKind::Index
                             | ProjectionKind::Subslice
                             | ProjectionKind::Deref
+                            | ProjectionKind::OpaqueCast
                             | ProjectionKind::Field(..)),
                         ) => bug!(
                             "ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
@@ -1885,6 +1888,7 @@ fn restrict_capture_precision(
                 return (place, curr_mode);
             }
             ProjectionKind::Deref => {}
+            ProjectionKind::OpaqueCast => {}
             ProjectionKind::Field(..) => {} // ignore
         }
     }
@@ -1941,6 +1945,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
             ProjectionKind::Deref => String::from("Deref"),
             ProjectionKind::Index => String::from("Index"),
             ProjectionKind::Subslice => String::from("Subslice"),
+            ProjectionKind::OpaqueCast => String::from("OpaqueCast"),
         };
         if i != 0 {
             projections_str.push(',');
diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs
index 8a22de931c3..32f3a177508 100644
--- a/compiler/rustc_middle/src/hir/place.rs
+++ b/compiler/rustc_middle/src/hir/place.rs
@@ -36,6 +36,10 @@ pub enum ProjectionKind {
 
     /// A subslice covering a range of values like `B[x..y]`.
     Subslice,
+
+    /// A conversion from an opaque type to its hidden type so we can
+    /// do further projections on it.
+    OpaqueCast,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 91eefa2c125..6cf4fef1d04 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -174,6 +174,8 @@ impl<'tcx> CapturedPlace<'tcx> {
                 // Ignore derefs for now, as they are likely caused by
                 // autoderefs that don't appear in the original code.
                 HirProjectionKind::Deref => {}
+                // Just change the type to the hidden type, so we can actually project.
+                HirProjectionKind::OpaqueCast => {}
                 proj => bug!("Unexpected projection {:?} in captured place", proj),
             }
             ty = proj.ty;
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 7756d5d4879..2e7ef265a93 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -236,6 +236,9 @@ fn strip_prefix<'a, 'tcx>(
                 }
                 assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
             }
+            HirProjectionKind::OpaqueCast => {
+                assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..)));
+            }
             HirProjectionKind::Index | HirProjectionKind::Subslice => {
                 bug!("unexpected projection kind: {:?}", projection);
             }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 711a9126c04..2f0f71a8dc6 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1074,6 +1074,9 @@ impl<'tcx> Cx<'tcx> {
                     variant_index,
                     name: field,
                 },
+                HirProjectionKind::OpaqueCast => {
+                    ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) }
+                }
                 HirProjectionKind::Index | HirProjectionKind::Subslice => {
                     // We don't capture these projections, so we can ignore them here
                     continue;
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 5d7e1494fcf..a43a81bc63a 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -1011,6 +1011,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         },
                         // note: unable to trigger `Subslice` kind in tests
                         ProjectionKind::Subslice => (),
+                        // Doesn't have surface syntax. Only occurs in patterns.
+                        ProjectionKind::OpaqueCast => (),
                         ProjectionKind::Deref => {
                             // Explicit derefs are typically handled later on, but
                             // some items do not need explicit deref, such as array accesses,
diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
index 2c740ccc1ae..fdd8fa65bd0 100644
--- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
@@ -1,5 +1,7 @@
 #![feature(type_alias_impl_trait)]
 // check-pass
+// revisions: default edition2021
+//[edition2021] compile-flags: --edition 2021
 
 fn main() {
     type T = impl Copy;