add the AscribeUserType statement kind
Make it have the semantics of subtype.
This commit is contained in:
parent
22f9bcce04
commit
dd3cc9669a
22 changed files with 134 additions and 78 deletions
|
|
@ -255,9 +255,9 @@ for mir::StatementKind<'gcx> {
|
|||
op.hash_stable(hcx, hasher);
|
||||
places.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::UserAssertTy(ref c_ty, ref local) => {
|
||||
mir::StatementKind::AscribeUserType(ref place, ref c_ty) => {
|
||||
place.hash_stable(hcx, hasher);
|
||||
c_ty.hash_stable(hcx, hasher);
|
||||
local.hash_stable(hcx, hasher);
|
||||
}
|
||||
mir::StatementKind::Nop => {}
|
||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
|
|
|
|||
|
|
@ -1636,22 +1636,14 @@ pub enum StatementKind<'tcx> {
|
|||
/// (The starting point(s) arise implicitly from borrows.)
|
||||
EndRegion(region::Scope),
|
||||
|
||||
/// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
|
||||
/// them. For example:
|
||||
/// Encodes a user's type ascription. These need to be preserved
|
||||
/// intact so that NLL can respect them. For example:
|
||||
///
|
||||
/// let (a, b): (T, U) = y;
|
||||
/// let a: T = y;
|
||||
///
|
||||
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
|
||||
/// is the right thing.
|
||||
///
|
||||
/// `CanonicalTy` is used to capture "inference variables" from the user's types. For example:
|
||||
///
|
||||
/// let x: Vec<_> = ...;
|
||||
/// let y: &u32 = ...;
|
||||
///
|
||||
/// would result in `Vec<?0>` and `&'?0 u32` respectively (where `?0` is a canonicalized
|
||||
/// variable).
|
||||
UserAssertTy(CanonicalTy<'tcx>, Local),
|
||||
/// Here we would insert a `AscribeUserType` that ensures that the
|
||||
/// type `Y` of `y` is a subtype of `T` (`Y <: T`).
|
||||
AscribeUserType(Place<'tcx>, CanonicalTy<'tcx>),
|
||||
|
||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||
Nop,
|
||||
|
|
@ -1728,8 +1720,8 @@ impl<'tcx> Debug for Statement<'tcx> {
|
|||
ref outputs,
|
||||
ref inputs,
|
||||
} => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
|
||||
UserAssertTy(ref c_ty, ref local) => {
|
||||
write!(fmt, "UserAssertTy({:?}, {:?})", c_ty, local)
|
||||
AscribeUserType(ref place, ref c_ty) => {
|
||||
write!(fmt, "AscribeUserType({:?}, {:?})", place, c_ty)
|
||||
}
|
||||
Nop => write!(fmt, "nop"),
|
||||
}
|
||||
|
|
@ -2652,7 +2644,7 @@ EnumTypeFoldableImpl! {
|
|||
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
||||
(StatementKind::Validate)(a, b),
|
||||
(StatementKind::EndRegion)(a),
|
||||
(StatementKind::UserAssertTy)(a, b),
|
||||
(StatementKind::AscribeUserType)(a, b),
|
||||
(StatementKind::Nop),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,11 +144,11 @@ macro_rules! make_mir_visitor {
|
|||
self.super_operand(operand, location);
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(&mut self,
|
||||
c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
local: & $($mutability)* Local,
|
||||
location: Location) {
|
||||
self.super_user_assert_ty(c_ty, local, location);
|
||||
fn visit_ascribe_user_ty(&mut self,
|
||||
place: & $($mutability)* Place<'tcx>,
|
||||
c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
location: Location) {
|
||||
self.super_ascribe_user_ty(place, c_ty, location);
|
||||
}
|
||||
|
||||
fn visit_place(&mut self,
|
||||
|
|
@ -386,9 +386,11 @@ macro_rules! make_mir_visitor {
|
|||
self.visit_operand(input, location);
|
||||
}
|
||||
}
|
||||
StatementKind::UserAssertTy(ref $($mutability)* c_ty,
|
||||
ref $($mutability)* local) => {
|
||||
self.visit_user_assert_ty(c_ty, local, location);
|
||||
StatementKind::AscribeUserType(
|
||||
ref $($mutability)* place,
|
||||
ref $($mutability)* c_ty,
|
||||
) => {
|
||||
self.visit_ascribe_user_ty(place, c_ty, location);
|
||||
}
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
|
|
@ -629,12 +631,12 @@ macro_rules! make_mir_visitor {
|
|||
}
|
||||
}
|
||||
|
||||
fn super_user_assert_ty(&mut self,
|
||||
c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
local: & $($mutability)* Local,
|
||||
location: Location) {
|
||||
fn super_ascribe_user_ty(&mut self,
|
||||
place: & $($mutability)* Place<'tcx>,
|
||||
c_ty: & $($mutability)* CanonicalTy<'tcx>,
|
||||
location: Location) {
|
||||
self.visit_place(place, PlaceContext::Validate, location);
|
||||
self.visit_canonical_ty(c_ty);
|
||||
self.visit_local(local, PlaceContext::Validate, location);
|
||||
}
|
||||
|
||||
fn super_place(&mut self,
|
||||
|
|
|
|||
|
|
@ -356,8 +356,8 @@ pub struct TypeckTables<'tcx> {
|
|||
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
|
||||
field_indices: ItemLocalMap<usize>,
|
||||
|
||||
/// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in
|
||||
/// MIR.
|
||||
/// Stores the canonicalized types provided by the user. See also
|
||||
/// `AscribeUserType` statement in MIR.
|
||||
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
|
||||
|
||||
/// Stores the types for various nodes in the AST. Note that this table
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
|
|||
mir::StatementKind::ReadForMatch(_) |
|
||||
mir::StatementKind::EndRegion(_) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::AscribeUserType(..) |
|
||||
mir::StatementKind::Nop => bx,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,10 +535,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
|||
// flow_state already handled).
|
||||
}
|
||||
StatementKind::Nop
|
||||
| StatementKind::UserAssertTy(..)
|
||||
| StatementKind::AscribeUserType(..)
|
||||
| StatementKind::Validate(..)
|
||||
| StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
|
||||
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
|
||||
// to borrow check.
|
||||
}
|
||||
StatementKind::StorageDead(local) => {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use rustc::infer::InferCtxt;
|
|||
use rustc::mir::visit::TyContext;
|
||||
use rustc::mir::visit::Visitor;
|
||||
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
|
||||
use rustc::mir::{Local, Statement, Terminator};
|
||||
use rustc::mir::{Statement, Terminator};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid};
|
||||
|
|
@ -175,10 +175,10 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
|
|||
self.super_terminator(block, terminator, location);
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(
|
||||
fn visit_ascribe_user_ty(
|
||||
&mut self,
|
||||
_place: &Place<'tcx>,
|
||||
_c_ty: &CanonicalTy<'tcx>,
|
||||
_local: &Local,
|
||||
_location: Location,
|
||||
) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
|
|||
// EndRegion matters to older NLL/MIR AST borrowck, not to alias NLL
|
||||
StatementKind::EndRegion(..) |
|
||||
StatementKind::Nop |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::AscribeUserType(..) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
|
||||
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
|
||||
// to borrow check.
|
||||
}
|
||||
StatementKind::StorageDead(local) => {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
|
||||
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
|
||||
use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
|
||||
use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
|
||||
|
||||
|
|
@ -112,8 +112,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
|
|||
debug!("visit_closure_substs: substs={:?}", substs);
|
||||
}
|
||||
|
||||
fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local,
|
||||
_location: Location) {
|
||||
fn visit_ascribe_user_ty(
|
||||
&mut self,
|
||||
_place: &mut Place<'tcx>,
|
||||
_c_ty: &mut CanonicalTy<'tcx>,
|
||||
_location: Location,
|
||||
) {
|
||||
// User-assert-ty statements represent types that the user added explicitly.
|
||||
// We don't want to erase the regions from these types: rather, we want to
|
||||
// add them as constraints at type-check time.
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
if let Some(user_ty) = constant.user_ty {
|
||||
if let Err(terr) =
|
||||
self.cx
|
||||
.eq_canonical_type_and_type(user_ty, constant.ty, location.boring())
|
||||
.eq_user_type_and_type(user_ty, constant.ty, location.boring())
|
||||
{
|
||||
span_mirbug!(
|
||||
self,
|
||||
|
|
@ -850,13 +850,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn eq_canonical_type_and_type(
|
||||
fn sub_type_and_user_type(
|
||||
&mut self,
|
||||
a: Ty<'tcx>,
|
||||
b: CanonicalTy<'tcx>,
|
||||
locations: Locations,
|
||||
) -> Fallible<()> {
|
||||
relate_tys::sub_type_and_user_type(
|
||||
self.infcx,
|
||||
a,
|
||||
b,
|
||||
locations,
|
||||
self.borrowck_context.as_mut().map(|x| &mut **x),
|
||||
)
|
||||
}
|
||||
|
||||
fn eq_user_type_and_type(
|
||||
&mut self,
|
||||
a: CanonicalTy<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
locations: Locations,
|
||||
) -> Fallible<()> {
|
||||
relate_tys::eq_canonical_type_and_type(
|
||||
relate_tys::eq_user_type_and_type(
|
||||
self.infcx,
|
||||
a,
|
||||
b,
|
||||
|
|
@ -905,7 +920,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
if let Some(user_ty) = self.rvalue_user_ty(rv) {
|
||||
if let Err(terr) = self.eq_canonical_type_and_type(
|
||||
if let Err(terr) = self.eq_user_type_and_type(
|
||||
user_ty,
|
||||
rv_ty,
|
||||
location.boring(),
|
||||
|
|
@ -955,15 +970,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
};
|
||||
}
|
||||
StatementKind::UserAssertTy(c_ty, local) => {
|
||||
let local_ty = mir.local_decls()[local].ty;
|
||||
if let Err(terr) = self.eq_canonical_type_and_type(c_ty, local_ty, Locations::All) {
|
||||
StatementKind::AscribeUserType(ref place, c_ty) => {
|
||||
let place_ty = place.ty(mir, tcx).to_ty(tcx);
|
||||
if let Err(terr) = self.sub_type_and_user_type(place_ty, c_ty, Locations::All) {
|
||||
span_mirbug!(
|
||||
self,
|
||||
stmt,
|
||||
"bad type assert ({:?} = {:?}): {:?}",
|
||||
"bad type assert ({:?} <: {:?}): {:?}",
|
||||
place_ty,
|
||||
c_ty,
|
||||
local_ty,
|
||||
terr
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ use rustc::ty::{self, CanonicalTy, CanonicalVar, RegionVid, Ty, TyCtxt};
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a <: b`.
|
||||
pub(super) fn sub_types<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
|
|
@ -40,6 +41,7 @@ pub(super) fn sub_types<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a == b`.
|
||||
pub(super) fn eq_types<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
|
|
@ -58,7 +60,43 @@ pub(super) fn eq_types<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn eq_canonical_type_and_type<'tcx>(
|
||||
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
|
||||
/// a user-given type (which means it may have canonical variables
|
||||
/// encoding things like `_`).
|
||||
pub(super) fn sub_type_and_user_type<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
b: CanonicalTy<'tcx>,
|
||||
locations: Locations,
|
||||
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
|
||||
) -> Fallible<()> {
|
||||
debug!(
|
||||
"sub_type_and_user_type(a={:?}, b={:?}, locations={:?})",
|
||||
a, b, locations
|
||||
);
|
||||
let Canonical {
|
||||
variables: b_variables,
|
||||
value: b_value,
|
||||
} = b;
|
||||
|
||||
// (*) The `TypeRelating` code assumes that the "canonical variables"
|
||||
// appear in the "a" side, so start with `Contravariant` ambient
|
||||
// variance to get the right relationship.
|
||||
|
||||
TypeRelating::new(
|
||||
infcx,
|
||||
ty::Variance::Contravariant, // (*)
|
||||
locations,
|
||||
borrowck_context,
|
||||
b_variables,
|
||||
).relate(&b_value, &a)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
|
||||
/// a user-given type (which means it may have canonical variables
|
||||
/// encoding things like `_`).
|
||||
pub(super) fn eq_user_type_and_type<'tcx>(
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
a: CanonicalTy<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
|
|
@ -66,16 +104,21 @@ pub(super) fn eq_canonical_type_and_type<'tcx>(
|
|||
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
|
||||
) -> Fallible<()> {
|
||||
debug!(
|
||||
"eq_canonical_type_and_type(a={:?}, b={:?}, locations={:?})",
|
||||
"eq_user_type_and_type(a={:?}, b={:?}, locations={:?})",
|
||||
a, b, locations
|
||||
);
|
||||
let Canonical {
|
||||
variables: a_variables,
|
||||
value: a_value,
|
||||
} = a;
|
||||
|
||||
// (*) The `TypeRelating` code assumes that the "canonical variables"
|
||||
// appear in the "a" side, so start with `Contravariant` ambient
|
||||
// variance to get the right relationship.
|
||||
|
||||
TypeRelating::new(
|
||||
infcx,
|
||||
ty::Variance::Invariant,
|
||||
ty::Variance::Invariant, // (*)
|
||||
locations,
|
||||
borrowck_context,
|
||||
a_variables,
|
||||
|
|
|
|||
|
|
@ -338,7 +338,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
|||
mir::StatementKind::SetDiscriminant { .. } |
|
||||
mir::StatementKind::StorageLive(..) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::AscribeUserType(..) |
|
||||
mir::StatementKind::Nop => {}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
|||
}
|
||||
StatementKind::EndRegion(_) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::AscribeUserType(..) |
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
|||
}
|
||||
|
||||
EndRegion(..) => {}
|
||||
UserAssertTy(..) => {}
|
||||
AscribeUserType(..) => {}
|
||||
|
||||
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
||||
// size of MIR constantly.
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
|||
StatementKind::StorageDead(..) |
|
||||
StatementKind::EndRegion(..) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::AscribeUserType(..) |
|
||||
StatementKind::Nop => {
|
||||
// safe (at least as emitted during MIR construction)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
//!
|
||||
//! - `CleanEndRegions`, that reduces the set of `EndRegion` statements
|
||||
//! in the MIR.
|
||||
//! - `CleanUserAssertTy`, that replaces all `UserAssertTy` statements
|
||||
//! - `CleanAscribeUserType`, that replaces all `AscribeUserType` statements
|
||||
//! with `Nop`.
|
||||
//!
|
||||
//! The `CleanEndRegions` "pass" is actually implemented as two
|
||||
|
|
@ -24,10 +24,10 @@
|
|||
//! MIR and removes any `EndRegion` that is applied to a region that
|
||||
//! was not seen in the previous pass.
|
||||
//!
|
||||
//! The `CleanUserAssertTy` pass runs at a distinct time from the
|
||||
//! `CleanEndRegions` pass. It is important that the `CleanUserAssertTy`
|
||||
//! The `CleanAscribeUserType` pass runs at a distinct time from the
|
||||
//! `CleanEndRegions` pass. It is important that the `CleanAscribeUserType`
|
||||
//! pass runs after the MIR borrowck so that the NLL type checker can
|
||||
//! perform the type assertion when it encounters the `UserAssertTy`
|
||||
//! perform the type assertion when it encounters the `AscribeUserType`
|
||||
//! statements.
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
@ -110,26 +110,26 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CleanUserAssertTy;
|
||||
pub struct CleanAscribeUserType;
|
||||
|
||||
pub struct DeleteUserAssertTy;
|
||||
pub struct DeleteAscribeUserType;
|
||||
|
||||
impl MirPass for CleanUserAssertTy {
|
||||
impl MirPass for CleanAscribeUserType {
|
||||
fn run_pass<'a, 'tcx>(&self,
|
||||
_tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
_source: MirSource,
|
||||
mir: &mut Mir<'tcx>) {
|
||||
let mut delete = DeleteUserAssertTy;
|
||||
let mut delete = DeleteAscribeUserType;
|
||||
delete.visit_mir(mir);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for DeleteUserAssertTy {
|
||||
impl<'tcx> MutVisitor<'tcx> for DeleteAscribeUserType {
|
||||
fn visit_statement(&mut self,
|
||||
block: BasicBlock,
|
||||
statement: &mut Statement<'tcx>,
|
||||
location: Location) {
|
||||
if let StatementKind::UserAssertTy(..) = statement.kind {
|
||||
if let StatementKind::AscribeUserType(..) = statement.kind {
|
||||
statement.make_nop();
|
||||
}
|
||||
self.super_statement(block, statement, location);
|
||||
|
|
|
|||
|
|
@ -238,8 +238,8 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
|
|||
simplify_branches::SimplifyBranches::new("initial"),
|
||||
remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
simplify::SimplifyCfg::new("early-opt"),
|
||||
// Remove all `UserAssertTy` statements.
|
||||
cleanup_post_borrowck::CleanUserAssertTy,
|
||||
// Remove all `AscribeUserType` statements.
|
||||
cleanup_post_borrowck::CleanAscribeUserType,
|
||||
|
||||
// These next passes must be executed together
|
||||
add_call_guards::CriticalCallEdges,
|
||||
|
|
|
|||
|
|
@ -1098,7 +1098,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
|
|||
StatementKind::InlineAsm {..} |
|
||||
StatementKind::EndRegion(_) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::AscribeUserType(..) |
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl RemoveNoopLandingPads {
|
|||
StatementKind::StorageLive(_) |
|
||||
StatementKind::StorageDead(_) |
|
||||
StatementKind::EndRegion(_) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::AscribeUserType(..) |
|
||||
StatementKind::Nop => {
|
||||
// These are all nops in a landing pad (there's some
|
||||
// borrowck interaction between EndRegion and storage
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
mir::StatementKind::InlineAsm { .. } |
|
||||
mir::StatementKind::EndRegion(_) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::AscribeUserType(..) |
|
||||
mir::StatementKind::Nop => continue,
|
||||
mir::StatementKind::SetDiscriminant{ .. } =>
|
||||
span_bug!(stmt.source_info.span,
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
|||
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
|
||||
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
|
||||
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
|
||||
StatementKind::UserAssertTy(..) => "StatementKind::UserAssertTy",
|
||||
StatementKind::AscribeUserType(..) => "StatementKind::AscribeUserType",
|
||||
StatementKind::Nop => "StatementKind::Nop",
|
||||
}, &statement.kind);
|
||||
self.super_statement(block, statement, location);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ fn main() {
|
|||
// _2 = move _3;
|
||||
// StorageDead(_3);
|
||||
// StorageLive(_4);
|
||||
// UserAssertTy(Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> }, _4);
|
||||
// AscribeUserType(_4, Canonical { variables: [], value: std::option::Option<std::boxed::Box<u32>> });
|
||||
// _4 = std::option::Option<std::boxed::Box<u32>>::None;
|
||||
// StorageLive(_5);
|
||||
// StorageLive(_6);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue