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 🤔 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
This commit is contained in:
@@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user