Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove separate indexing of early-bound regions #99821

Merged
merged 9 commits into from
Aug 29, 2022
1 change: 1 addition & 0 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
codegen_fn_attrs => { table }
impl_trait_ref => { table }
const_param_default => { table }
object_lifetime_default => { table }
thir_abstract_const => { table }
optimized_mir => { table }
mir_for_ctfe => { table }
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
}
}
if let DefKind::TyParam | DefKind::ConstParam = def_kind {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see other places in this PR were updated to handle DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam, should this also check for DefKind::LifetimeParam?

if let Some(default) = self.tcx.object_lifetime_default(def_id) {
record!(self.tables.object_lifetime_default[def_id] <- default);
}
}
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
Expand Down Expand Up @@ -357,6 +358,7 @@ define_tables! {
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'static>>>,
const_param_default: Table<DefIndex, LazyValue<rustc_middle::ty::Const<'static>>>,
object_lifetime_default: Table<DefIndex, LazyValue<ObjectLifetimeDefault>>,
optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1579,8 +1579,9 @@ rustc_queries! {
/// for each parameter if a trait object were to be passed for that parameter.
/// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
/// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> {
desc { "looking up lifetime defaults for a region on an item" }
query object_lifetime_default(key: DefId) -> Option<ObjectLifetimeDefault> {
desc { "looking up lifetime defaults for generic parameter `{:?}`", key }
separate_provide_extern
}
query late_bound_vars_map(_: LocalDefId)
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/ty/generics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
use crate::ty;
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::EarlyBinder;
Expand All @@ -13,7 +12,7 @@ use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predi
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
Lifetime,
Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool },
Type { has_default: bool, synthetic: bool },
Const { has_default: bool },
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/parameterized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::resolve_lifetime::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::Generics,
ty::ImplPolarity,
Expand Down
28 changes: 28 additions & 0 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
use rustc_hir::{MethodKind, Target};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{
Expand Down Expand Up @@ -171,6 +172,9 @@ impl CheckAttrVisitor<'_> {
sym::no_implicit_prelude => {
self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
}
sym::rustc_object_lifetime_default => {
self.check_object_lifetime_default(hir_id, span)
}
_ => {}
}

Expand Down Expand Up @@ -402,6 +406,30 @@ impl CheckAttrVisitor<'_> {
}
}

/// Debugging aid for `object_lifetime_default` query.
fn check_object_lifetime_default(&self, hir_id: HirId, span: Span) {
let tcx = self.tcx;
if let Some(generics) = tcx.hir().get_generics(tcx.hir().local_def_id(hir_id)) {
let object_lifetime_default_reprs: String = generics
.params
.iter()
.filter_map(|p| {
let param_id = tcx.hir().local_def_id(p.hir_id);
let default = tcx.object_lifetime_default(param_id)?;
Some(match default {
ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
ObjectLifetimeDefault::Static => "'static".to_owned(),
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
})
})
.collect::<Vec<String>>()
.join(",");

tcx.sess.span_err(span, &object_lifetime_default_reprs);
}
}

/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
fn check_track_caller(
&self,
Expand Down
108 changes: 24 additions & 84 deletions compiler/rustc_resolve/src/late/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ use rustc_middle::bug;
use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*;
use rustc_middle::ty::{self, GenericParamDefKind, TyCtxt};
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use std::borrow::Cow;
use std::fmt;

trait RegionExt {
Expand Down Expand Up @@ -290,7 +289,7 @@ pub fn provide(providers: &mut ty::query::Providers) {

named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
is_late_bound_map,
object_lifetime_defaults,
object_lifetime_default,
late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),

..*providers
Expand Down Expand Up @@ -1264,87 +1263,36 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}

fn object_lifetime_defaults<'tcx>(
fn object_lifetime_default<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> Option<&'tcx [ObjectLifetimeDefault]> {
let hir::Node::Item(item) = tcx.hir().get_by_def_id(def_id) else { return None; };
match item.kind {
hir::ItemKind::Struct(_, ref generics)
| hir::ItemKind::Union(_, ref generics)
| hir::ItemKind::Enum(_, ref generics)
| hir::ItemKind::OpaqueTy(hir::OpaqueTy {
ref generics,
origin: hir::OpaqueTyOrigin::TyAlias,
..
})
| hir::ItemKind::TyAlias(_, ref generics)
| hir::ItemKind::Trait(_, _, ref generics, ..) => {
let result = object_lifetime_defaults_for_item(tcx, generics);

// Debugging aid.
let attrs = tcx.hir().attrs(item.hir_id());
if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) {
let object_lifetime_default_reprs: String = result
.iter()
.map(|set| match *set {
ObjectLifetimeDefault::Empty => "BaseDefault".into(),
ObjectLifetimeDefault::Static => "'static".into(),
ObjectLifetimeDefault::Param(def_id) => {
let def_id = def_id.expect_local();
tcx.hir().ty_param_name(def_id).to_string().into()
}
ObjectLifetimeDefault::Ambiguous => "Ambiguous".into(),
})
.collect::<Vec<Cow<'static, str>>>()
.join(",");
tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
}

Some(result)
}
_ => None,
}
}

/// Scan the bounds and where-clauses on parameters to extract bounds
/// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
/// for each type parameter.
fn object_lifetime_defaults_for_item<'tcx>(
tcx: TyCtxt<'tcx>,
generics: &hir::Generics<'_>,
) -> &'tcx [ObjectLifetimeDefault] {
fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::GenericBound<'_>]) {
for bound in bounds {
if let hir::GenericBound::Outlives(ref lifetime) = *bound {
set.insert(lifetime.name.normalize_to_macros_2_0());
}
}
}

let process_param = |param: &hir::GenericParam<'_>| match param.kind {
param_def_id: DefId,
) -> Option<ObjectLifetimeDefault> {
let param_def_id = param_def_id.expect_local();
let parent_def_id = tcx.local_parent(param_def_id);
let generics = tcx.hir().get_generics(parent_def_id)?;
let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;

// Scan the bounds and where-clauses on parameters to extract bounds
// of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
// for each type parameter.
match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { .. } => {
let mut set = Set1::Empty;

let param_def_id = tcx.hir().local_def_id(param.hir_id);
for predicate in generics.predicates {
// Look for `type: ...` where clauses.
let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue };

// Look for `type: ...` where clauses.
for bound in generics.bounds_for_param(param_def_id) {
// Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it).
if !data.bound_generic_params.is_empty() {
if !bound.bound_generic_params.is_empty() {
continue;
}

let res = match data.bounded_ty.kind {
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.res,
_ => continue,
};

if res == Res::Def(DefKind::TyParam, param_def_id.to_def_id()) {
add_bounds(&mut set, &data.bounds);
for bound in bound.bounds {
if let hir::GenericBound::Outlives(ref lifetime) = *bound {
set.insert(lifetime.name.normalize_to_macros_2_0());
}
}
}

Expand All @@ -1364,9 +1312,7 @@ fn object_lifetime_defaults_for_item<'tcx>(
// in an arbitrary order.
Some(ObjectLifetimeDefault::Empty)
}
};

tcx.arena.alloc_from_iter(generics.params.iter().filter_map(process_param))
}
}

impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Expand Down Expand Up @@ -1744,13 +1690,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamDefKind::Type { object_lifetime_default, .. } => {
Some(object_lifetime_default)
}
GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty),
GenericParamDefKind::Lifetime => None,
})
.filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
.map(set_to_region)
.collect()
});
Expand Down
24 changes: 3 additions & 21 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use rustc_hir::weak_lang_items;
use rustc_hir::{GenericParamKind, HirId, Node};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts;
Expand Down Expand Up @@ -1598,7 +1597,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false,
},
});
Expand Down Expand Up @@ -1642,8 +1640,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
kind: ty::GenericParamDefKind::Lifetime,
}));

let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id.owner);

// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
Expand All @@ -1668,13 +1664,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
}
}

let kind = ty::GenericParamDefKind::Type {
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(ObjectLifetimeDefault::Empty, |o| o[i]),
synthetic,
};
let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };

let param_def = ty::GenericParamDef {
index: type_start + i as u32,
Expand Down Expand Up @@ -1726,11 +1716,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
name: Symbol::intern(arg),
def_id,
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false,
},
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
}));
}

Expand All @@ -1743,11 +1729,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
name: Symbol::intern("<const_ty>"),
def_id,
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false,
},
kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
});
}
}
Expand Down