about summary refs log tree commit diff
path: root/compiler/rustc_middle/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-23 04:15:41 +0000
committerbors <bors@rust-lang.org>2024-12-23 04:15:41 +0000
commit0eca4dd3205a01dba4bd7b7c140ec370aff03440 (patch)
treefc44790a8c2df7fe5036995644c38d9e40fb8c0b /compiler/rustc_middle/src
parent908af5ba4ad921fec81d95c97411c867cdcb33fa (diff)
parent5bced1419fbafb7fba837b992d2d70388f228f11 (diff)
Auto merge of #134465 - lcnr:type-verifier, r=compiler-errors
cleanup `TypeVerifier`

We should merge it with the `TypeChecker` as we no longer bail in cases where it encounters an error since #111863.

It's quite inconsistent whether a check lives in the verifier or the `TypeChecker`, so this feels like a quite impactful cleanup. I expect that for this we may want to change the `TypeChecker` to also be a MIR visitor :thinking: this is non-trivial so I didn't fully do it in this PR.

Best reviewed commit by commit.

r? `@compiler-errors` feel free to reassign however
Diffstat (limited to 'compiler/rustc_middle/src')
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs71
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs29
2 files changed, 75 insertions, 25 deletions
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index bbfc68aa706..cbb26b83c79 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -5,6 +5,7 @@
 
 use rustc_hir as hir;
 use tracing::{debug, instrument};
+use ty::CoroutineArgsExt;
 
 use crate::mir::*;
 
@@ -25,29 +26,63 @@ impl<'tcx> PlaceTy<'tcx> {
         PlaceTy { ty, variant_index: None }
     }
 
-    /// `place_ty.field_ty(tcx, f)` computes the type at a given field
-    /// of a record or enum-variant. (Most clients of `PlaceTy` can
-    /// instead just extract the relevant type directly from their
-    /// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
-    /// not carry a `Ty` for `T`.)
+    /// `place_ty.field_ty(tcx, f)` computes the type of a given field.
+    ///
+    /// Most clients of `PlaceTy` can instead just extract the relevant type
+    /// directly from their `PlaceElem`, but some instances of `ProjectionElem<V, T>`
+    /// do not carry a `Ty` for `T`.
     ///
     /// Note that the resulting type has not been normalized.
     #[instrument(level = "debug", skip(tcx), ret)]
     pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: FieldIdx) -> Ty<'tcx> {
-        match self.ty.kind() {
-            ty::Adt(adt_def, args) => {
-                let variant_def = match self.variant_index {
-                    None => adt_def.non_enum_variant(),
-                    Some(variant_index) => {
-                        assert!(adt_def.is_enum());
-                        adt_def.variant(variant_index)
-                    }
-                };
-                let field_def = &variant_def.fields[f];
-                field_def.ty(tcx, args)
+        if let Some(variant_index) = self.variant_index {
+            match *self.ty.kind() {
+                ty::Adt(adt_def, args) if adt_def.is_enum() => {
+                    adt_def.variant(variant_index).fields[f].ty(tcx, args)
+                }
+                ty::Coroutine(def_id, args) => {
+                    let mut variants = args.as_coroutine().state_tys(def_id, tcx);
+                    let Some(mut variant) = variants.nth(variant_index.into()) else {
+                        bug!("variant {variant_index:?} of coroutine out of range: {self:?}");
+                    };
+
+                    variant
+                        .nth(f.index())
+                        .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}"))
+                }
+                _ => bug!("can't downcast non-adt non-coroutine type: {self:?}"),
+            }
+        } else {
+            match self.ty.kind() {
+                ty::Adt(adt_def, args) if !adt_def.is_enum() => {
+                    adt_def.non_enum_variant().fields[f].ty(tcx, args)
+                }
+                ty::Closure(_, args) => args
+                    .as_closure()
+                    .upvar_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                ty::CoroutineClosure(_, args) => args
+                    .as_coroutine_closure()
+                    .upvar_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                // Only prefix fields (upvars and current state) are
+                // accessible without a variant index.
+                ty::Coroutine(_, args) => args
+                    .as_coroutine()
+                    .prefix_tys()
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                ty::Tuple(tys) => tys
+                    .get(f.index())
+                    .copied()
+                    .unwrap_or_else(|| bug!("field {f:?} out of range: {self:?}")),
+                _ => bug!("can't project out of {self:?}"),
             }
-            ty::Tuple(tys) => tys[f.index()],
-            _ => bug!("extracting field of non-tuple non-adt: {:?}", self),
         }
     }
 
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 899eb9f7f47..12a024a219e 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1361,12 +1361,12 @@ pub enum PlaceContext {
 impl PlaceContext {
     /// Returns `true` if this place context represents a drop.
     #[inline]
-    pub fn is_drop(&self) -> bool {
+    pub fn is_drop(self) -> bool {
         matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
     }
 
     /// Returns `true` if this place context represents a borrow.
-    pub fn is_borrow(&self) -> bool {
+    pub fn is_borrow(self) -> bool {
         matches!(
             self,
             PlaceContext::NonMutatingUse(
@@ -1376,7 +1376,7 @@ impl PlaceContext {
     }
 
     /// Returns `true` if this place context represents an address-of.
-    pub fn is_address_of(&self) -> bool {
+    pub fn is_address_of(self) -> bool {
         matches!(
             self,
             PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow)
@@ -1386,7 +1386,7 @@ impl PlaceContext {
 
     /// Returns `true` if this place context represents a storage live or storage dead marker.
     #[inline]
-    pub fn is_storage_marker(&self) -> bool {
+    pub fn is_storage_marker(self) -> bool {
         matches!(
             self,
             PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
@@ -1395,18 +1395,18 @@ impl PlaceContext {
 
     /// Returns `true` if this place context represents a use that potentially changes the value.
     #[inline]
-    pub fn is_mutating_use(&self) -> bool {
+    pub fn is_mutating_use(self) -> bool {
         matches!(self, PlaceContext::MutatingUse(..))
     }
 
     /// Returns `true` if this place context represents a use.
     #[inline]
-    pub fn is_use(&self) -> bool {
+    pub fn is_use(self) -> bool {
         !matches!(self, PlaceContext::NonUse(..))
     }
 
     /// Returns `true` if this place context represents an assignment statement.
-    pub fn is_place_assignment(&self) -> bool {
+    pub fn is_place_assignment(self) -> bool {
         matches!(
             self,
             PlaceContext::MutatingUse(
@@ -1416,4 +1416,19 @@ impl PlaceContext {
             )
         )
     }
+
+    /// The variance of a place in the given context.
+    pub fn ambient_variance(self) -> ty::Variance {
+        use NonMutatingUseContext::*;
+        use NonUseContext::*;
+        match self {
+            PlaceContext::MutatingUse(_) => ty::Invariant,
+            PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+            PlaceContext::NonMutatingUse(
+                Inspect | Copy | Move | PlaceMention | SharedBorrow | FakeBorrow | RawBorrow
+                | Projection,
+            ) => ty::Covariant,
+            PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
+        }
+    }
 }