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```
This commit is contained in:
commit
f783871ab1
@ -1316,7 +1316,7 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
|
||||
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)
|
||||
|
@ -2578,7 +2578,8 @@ pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
|
||||
}
|
||||
|
||||
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]> {
|
||||
|
@ -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);
|
||||
|
@ -11,7 +11,8 @@
|
||||
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::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 {
|
||||
|
18
src/test/ui/const-generics/late-bound-vars/in_closure.rs
Normal file
18
src/test/ui/const-generics/late-bound-vars/in_closure.rs
Normal file
@ -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();
|
||||
}
|
16
src/test/ui/const-generics/late-bound-vars/simple.rs
Normal file
16
src/test/ui/const-generics/late-bound-vars/simple.rs
Normal file
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user