diff options
| author | Mara Bos <m-ou.se@m-ou.se> | 2021-01-17 12:24:39 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-17 12:24:39 +0000 |
| commit | f783871ab18346b7ccb7bda04b9a69f103d851a7 (patch) | |
| tree | d7a0e0c10cd94d841d95a66c26d497c7ee3f5140 | |
| parent | d51cf9601c714a8383aecade7c98559dd4831625 (diff) | |
| parent | 15f0921d0c0d95c009bee7d9cd9921306b78615c (diff) | |
Rollup merge of #79298 - lcnr:new-elysium, r=matthewjasper
correctly deal with late-bound lifetimes in anon consts
adds support for using late bound lifetimes of the parent context in anon consts.
```rust
#![feature(const_generics)]
const fn inner<'a>() -> usize where &'a (): Sized { 3 }
fn test<'a>() {
let _: [u8; inner::<'a>()];
}
```
The lifetime `'a` is late bound in `test` so it's not included in its generics but is instead dealt with separately in borrowck.
This didn't previously work for anon consts as they have to use the late bound lifetimes of their parent which has
to be explicitly handled.
r? ```@matthewjasper``` cc ```@varkor``` ```@eddyb```
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/borrow_check/universal_regions.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 32 | ||||
| -rw-r--r-- | src/test/ui/const-generics/late-bound-vars/in_closure.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/const-generics/late-bound-vars/simple.rs | 16 |
6 files changed, 71 insertions, 8 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9770e67f2d2..0a9f740d53a 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1316,7 +1316,7 @@ rustc_queries! { desc { "looking up a named region" } } query is_late_bound_map(_: LocalDefId) -> - Option<&'tcx FxHashSet<ItemLocalId>> { + Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> { desc { "testing if a region is late bound" } } query object_lifetime_defaults_map(_: LocalDefId) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a355242f5ce..148ac604596 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2578,7 +2578,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id)) + self.is_late_bound_map(id.owner) + .map_or(false, |(owner, set)| owner == id.owner && set.contains(&id.local_id)) } pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_mir/src/borrow_check/universal_regions.rs index c1a0d9856b7..02d951b70e2 100644 --- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs +++ b/compiler/rustc_mir/src/borrow_check/universal_regions.rs @@ -788,13 +788,13 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { - for late_bound in late_bounds.iter() { - let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound }; + if let Some((owner, late_bounds)) = tcx.is_late_bound_map(fn_def_id.expect_local()) { + for &late_bound in late_bounds.iter() { + let hir_id = HirId { owner, local_id: late_bound }; let name = tcx.hir().name(hir_id); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { - scope: fn_def_id, + scope: owner.to_def_id(), bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name), })); f(liberated_region); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index aab5c3cf8f5..1be06a44687 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -11,7 +11,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefIdMap, LOCAL_CRATE}; +use rustc_hir::hir_id::ItemLocalId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}; @@ -20,6 +21,7 @@ use rustc_middle::middle::resolve_lifetime::*; use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; +use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::borrow::Cow; @@ -284,7 +286,7 @@ pub fn provide(providers: &mut ty::query::Providers) { resolve_lifetimes, named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), - is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id), + is_late_bound_map, object_lifetime_defaults_map: |tcx, id| { tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) }, @@ -320,6 +322,32 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> ResolveLifetimes { rl } +fn is_late_bound_map<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> { + match tcx.def_kind(def_id) { + DefKind::AnonConst => { + let mut def_id = tcx + .parent(def_id.to_def_id()) + .unwrap_or_else(|| bug!("anon const or closure without a parent")); + // We search for the next outer anon const or fn here + // while skipping closures. + // + // Note that for `AnonConst` we still just recurse until we + // find a function body, but who cares :shrug: + while tcx.is_closure(def_id) { + def_id = tcx + .parent(def_id) + .unwrap_or_else(|| bug!("anon const or closure without a parent")); + } + + tcx.is_late_bound_map(def_id.expect_local()) + } + _ => tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&def_id).map(|lt| (def_id, lt)), + } +} + fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { let krate = tcx.hir().krate(); let mut map = NamedRegionMap { diff --git a/src/test/ui/const-generics/late-bound-vars/in_closure.rs b/src/test/ui/const-generics/late-bound-vars/in_closure.rs new file mode 100644 index 00000000000..0aaeaffb4cb --- /dev/null +++ b/src/test/ui/const-generics/late-bound-vars/in_closure.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(const_generics)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _ = || { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; + }; +} + +fn main() { + test(); +} diff --git a/src/test/ui/const-generics/late-bound-vars/simple.rs b/src/test/ui/const-generics/late-bound-vars/simple.rs new file mode 100644 index 00000000000..2c411a3bdc5 --- /dev/null +++ b/src/test/ui/const-generics/late-bound-vars/simple.rs @@ -0,0 +1,16 @@ +// run-pass +#![feature(const_generics)] +#![allow(incomplete_features)] + +const fn inner<'a>() -> usize where &'a (): Sized { + 3 +} + +fn test<'a>() { + let _: [u8; inner::<'a>()]; + let _ = [0; inner::<'a>()]; +} + +fn main() { + test(); +} |
