Skip to content

Commit 588f7db

Browse files
committed
Auto merge of #46733 - nikomatsakis:nll-master-to-rust-master-5, r=arielb1
nll part 5 Next round of changes from the nll-master branch. Extensions: - we now propagate ty-region-outlives constraints out of closures and into their creator when necessary - we fix a few ICEs that can occur by doing liveness analysis (and the resulting normalization) during type-checking - we handle the implicit region bound that assumes that each type `T` outlives the fn body - we handle normalization of inputs/outputs in fn signatures Not included in this PR (will come next): - handling `impl Trait` - tracking causal information - extended errors r? @arielb1
2 parents edbd7d2 + 1816ede commit 588f7db

File tree

78 files changed

+4057
-646
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4057
-646
lines changed

src/librustc/ich/impls_mir.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -536,14 +536,29 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> {
536536

537537
impl_stable_hash_for!(struct mir::Location { block, statement_index });
538538

539-
impl_stable_hash_for!(struct mir::ClosureRegionRequirements {
539+
impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> {
540540
num_external_vids,
541541
outlives_requirements
542542
});
543543

544-
impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement {
545-
free_region,
544+
impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
545+
subject,
546546
outlived_free_region,
547547
blame_span
548548
});
549549

550+
impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::ClosureOutlivesSubject<'gcx> {
551+
fn hash_stable<W: StableHasherResult>(&self,
552+
hcx: &mut StableHashingContext<'gcx>,
553+
hasher: &mut StableHasher<W>) {
554+
mem::discriminant(self).hash_stable(hcx, hasher);
555+
match *self {
556+
mir::ClosureOutlivesSubject::Ty(ref ty) => {
557+
ty.hash_stable(hcx, hasher);
558+
}
559+
mir::ClosureOutlivesSubject::Region(ref region) => {
560+
region.hash_stable(hcx, hasher);
561+
}
562+
}
563+
}
564+
}

src/librustc/ich/impls_ty.rs

+3
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ for ty::RegionKind {
7575
ty::ReFree(ref free_region) => {
7676
free_region.hash_stable(hcx, hasher);
7777
}
78+
ty::ReClosureBound(vid) => {
79+
vid.hash_stable(hcx, hasher);
80+
}
7881
ty::ReLateBound(..) |
7982
ty::ReVar(..) |
8083
ty::ReSkolemized(..) => {

src/librustc/infer/combine.rs

+8
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,14 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
475475
ty::Bivariant | ty::Covariant | ty::Contravariant => (),
476476
}
477477
}
478+
479+
ty::ReClosureBound(..) => {
480+
span_bug!(
481+
self.span,
482+
"encountered unexpected ReClosureBound: {:?}",
483+
r,
484+
);
485+
}
478486
}
479487

480488
// FIXME: This is non-ideal because we don't give a

src/librustc/infer/error_reporting/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
240240
ty::ReErased => {
241241
(format!("lifetime {:?}", region), None)
242242
}
243+
244+
// We shouldn't encounter an error message with ReClosureBound.
245+
ty::ReClosureBound(..) => {
246+
bug!(
247+
"encountered unexpected ReClosureBound: {:?}",
248+
region,
249+
);
250+
}
243251
};
244252
let message = format!("{}{}{}", prefix, description, suffix);
245253
if let Some(span) = span {

src/librustc/infer/freshen.rs

+7
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
113113
// replace all free regions with 'erased
114114
self.tcx().types.re_erased
115115
}
116+
117+
ty::ReClosureBound(..) => {
118+
bug!(
119+
"encountered unexpected ReClosureBound: {:?}",
120+
r,
121+
);
122+
}
116123
}
117124
}
118125

src/librustc/infer/lexical_region_resolve/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,12 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
258258
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
259259
let tcx = self.region_rels.tcx;
260260
match (a, b) {
261-
(&ReLateBound(..), _) | (_, &ReLateBound(..)) | (&ReErased, _) | (_, &ReErased) => {
261+
(&ty::ReClosureBound(..), _) |
262+
(_, &ty::ReClosureBound(..)) |
263+
(&ReLateBound(..), _) |
264+
(_, &ReLateBound(..)) |
265+
(&ReErased, _) |
266+
(_, &ReErased) => {
262267
bug!("cannot relate region: LUB({:?}, {:?})", a, b);
263268
}
264269

src/librustc/mir/mod.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -1832,8 +1832,17 @@ pub struct GeneratorLayout<'tcx> {
18321832
/// instance of the closure is created, the corresponding free regions
18331833
/// can be extracted from its type and constrained to have the given
18341834
/// outlives relationship.
1835+
///
1836+
/// In some cases, we have to record outlives requirements between
1837+
/// types and regions as well. In that case, if those types include
1838+
/// any regions, those regions are recorded as `ReClosureBound`
1839+
/// instances assigned one of these same indices. Those regions will
1840+
/// be substituted away by the creator. We use `ReClosureBound` in
1841+
/// that case because the regions must be allocated in the global
1842+
/// TyCtxt, and hence we cannot use `ReVar` (which is what we use
1843+
/// internally within the rest of the NLL code).
18351844
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
1836-
pub struct ClosureRegionRequirements {
1845+
pub struct ClosureRegionRequirements<'gcx> {
18371846
/// The number of external regions defined on the closure. In our
18381847
/// example above, it would be 3 -- one for `'static`, then `'1`
18391848
/// and `'2`. This is just used for a sanity check later on, to
@@ -1843,15 +1852,15 @@ pub struct ClosureRegionRequirements {
18431852

18441853
/// Requirements between the various free regions defined in
18451854
/// indices.
1846-
pub outlives_requirements: Vec<ClosureOutlivesRequirement>,
1855+
pub outlives_requirements: Vec<ClosureOutlivesRequirement<'gcx>>,
18471856
}
18481857

1849-
/// Indicates an outlives constraint between two free-regions declared
1850-
/// on the closure.
1851-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
1852-
pub struct ClosureOutlivesRequirement {
1853-
// This region ...
1854-
pub free_region: ty::RegionVid,
1858+
/// Indicates an outlives constraint between a type or between two
1859+
/// free-regions declared on the closure.
1860+
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
1861+
pub struct ClosureOutlivesRequirement<'tcx> {
1862+
// This region or type ...
1863+
pub subject: ClosureOutlivesSubject<'tcx>,
18551864

18561865
// .. must outlive this one.
18571866
pub outlived_free_region: ty::RegionVid,
@@ -1860,6 +1869,23 @@ pub struct ClosureOutlivesRequirement {
18601869
pub blame_span: Span,
18611870
}
18621871

1872+
/// The subject of a ClosureOutlivesRequirement -- that is, the thing
1873+
/// that must outlive some region.
1874+
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
1875+
pub enum ClosureOutlivesSubject<'tcx> {
1876+
/// Subject is a type, typically a type parameter, but could also
1877+
/// be a projection. Indicates a requirement like `T: 'a` being
1878+
/// passed to the caller, where the type here is `T`.
1879+
///
1880+
/// The type here is guaranteed not to contain any free regions at
1881+
/// present.
1882+
Ty(Ty<'tcx>),
1883+
1884+
/// Subject is a free region from the closure. Indicates a requirement
1885+
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
1886+
Region(ty::RegionVid),
1887+
}
1888+
18631889
/*
18641890
* TypeFoldable implementations for MIR types
18651891
*/

src/librustc/ty/fold.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,19 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
9797
fn has_closure_types(&self) -> bool {
9898
self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
9999
}
100+
/// "Free" regions in this context means that it has any region
101+
/// that is not (a) erased or (b) late-bound.
102+
fn has_free_regions(&self) -> bool {
103+
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
104+
}
105+
106+
/// True if there any any un-erased free regions.
100107
fn has_erasable_regions(&self) -> bool {
101-
self.has_type_flags(TypeFlags::HAS_RE_EARLY_BOUND |
102-
TypeFlags::HAS_RE_INFER |
103-
TypeFlags::HAS_FREE_REGIONS)
108+
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
104109
}
110+
105111
fn is_normalized_for_trans(&self) -> bool {
106-
!self.has_type_flags(TypeFlags::HAS_RE_EARLY_BOUND |
107-
TypeFlags::HAS_RE_INFER |
112+
!self.has_type_flags(TypeFlags::HAS_RE_INFER |
108113
TypeFlags::HAS_FREE_REGIONS |
109114
TypeFlags::HAS_TY_INFER |
110115
TypeFlags::HAS_PARAMS |

src/librustc/ty/maps/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ define_maps! { <'tcx>
193193

194194
/// Borrow checks the function body. If this is a closure, returns
195195
/// additional requirements that the closure's creator must verify.
196-
[] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements>,
196+
[] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements<'tcx>>,
197197

198198
/// Gets a complete map from all types to their inherent impls.
199199
/// Not meant to be used directly outside of coherence.

src/librustc/ty/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,18 @@ bitflags! {
421421
const HAS_TY_INFER = 1 << 2;
422422
const HAS_RE_INFER = 1 << 3;
423423
const HAS_RE_SKOL = 1 << 4;
424+
425+
/// Does this have any `ReEarlyBound` regions? Used to
426+
/// determine whether substitition is required, since those
427+
/// represent regions that are bound in a `ty::Generics` and
428+
/// hence may be substituted.
424429
const HAS_RE_EARLY_BOUND = 1 << 5;
430+
431+
/// Does this have any region that "appears free" in the type?
432+
/// Basically anything but `ReLateBound` and `ReErased`.
425433
const HAS_FREE_REGIONS = 1 << 6;
434+
435+
/// Is an error type reachable?
426436
const HAS_TY_ERR = 1 << 7;
427437
const HAS_PROJECTION = 1 << 8;
428438

src/librustc/ty/sty.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,12 @@ pub enum RegionKind {
10361036

10371037
/// Erased region, used by trait selection, in MIR and during trans.
10381038
ReErased,
1039+
1040+
/// These are regions bound in the "defining type" for a
1041+
/// closure. They are used ONLY as part of the
1042+
/// `ClosureRegionRequirements` that are produced by MIR borrowck.
1043+
/// See `ClosureRegionRequirements` for more details.
1044+
ReClosureBound(RegionVid),
10391045
}
10401046

10411047
impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@@ -1184,18 +1190,32 @@ impl RegionKind {
11841190

11851191
match *self {
11861192
ty::ReVar(..) => {
1193+
flags = flags | TypeFlags::HAS_FREE_REGIONS;
11871194
flags = flags | TypeFlags::HAS_RE_INFER;
11881195
flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
11891196
}
11901197
ty::ReSkolemized(..) => {
1198+
flags = flags | TypeFlags::HAS_FREE_REGIONS;
11911199
flags = flags | TypeFlags::HAS_RE_INFER;
11921200
flags = flags | TypeFlags::HAS_RE_SKOL;
11931201
flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
11941202
}
11951203
ty::ReLateBound(..) => { }
1196-
ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_RE_EARLY_BOUND; }
1197-
ty::ReStatic | ty::ReErased => { }
1198-
_ => { flags = flags | TypeFlags::HAS_FREE_REGIONS; }
1204+
ty::ReEarlyBound(..) => {
1205+
flags = flags | TypeFlags::HAS_FREE_REGIONS;
1206+
flags = flags | TypeFlags::HAS_RE_EARLY_BOUND;
1207+
}
1208+
ty::ReEmpty |
1209+
ty::ReStatic |
1210+
ty::ReFree { .. } |
1211+
ty::ReScope { .. } => {
1212+
flags = flags | TypeFlags::HAS_FREE_REGIONS;
1213+
}
1214+
ty::ReErased => {
1215+
}
1216+
ty::ReClosureBound(..) => {
1217+
flags = flags | TypeFlags::HAS_FREE_REGIONS;
1218+
}
11991219
}
12001220

12011221
match *self {

src/librustc/ty/util.rs

+2
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
822822
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) => {
823823
self.def_id(def_id);
824824
}
825+
826+
ty::ReClosureBound(..) |
825827
ty::ReLateBound(..) |
826828
ty::ReFree(..) |
827829
ty::ReScope(..) |

src/librustc/util/ppaux.rs

+8
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ define_print! {
733733
ty::ReErased => Ok(()),
734734
ty::ReStatic => write!(f, "'static"),
735735
ty::ReEmpty => write!(f, "'<empty>"),
736+
737+
// The user should never encounter these in unsubstituted form.
738+
ty::ReClosureBound(vid) => write!(f, "{:?}", vid),
736739
}
737740
}
738741
debug {
@@ -743,6 +746,11 @@ define_print! {
743746
data.name)
744747
}
745748

749+
ty::ReClosureBound(ref vid) => {
750+
write!(f, "ReClosureBound({:?})",
751+
vid)
752+
}
753+
746754
ty::ReLateBound(binder_id, ref bound_region) => {
747755
write!(f, "ReLateBound({:?}, {:?})",
748756
binder_id,

src/librustc_borrowck/borrowck/gather_loans/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
367367
ty::ReStatic => self.item_ub,
368368

369369
ty::ReEmpty |
370+
ty::ReClosureBound(..) |
370371
ty::ReLateBound(..) |
371372
ty::ReVar(..) |
372373
ty::ReSkolemized(..) |

src/librustc_mir/borrow_check/error_reporting.rs

+1
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
381381
},
382382
(RegionKind::ReLateBound(_, _), _) |
383383
(RegionKind::ReSkolemized(_, _), _) |
384+
(RegionKind::ReClosureBound(_), _) |
384385
(RegionKind::ReErased, _) => {
385386
span_bug!(drop_span, "region does not make sense in this context");
386387
},

src/librustc_mir/borrow_check/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
2222
use rustc::mir::ClosureRegionRequirements;
2323

2424
use rustc_data_structures::fx::FxHashSet;
25-
use rustc_data_structures::indexed_set::{IdxSetBuf};
25+
use rustc_data_structures::indexed_set::IdxSetBuf;
2626
use rustc_data_structures::indexed_vec::Idx;
2727

2828
use syntax::ast;
2929
use syntax_pos::Span;
3030

3131
use dataflow::{do_dataflow, DebugFormatted};
32+
use dataflow::FlowAtLocation;
3233
use dataflow::MoveDataParamEnv;
3334
use dataflow::{DataflowAnalysis, DataflowResultsConsumer};
34-
use dataflow::{FlowAtLocation, FlowsAtLocation};
3535
use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
3636
use dataflow::{EverInitializedLvals, MovingOutStatements};
3737
use dataflow::{Borrows, BorrowData, ReserveOrActivateIndex};
@@ -65,7 +65,7 @@ pub fn provide(providers: &mut Providers) {
6565
fn mir_borrowck<'a, 'tcx>(
6666
tcx: TyCtxt<'a, 'tcx, 'tcx>,
6767
def_id: DefId,
68-
) -> Option<ClosureRegionRequirements> {
68+
) -> Option<ClosureRegionRequirements<'tcx>> {
6969
let input_mir = tcx.mir_validated(def_id);
7070
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
7171

@@ -89,7 +89,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
8989
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
9090
input_mir: &Mir<'gcx>,
9191
def_id: DefId,
92-
) -> Option<ClosureRegionRequirements> {
92+
) -> Option<ClosureRegionRequirements<'gcx>> {
9393
let tcx = infcx.tcx;
9494
let attributes = tcx.get_attrs(def_id);
9595
let param_env = tcx.param_env(def_id);

0 commit comments

Comments
 (0)