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

Lines changed: 18 additions & 3 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 6 additions & 1 deletion
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

Lines changed: 34 additions & 8 deletions
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

Lines changed: 10 additions & 5 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 10 additions & 0 deletions
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

0 commit comments

Comments
 (0)