Skip to content

Commit ab0ef14

Browse files
committed
Auto merge of #48482 - davidtwco:issue-47184, r=nikomatsakis
NLL should identify and respect the lifetime annotations that the user wrote Part of #47184. r? @nikomatsakis
2 parents 4be5d36 + 4161ae7 commit ab0ef14

36 files changed

+358
-33
lines changed

src/librustc/ich/impls_mir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ for mir::StatementKind<'gcx> {
277277
op.hash_stable(hcx, hasher);
278278
places.hash_stable(hcx, hasher);
279279
}
280+
mir::StatementKind::UserAssertTy(ref c_ty, ref local) => {
281+
c_ty.hash_stable(hcx, hasher);
282+
local.hash_stable(hcx, hasher);
283+
}
280284
mir::StatementKind::Nop => {}
281285
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
282286
asm.hash_stable(hcx, hasher);

src/librustc/infer/canonical.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
3434
use infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TypeVariableOrigin};
3535
use rustc_data_structures::indexed_vec::Idx;
36+
use serialize::UseSpecializedDecodable;
3637
use std::fmt::Debug;
3738
use std::ops::Index;
3839
use syntax::codemap::Span;
@@ -49,14 +50,16 @@ use rustc_data_structures::fx::FxHashMap;
4950
/// A "canonicalized" type `V` is one where all free inference
5051
/// variables have been rewriten to "canonical vars". These are
5152
/// numbered starting from 0 in order of first appearance.
52-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
53+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
5354
pub struct Canonical<'gcx, V> {
5455
pub variables: CanonicalVarInfos<'gcx>,
5556
pub value: V,
5657
}
5758

5859
pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
5960

61+
impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> { }
62+
6063
/// A set of values corresponding to the canonical variables from some
6164
/// `Canonical`. You can give these values to
6265
/// `canonical_value.substitute` to substitute them into the canonical
@@ -69,7 +72,7 @@ pub type CanonicalVarInfos<'gcx> = &'gcx Slice<CanonicalVarInfo>;
6972
/// You can also use `infcx.fresh_inference_vars_for_canonical_vars`
7073
/// to get back a `CanonicalVarValues` containing fresh inference
7174
/// variables.
72-
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
75+
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
7376
pub struct CanonicalVarValues<'tcx> {
7477
pub var_values: IndexVec<CanonicalVar, Kind<'tcx>>,
7578
}
@@ -78,15 +81,15 @@ pub struct CanonicalVarValues<'tcx> {
7881
/// canonical value. This is sufficient information for code to create
7982
/// a copy of the canonical value in some other inference context,
8083
/// with fresh inference variables replacing the canonical values.
81-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
84+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
8285
pub struct CanonicalVarInfo {
8386
pub kind: CanonicalVarKind,
8487
}
8588

8689
/// Describes the "kind" of the canonical variable. This is a "kind"
8790
/// in the type-theory sense of the term -- i.e., a "meta" type system
8891
/// that analyzes type-like values.
89-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
92+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
9093
pub enum CanonicalVarKind {
9194
/// Some kind of type inference variable.
9295
Ty(CanonicalTyVarKind),
@@ -100,7 +103,7 @@ pub enum CanonicalVarKind {
100103
/// 22.) can only be instantiated with integral/float types (e.g.,
101104
/// usize or f32). In order to faithfully reproduce a type, we need to
102105
/// know what set of types a given type variable can be unified with.
103-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
106+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
104107
pub enum CanonicalTyVarKind {
105108
/// General type variable `?T` that can be unified with arbitrary types.
106109
General,
@@ -855,11 +858,14 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for CanonicalVarValuesSubst<'cx, 'g
855858
}
856859

857860
CloneTypeFoldableAndLiftImpls! {
861+
::infer::canonical::Certainty,
862+
::infer::canonical::CanonicalVarInfo,
863+
::infer::canonical::CanonicalVarKind,
864+
}
865+
866+
CloneTypeFoldableImpls! {
858867
for <'tcx> {
859-
::infer::canonical::Certainty,
860-
::infer::canonical::CanonicalVarInfo,
861868
::infer::canonical::CanonicalVarInfos<'tcx>,
862-
::infer::canonical::CanonicalVarKind,
863869
}
864870
}
865871

@@ -870,6 +876,13 @@ BraceStructTypeFoldableImpl! {
870876
} where C: TypeFoldable<'tcx>
871877
}
872878

879+
BraceStructLiftImpl! {
880+
impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
881+
type Lifted = Canonical<'tcx, T::Lifted>;
882+
variables, value
883+
} where T: Lift<'tcx>
884+
}
885+
873886
impl<'tcx> CanonicalVarValues<'tcx> {
874887
fn iter<'a>(&'a self) -> impl Iterator<Item = Kind<'tcx>> + 'a {
875888
self.var_values.iter().cloned()

src/librustc/mir/mod.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use hir::def_id::DefId;
2727
use mir::visit::MirVisitable;
2828
use mir::interpret::{Value, PrimVal};
2929
use ty::subst::{Subst, Substs};
30-
use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
30+
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
3131
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3232
use ty::TypeAndMut;
3333
use util::ppaux;
@@ -1253,6 +1253,23 @@ pub enum StatementKind<'tcx> {
12531253
/// (The starting point(s) arise implicitly from borrows.)
12541254
EndRegion(region::Scope),
12551255

1256+
/// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
1257+
/// them. For example:
1258+
///
1259+
/// let (a, b): (T, U) = y;
1260+
///
1261+
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
1262+
/// is the right thing.
1263+
///
1264+
/// `CanonicalTy` is used to capture "inference variables" from the user's types. For example:
1265+
///
1266+
/// let x: Vec<_> = ...;
1267+
/// let y: &u32 = ...;
1268+
///
1269+
/// would result in `Vec<?0>` and `&'?0 u32` respectively (where `?0` is a canonicalized
1270+
/// variable).
1271+
UserAssertTy(CanonicalTy<'tcx>, Local),
1272+
12561273
/// No-op. Useful for deleting instructions without affecting statement indices.
12571274
Nop,
12581275
}
@@ -1324,6 +1341,8 @@ impl<'tcx> Debug for Statement<'tcx> {
13241341
InlineAsm { ref asm, ref outputs, ref inputs } => {
13251342
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
13261343
},
1344+
UserAssertTy(ref c_ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})",
1345+
c_ty, local),
13271346
Nop => write!(fmt, "nop"),
13281347
}
13291348
}
@@ -2184,6 +2203,7 @@ EnumTypeFoldableImpl! {
21842203
(StatementKind::InlineAsm) { asm, outputs, inputs },
21852204
(StatementKind::Validate)(a, b),
21862205
(StatementKind::EndRegion)(a),
2206+
(StatementKind::UserAssertTy)(a, b),
21872207
(StatementKind::Nop),
21882208
}
21892209
}

src/librustc/mir/visit.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use hir::def_id::DefId;
1212
use ty::subst::Substs;
13-
use ty::{ClosureSubsts, Region, Ty, GeneratorInterior};
13+
use ty::{CanonicalTy, ClosureSubsts, Region, Ty, GeneratorInterior};
1414
use mir::*;
1515
use syntax_pos::Span;
1616

@@ -144,6 +144,13 @@ 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);
152+
}
153+
147154
fn visit_place(&mut self,
148155
place: & $($mutability)* Place<'tcx>,
149156
context: PlaceContext<'tcx>,
@@ -376,6 +383,10 @@ macro_rules! make_mir_visitor {
376383
self.visit_operand(input, location);
377384
}
378385
}
386+
StatementKind::UserAssertTy(ref $($mutability)* c_ty,
387+
ref $($mutability)* local) => {
388+
self.visit_user_assert_ty(c_ty, local, location);
389+
}
379390
StatementKind::Nop => {}
380391
}
381392
}
@@ -619,6 +630,13 @@ macro_rules! make_mir_visitor {
619630
}
620631
}
621632

633+
fn super_user_assert_ty(&mut self,
634+
_c_ty: & $($mutability)* CanonicalTy<'tcx>,
635+
local: & $($mutability)* Local,
636+
location: Location) {
637+
self.visit_local(local, PlaceContext::Validate, location);
638+
}
639+
622640
fn super_place(&mut self,
623641
place: & $($mutability)* Place<'tcx>,
624642
context: PlaceContext<'tcx>,

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
12511251
"choose which RELRO level to use"),
12521252
nll: bool = (false, parse_bool, [UNTRACKED],
12531253
"run the non-lexical lifetimes MIR pass"),
1254+
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
1255+
"disable user provided type assertion in NLL"),
12541256
trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
12551257
"generate a graphical HTML report of time spent in trans and LLVM"),
12561258
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],

src/librustc/ty/codec.rs

+23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// persisting to incr. comp. caches.
1818

1919
use hir::def_id::{DefId, CrateNum};
20+
use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
2021
use rustc_data_structures::fx::FxHashMap;
2122
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
2223
use std::hash::Hash;
@@ -239,6 +240,19 @@ pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
239240
.mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
240241
}
241242

243+
#[inline]
244+
pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
245+
-> Result<CanonicalVarInfos<'tcx>, D::Error>
246+
where D: TyDecoder<'a, 'tcx>,
247+
'tcx: 'a,
248+
{
249+
let len = decoder.read_usize()?;
250+
let interned: Result<Vec<CanonicalVarInfo>, _> = (0..len).map(|_| Decodable::decode(decoder))
251+
.collect();
252+
Ok(decoder.tcx()
253+
.intern_canonical_var_infos(interned?.as_slice()))
254+
}
255+
242256
#[inline]
243257
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
244258
-> Result<&'tcx ty::Const<'tcx>, D::Error>
@@ -262,6 +276,7 @@ macro_rules! implement_ty_decoder {
262276
($DecoderName:ident <$($typaram:tt),*>) => {
263277
mod __ty_decoder_impl {
264278
use super::$DecoderName;
279+
use $crate::infer::canonical::CanonicalVarInfos;
265280
use $crate::ty;
266281
use $crate::ty::codec::*;
267282
use $crate::ty::subst::Substs;
@@ -364,6 +379,14 @@ macro_rules! implement_ty_decoder {
364379
}
365380
}
366381

382+
impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
383+
for $DecoderName<$($typaram),*> {
384+
fn specialized_decode(&mut self)
385+
-> Result<CanonicalVarInfos<'tcx>, Self::Error> {
386+
decode_canonical_var_infos(self)
387+
}
388+
}
389+
367390
impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
368391
for $DecoderName<$($typaram),*> {
369392
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {

src/librustc/ty/context.rs

+40
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
4848
use ty::maps;
4949
use ty::steal::Steal;
5050
use ty::BindingMode;
51+
use ty::CanonicalTy;
5152
use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
5253
use util::nodemap::{FxHashMap, FxHashSet};
5354
use rustc_data_structures::accumulate_vec::AccumulateVec;
@@ -344,6 +345,10 @@ pub struct TypeckTables<'tcx> {
344345
/// method calls, including those of overloaded operators.
345346
type_dependent_defs: ItemLocalMap<Def>,
346347

348+
/// Stores the canonicalized types provided by the user. See also `UserAssertTy` statement in
349+
/// MIR.
350+
user_provided_tys: ItemLocalMap<CanonicalTy<'tcx>>,
351+
347352
/// Stores the types for various nodes in the AST. Note that this table
348353
/// is not guaranteed to be populated until after typeck. See
349354
/// typeck::check::fn_ctxt for details.
@@ -420,6 +425,7 @@ impl<'tcx> TypeckTables<'tcx> {
420425
TypeckTables {
421426
local_id_root,
422427
type_dependent_defs: ItemLocalMap(),
428+
user_provided_tys: ItemLocalMap(),
423429
node_types: ItemLocalMap(),
424430
node_substs: ItemLocalMap(),
425431
adjustments: ItemLocalMap(),
@@ -461,6 +467,20 @@ impl<'tcx> TypeckTables<'tcx> {
461467
}
462468
}
463469

470+
pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
471+
LocalTableInContext {
472+
local_id_root: self.local_id_root,
473+
data: &self.user_provided_tys
474+
}
475+
}
476+
477+
pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<CanonicalTy<'tcx>> {
478+
LocalTableInContextMut {
479+
local_id_root: self.local_id_root,
480+
data: &mut self.user_provided_tys
481+
}
482+
}
483+
464484
pub fn node_types(&self) -> LocalTableInContext<Ty<'tcx>> {
465485
LocalTableInContext {
466486
local_id_root: self.local_id_root,
@@ -685,6 +705,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
685705
let ty::TypeckTables {
686706
local_id_root,
687707
ref type_dependent_defs,
708+
ref user_provided_tys,
688709
ref node_types,
689710
ref node_substs,
690711
ref adjustments,
@@ -704,6 +725,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
704725

705726
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
706727
type_dependent_defs.hash_stable(hcx, hasher);
728+
user_provided_tys.hash_stable(hcx, hasher);
707729
node_types.hash_stable(hcx, hasher);
708730
node_substs.hash_stable(hcx, hasher);
709731
adjustments.hash_stable(hcx, hasher);
@@ -1637,6 +1659,24 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Predicate<'a>> {
16371659
}
16381660
}
16391661

1662+
impl<'a, 'tcx> Lift<'tcx> for &'a Slice<CanonicalVarInfo> {
1663+
type Lifted = &'tcx Slice<CanonicalVarInfo>;
1664+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
1665+
if self.len() == 0 {
1666+
return Some(Slice::empty());
1667+
}
1668+
if tcx.interners.arena.in_arena(*self as *const _) {
1669+
return Some(unsafe { mem::transmute(*self) });
1670+
}
1671+
// Also try in the global tcx if we're not that.
1672+
if !tcx.is_global() {
1673+
self.lift_to_tcx(tcx.global_tcx())
1674+
} else {
1675+
None
1676+
}
1677+
}
1678+
}
1679+
16401680
pub mod tls {
16411681
use super::{CtxtInterners, GlobalCtxt, TyCtxt};
16421682

src/librustc/ty/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use hir::map::DefPathData;
2121
use hir::svh::Svh;
2222
use ich::Fingerprint;
2323
use ich::StableHashingContext;
24+
use infer::canonical::{Canonical, Canonicalize};
2425
use middle::const_val::ConstVal;
2526
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
2627
use middle::privacy::AccessLevels;
@@ -554,6 +555,17 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>;
554555
impl<'tcx> serialize::UseSpecializedEncodable for Ty<'tcx> {}
555556
impl<'tcx> serialize::UseSpecializedDecodable for Ty<'tcx> {}
556557

558+
pub type CanonicalTy<'gcx> = Canonical<'gcx, Ty<'gcx>>;
559+
560+
impl <'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for Ty<'tcx> {
561+
type Canonicalized = CanonicalTy<'gcx>;
562+
563+
fn intern(_gcx: TyCtxt<'_, 'gcx, 'gcx>,
564+
value: Canonical<'gcx, Self::Lifted>) -> Self::Canonicalized {
565+
value
566+
}
567+
}
568+
557569
/// A wrapper for slices with the additional invariant
558570
/// that the slice is interned and no other slice with
559571
/// the same contents can exist in the same context.

src/librustc_mir/borrow_check/mod.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
392392
// ignored when consuming results (update to
393393
// flow_state already handled).
394394
}
395-
StatementKind::Nop | StatementKind::Validate(..) | StatementKind::StorageLive(..) => {
396-
// `Nop`, `Validate`, and `StorageLive` are irrelevant
395+
StatementKind::Nop |
396+
StatementKind::UserAssertTy(..) |
397+
StatementKind::Validate(..) |
398+
StatementKind::StorageLive(..) => {
399+
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
397400
// to borrow check.
398401
}
399-
400402
StatementKind::StorageDead(local) => {
401403
self.access_place(
402404
ContextKind::StorageDead.new(location),

0 commit comments

Comments
 (0)