Skip to content

Commit dd3cc96

Browse files
committed
add the AscribeUserType statement kind
Make it have the semantics of subtype.
1 parent 22f9bcc commit dd3cc96

File tree

22 files changed

+134
-78
lines changed

22 files changed

+134
-78
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ for mir::StatementKind<'gcx> {
255255
op.hash_stable(hcx, hasher);
256256
places.hash_stable(hcx, hasher);
257257
}
258-
mir::StatementKind::UserAssertTy(ref c_ty, ref local) => {
258+
mir::StatementKind::AscribeUserType(ref place, ref c_ty) => {
259+
place.hash_stable(hcx, hasher);
259260
c_ty.hash_stable(hcx, hasher);
260-
local.hash_stable(hcx, hasher);
261261
}
262262
mir::StatementKind::Nop => {}
263263
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {

src/librustc/mir/mod.rs

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,22 +1636,14 @@ pub enum StatementKind<'tcx> {
16361636
/// (The starting point(s) arise implicitly from borrows.)
16371637
EndRegion(region::Scope),
16381638

1639-
/// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
1640-
/// them. For example:
1639+
/// Encodes a user's type ascription. These need to be preserved
1640+
/// intact so that NLL can respect them. For example:
16411641
///
1642-
/// let (a, b): (T, U) = y;
1642+
/// let a: T = y;
16431643
///
1644-
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
1645-
/// is the right thing.
1646-
///
1647-
/// `CanonicalTy` is used to capture "inference variables" from the user's types. For example:
1648-
///
1649-
/// let x: Vec<_> = ...;
1650-
/// let y: &u32 = ...;
1651-
///
1652-
/// would result in `Vec<?0>` and `&'?0 u32` respectively (where `?0` is a canonicalized
1653-
/// variable).
1654-
UserAssertTy(CanonicalTy<'tcx>, Local),
1644+
/// Here we would insert a `AscribeUserType` that ensures that the
1645+
/// type `Y` of `y` is a subtype of `T` (`Y <: T`).
1646+
AscribeUserType(Place<'tcx>, CanonicalTy<'tcx>),
16551647

16561648
/// No-op. Useful for deleting instructions without affecting statement indices.
16571649
Nop,
@@ -1728,8 +1720,8 @@ impl<'tcx> Debug for Statement<'tcx> {
17281720
ref outputs,
17291721
ref inputs,
17301722
} => write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs),
1731-
UserAssertTy(ref c_ty, ref local) => {
1732-
write!(fmt, "UserAssertTy({:?}, {:?})", c_ty, local)
1723+
AscribeUserType(ref place, ref c_ty) => {
1724+
write!(fmt, "AscribeUserType({:?}, {:?})", place, c_ty)
17331725
}
17341726
Nop => write!(fmt, "nop"),
17351727
}
@@ -2652,7 +2644,7 @@ EnumTypeFoldableImpl! {
26522644
(StatementKind::InlineAsm) { asm, outputs, inputs },
26532645
(StatementKind::Validate)(a, b),
26542646
(StatementKind::EndRegion)(a),
2655-
(StatementKind::UserAssertTy)(a, b),
2647+
(StatementKind::AscribeUserType)(a, b),
26562648
(StatementKind::Nop),
26572649
}
26582650
}

src/librustc/mir/visit.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,11 @@ macro_rules! make_mir_visitor {
144144
self.super_operand(operand, location);
145145
}
146146

147-
fn visit_user_assert_ty(&mut self,
148-
c_ty: & $($mutability)* CanonicalTy<'tcx>,
149-
local: & $($mutability)* Local,
150-
location: Location) {
151-
self.super_user_assert_ty(c_ty, local, location);
147+
fn visit_ascribe_user_ty(&mut self,
148+
place: & $($mutability)* Place<'tcx>,
149+
c_ty: & $($mutability)* CanonicalTy<'tcx>,
150+
location: Location) {
151+
self.super_ascribe_user_ty(place, c_ty, location);
152152
}
153153

154154
fn visit_place(&mut self,
@@ -386,9 +386,11 @@ macro_rules! make_mir_visitor {
386386
self.visit_operand(input, location);
387387
}
388388
}
389-
StatementKind::UserAssertTy(ref $($mutability)* c_ty,
390-
ref $($mutability)* local) => {
391-
self.visit_user_assert_ty(c_ty, local, location);
389+
StatementKind::AscribeUserType(
390+
ref $($mutability)* place,
391+
ref $($mutability)* c_ty,
392+
) => {
393+
self.visit_ascribe_user_ty(place, c_ty, location);
392394
}
393395
StatementKind::Nop => {}
394396
}
@@ -629,12 +631,12 @@ macro_rules! make_mir_visitor {
629631
}
630632
}
631633

632-
fn super_user_assert_ty(&mut self,
633-
c_ty: & $($mutability)* CanonicalTy<'tcx>,
634-
local: & $($mutability)* Local,
635-
location: Location) {
634+
fn super_ascribe_user_ty(&mut self,
635+
place: & $($mutability)* Place<'tcx>,
636+
c_ty: & $($mutability)* CanonicalTy<'tcx>,
637+
location: Location) {
638+
self.visit_place(place, PlaceContext::Validate, location);
636639
self.visit_canonical_ty(c_ty);
637-
self.visit_local(local, PlaceContext::Validate, location);
638640
}
639641

640642
fn super_place(&mut self,

src/librustc/ty/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ pub struct TypeckTables<'tcx> {
356356
/// belongs, but it may not exist if it's a tuple field (`tuple.0`).
357357
field_indices: ItemLocalMap<usize>,
358358

359-
/// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in
360-
/// MIR.
359+
/// Stores the canonicalized types provided by the user. See also
360+
/// `AscribeUserType` statement in MIR.
361361
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
362362

363363
/// Stores the types for various nodes in the AST. Note that this table

src/librustc_codegen_llvm/mir/statement.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
9292
mir::StatementKind::ReadForMatch(_) |
9393
mir::StatementKind::EndRegion(_) |
9494
mir::StatementKind::Validate(..) |
95-
mir::StatementKind::UserAssertTy(..) |
95+
mir::StatementKind::AscribeUserType(..) |
9696
mir::StatementKind::Nop => bx,
9797
}
9898
}

src/librustc_mir/borrow_check/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
535535
// flow_state already handled).
536536
}
537537
StatementKind::Nop
538-
| StatementKind::UserAssertTy(..)
538+
| StatementKind::AscribeUserType(..)
539539
| StatementKind::Validate(..)
540540
| StatementKind::StorageLive(..) => {
541-
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
541+
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
542542
// to borrow check.
543543
}
544544
StatementKind::StorageDead(local) => {

src/librustc_mir/borrow_check/nll/constraint_generation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc::infer::InferCtxt;
1717
use rustc::mir::visit::TyContext;
1818
use rustc::mir::visit::Visitor;
1919
use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
20-
use rustc::mir::{Local, Statement, Terminator};
20+
use rustc::mir::{Statement, Terminator};
2121
use rustc::ty::fold::TypeFoldable;
2222
use rustc::ty::subst::Substs;
2323
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid};
@@ -175,10 +175,10 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
175175
self.super_terminator(block, terminator, location);
176176
}
177177

178-
fn visit_user_assert_ty(
178+
fn visit_ascribe_user_ty(
179179
&mut self,
180+
_place: &Place<'tcx>,
180181
_c_ty: &CanonicalTy<'tcx>,
181-
_local: &Local,
182182
_location: Location,
183183
) {
184184
}

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,10 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc
144144
// EndRegion matters to older NLL/MIR AST borrowck, not to alias NLL
145145
StatementKind::EndRegion(..) |
146146
StatementKind::Nop |
147-
StatementKind::UserAssertTy(..) |
147+
StatementKind::AscribeUserType(..) |
148148
StatementKind::Validate(..) |
149149
StatementKind::StorageLive(..) => {
150-
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
150+
// `Nop`, `AscribeUserType`, `Validate`, and `StorageLive` are irrelevant
151151
// to borrow check.
152152
}
153153
StatementKind::StorageDead(local) => {

src/librustc_mir/borrow_check/nll/renumber.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use rustc::ty::subst::Substs;
1212
use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
13-
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
13+
use rustc::mir::{BasicBlock, Location, Mir, Place, Statement, StatementKind};
1414
use rustc::mir::visit::{MutVisitor, TyContext};
1515
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
1616

@@ -112,8 +112,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
112112
debug!("visit_closure_substs: substs={:?}", substs);
113113
}
114114

115-
fn visit_user_assert_ty(&mut self, _c_ty: &mut CanonicalTy<'tcx>, _local: &mut Local,
116-
_location: Location) {
115+
fn visit_ascribe_user_ty(
116+
&mut self,
117+
_place: &mut Place<'tcx>,
118+
_c_ty: &mut CanonicalTy<'tcx>,
119+
_location: Location,
120+
) {
117121
// User-assert-ty statements represent types that the user added explicitly.
118122
// We don't want to erase the regions from these types: rather, we want to
119123
// add them as constraints at type-check time.

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
248248
if let Some(user_ty) = constant.user_ty {
249249
if let Err(terr) =
250250
self.cx
251-
.eq_canonical_type_and_type(user_ty, constant.ty, location.boring())
251+
.eq_user_type_and_type(user_ty, constant.ty, location.boring())
252252
{
253253
span_mirbug!(
254254
self,
@@ -850,13 +850,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
850850
)
851851
}
852852

853-
fn eq_canonical_type_and_type(
853+
fn sub_type_and_user_type(
854+
&mut self,
855+
a: Ty<'tcx>,
856+
b: CanonicalTy<'tcx>,
857+
locations: Locations,
858+
) -> Fallible<()> {
859+
relate_tys::sub_type_and_user_type(
860+
self.infcx,
861+
a,
862+
b,
863+
locations,
864+
self.borrowck_context.as_mut().map(|x| &mut **x),
865+
)
866+
}
867+
868+
fn eq_user_type_and_type(
854869
&mut self,
855870
a: CanonicalTy<'tcx>,
856871
b: Ty<'tcx>,
857872
locations: Locations,
858873
) -> Fallible<()> {
859-
relate_tys::eq_canonical_type_and_type(
874+
relate_tys::eq_user_type_and_type(
860875
self.infcx,
861876
a,
862877
b,
@@ -905,7 +920,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
905920
}
906921

907922
if let Some(user_ty) = self.rvalue_user_ty(rv) {
908-
if let Err(terr) = self.eq_canonical_type_and_type(
923+
if let Err(terr) = self.eq_user_type_and_type(
909924
user_ty,
910925
rv_ty,
911926
location.boring(),
@@ -955,15 +970,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
955970
);
956971
};
957972
}
958-
StatementKind::UserAssertTy(c_ty, local) => {
959-
let local_ty = mir.local_decls()[local].ty;
960-
if let Err(terr) = self.eq_canonical_type_and_type(c_ty, local_ty, Locations::All) {
973+
StatementKind::AscribeUserType(ref place, c_ty) => {
974+
let place_ty = place.ty(mir, tcx).to_ty(tcx);
975+
if let Err(terr) = self.sub_type_and_user_type(place_ty, c_ty, Locations::All) {
961976
span_mirbug!(
962977
self,
963978
stmt,
964-
"bad type assert ({:?} = {:?}): {:?}",
979+
"bad type assert ({:?} <: {:?}): {:?}",
980+
place_ty,
965981
c_ty,
966-
local_ty,
967982
terr
968983
);
969984
}

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::ty::{self, CanonicalTy, CanonicalVar, RegionVid, Ty, TyCtxt};
2222
use rustc_data_structures::fx::FxHashMap;
2323
use rustc_data_structures::indexed_vec::IndexVec;
2424

25+
/// Adds sufficient constraints to ensure that `a <: b`.
2526
pub(super) fn sub_types<'tcx>(
2627
infcx: &InferCtxt<'_, '_, 'tcx>,
2728
a: Ty<'tcx>,
@@ -40,6 +41,7 @@ pub(super) fn sub_types<'tcx>(
4041
Ok(())
4142
}
4243

44+
/// Adds sufficient constraints to ensure that `a == b`.
4345
pub(super) fn eq_types<'tcx>(
4446
infcx: &InferCtxt<'_, '_, 'tcx>,
4547
a: Ty<'tcx>,
@@ -58,24 +60,65 @@ pub(super) fn eq_types<'tcx>(
5860
Ok(())
5961
}
6062

61-
pub(super) fn eq_canonical_type_and_type<'tcx>(
63+
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
64+
/// a user-given type (which means it may have canonical variables
65+
/// encoding things like `_`).
66+
pub(super) fn sub_type_and_user_type<'tcx>(
67+
infcx: &InferCtxt<'_, '_, 'tcx>,
68+
a: Ty<'tcx>,
69+
b: CanonicalTy<'tcx>,
70+
locations: Locations,
71+
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
72+
) -> Fallible<()> {
73+
debug!(
74+
"sub_type_and_user_type(a={:?}, b={:?}, locations={:?})",
75+
a, b, locations
76+
);
77+
let Canonical {
78+
variables: b_variables,
79+
value: b_value,
80+
} = b;
81+
82+
// (*) The `TypeRelating` code assumes that the "canonical variables"
83+
// appear in the "a" side, so start with `Contravariant` ambient
84+
// variance to get the right relationship.
85+
86+
TypeRelating::new(
87+
infcx,
88+
ty::Variance::Contravariant, // (*)
89+
locations,
90+
borrowck_context,
91+
b_variables,
92+
).relate(&b_value, &a)?;
93+
Ok(())
94+
}
95+
96+
/// Adds sufficient constraints to ensure that `a <: b`, where `b` is
97+
/// a user-given type (which means it may have canonical variables
98+
/// encoding things like `_`).
99+
pub(super) fn eq_user_type_and_type<'tcx>(
62100
infcx: &InferCtxt<'_, '_, 'tcx>,
63101
a: CanonicalTy<'tcx>,
64102
b: Ty<'tcx>,
65103
locations: Locations,
66104
borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
67105
) -> Fallible<()> {
68106
debug!(
69-
"eq_canonical_type_and_type(a={:?}, b={:?}, locations={:?})",
107+
"eq_user_type_and_type(a={:?}, b={:?}, locations={:?})",
70108
a, b, locations
71109
);
72110
let Canonical {
73111
variables: a_variables,
74112
value: a_value,
75113
} = a;
114+
115+
// (*) The `TypeRelating` code assumes that the "canonical variables"
116+
// appear in the "a" side, so start with `Contravariant` ambient
117+
// variance to get the right relationship.
118+
76119
TypeRelating::new(
77120
infcx,
78-
ty::Variance::Invariant,
121+
ty::Variance::Invariant, // (*)
79122
locations,
80123
borrowck_context,
81124
a_variables,

src/librustc_mir/dataflow/impls/borrows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
338338
mir::StatementKind::SetDiscriminant { .. } |
339339
mir::StatementKind::StorageLive(..) |
340340
mir::StatementKind::Validate(..) |
341-
mir::StatementKind::UserAssertTy(..) |
341+
mir::StatementKind::AscribeUserType(..) |
342342
mir::StatementKind::Nop => {}
343343

344344
}

src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
304304
}
305305
StatementKind::EndRegion(_) |
306306
StatementKind::Validate(..) |
307-
StatementKind::UserAssertTy(..) |
307+
StatementKind::AscribeUserType(..) |
308308
StatementKind::Nop => {}
309309
}
310310
}

src/librustc_mir/interpret/step.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
159159
}
160160

161161
EndRegion(..) => {}
162-
UserAssertTy(..) => {}
162+
AscribeUserType(..) => {}
163163

164164
// Defined to do nothing. These are added by optimization passes, to avoid changing the
165165
// size of MIR constantly.

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
114114
StatementKind::StorageDead(..) |
115115
StatementKind::EndRegion(..) |
116116
StatementKind::Validate(..) |
117-
StatementKind::UserAssertTy(..) |
117+
StatementKind::AscribeUserType(..) |
118118
StatementKind::Nop => {
119119
// safe (at least as emitted during MIR construction)
120120
}

0 commit comments

Comments
 (0)