Compute object_lifetime_default per parameter.

This commit is contained in:
Camille GILLOT 2022-05-29 20:15:34 +02:00
parent 236ccce79e
commit 99e2d33315
9 changed files with 67 additions and 108 deletions
compiler
rustc_metadata/src/rmeta
rustc_middle/src
rustc_passes/src
rustc_resolve/src/late
rustc_typeck/src

@ -199,6 +199,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
codegen_fn_attrs => { table } codegen_fn_attrs => { table }
impl_trait_ref => { table } impl_trait_ref => { table }
const_param_default => { table } const_param_default => { table }
object_lifetime_default => { table }
thir_abstract_const => { table } thir_abstract_const => { table }
optimized_mir => { table } optimized_mir => { table }
mir_for_ctfe => { table } mir_for_ctfe => { table }

@ -1044,6 +1044,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
} }
} }
if let DefKind::TyParam | DefKind::ConstParam = def_kind {
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 { if let DefKind::Trait | DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id)); record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
} }

@ -16,6 +16,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_middle::metadata::ModChild; use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
@ -357,6 +358,7 @@ define_tables! {
codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>, codegen_fn_attrs: Table<DefIndex, LazyValue<CodegenFnAttrs>>,
impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'static>>>, impl_trait_ref: Table<DefIndex, LazyValue<ty::TraitRef<'static>>>,
const_param_default: Table<DefIndex, LazyValue<rustc_middle::ty::Const<'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>>>, optimized_mir: Table<DefIndex, LazyValue<mir::Body<'static>>>,
mir_for_ctfe: 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>>>>, promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,

@ -1579,8 +1579,9 @@ rustc_queries! {
/// for each parameter if a trait object were to be passed for that parameter. /// 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 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]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> { query object_lifetime_default(key: DefId) -> Option<ObjectLifetimeDefault> {
desc { "looking up lifetime defaults for a region on an item" } desc { "looking up lifetime defaults for generic parameter `{:?}`", key }
separate_provide_extern
} }
query late_bound_vars_map(_: LocalDefId) query late_bound_vars_map(_: LocalDefId)
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> { -> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {

@ -1,4 +1,3 @@
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
use crate::ty; use crate::ty;
use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::EarlyBinder; use crate::ty::EarlyBinder;
@ -13,7 +12,7 @@ use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predi
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind { pub enum GenericParamDefKind {
Lifetime, Lifetime,
Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, Type { has_default: bool, synthetic: bool },
Const { has_default: bool }, Const { has_default: bool },
} }

@ -53,6 +53,7 @@ trivially_parameterized_over_tcx! {
crate::metadata::ModChild, crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs, crate::middle::codegen_fn_attrs::CodegenFnAttrs,
crate::middle::exported_symbols::SymbolExportInfo, crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::resolve_lifetime::ObjectLifetimeDefault,
crate::mir::ConstQualifs, crate::mir::ConstQualifs,
ty::Generics, ty::Generics,
ty::ImplPolarity, ty::ImplPolarity,

@ -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::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
use rustc_hir::{MethodKind, Target}; use rustc_hir::{MethodKind, Target};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::lint::builtin::{ use rustc_session::lint::builtin::{
@ -171,6 +172,9 @@ impl CheckAttrVisitor<'_> {
sym::no_implicit_prelude => { sym::no_implicit_prelude => {
self.check_generic_attr(hir_id, attr, target, &[Target::Mod]) self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
} }
sym::rustc_object_lifetime_default => {
self.check_object_lifetime_default(hir_id, span)
}
_ => {} _ => {}
} }
@ -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. /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
fn check_track_caller( fn check_track_caller(
&self, &self,

@ -18,11 +18,10 @@ use rustc_middle::bug;
use rustc_middle::hir::map::Map; use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::*; 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::def_id::DefId;
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use std::borrow::Cow;
use std::fmt; use std::fmt;
trait RegionExt { trait RegionExt {
@ -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), named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
is_late_bound_map, 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), late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
..*providers ..*providers
@ -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>, tcx: TyCtxt<'tcx>,
def_id: LocalDefId, param_def_id: DefId,
) -> Option<&'tcx [ObjectLifetimeDefault]> { ) -> Option<ObjectLifetimeDefault> {
let hir::Node::Item(item) = tcx.hir().get_by_def_id(def_id) else { return None; }; let param_def_id = param_def_id.expect_local();
match item.kind { let parent_def_id = tcx.local_parent(param_def_id);
hir::ItemKind::Struct(_, ref generics) let generics = tcx.hir().get_generics(parent_def_id)?;
| hir::ItemKind::Union(_, ref generics) let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
| hir::ItemKind::Enum(_, ref generics) let param = generics.params.iter().find(|p| p.hir_id == param_hir_id)?;
| 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. // Scan the bounds and where-clauses on parameters to extract bounds
let attrs = tcx.hir().attrs(item.hir_id()); // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
if tcx.sess.contains_name(attrs, sym::rustc_object_lifetime_default) { // for each type parameter.
let object_lifetime_default_reprs: String = result match param.kind {
.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 {
GenericParamKind::Lifetime { .. } => None, GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { .. } => { GenericParamKind::Type { .. } => {
let mut set = Set1::Empty; let mut set = Set1::Empty;
let param_def_id = tcx.hir().local_def_id(param.hir_id); // Look for `type: ...` where clauses.
for predicate in generics.predicates { for bound in generics.bounds_for_param(param_def_id) {
// Look for `type: ...` where clauses.
let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue };
// Ignore `for<'a> type: ...` as they can change what // Ignore `for<'a> type: ...` as they can change what
// lifetimes mean (although we could "just" handle it). // lifetimes mean (although we could "just" handle it).
if !data.bound_generic_params.is_empty() { if !bound.bound_generic_params.is_empty() {
continue; continue;
} }
let res = match data.bounded_ty.kind { for bound in bound.bounds {
hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.res, if let hir::GenericBound::Outlives(ref lifetime) = *bound {
_ => continue, set.insert(lifetime.name.normalize_to_macros_2_0());
}; }
if res == Res::Def(DefKind::TyParam, param_def_id.to_def_id()) {
add_bounds(&mut set, &data.bounds);
} }
} }
@ -1364,9 +1312,7 @@ fn object_lifetime_defaults_for_item<'tcx>(
// in an arbitrary order. // in an arbitrary order.
Some(ObjectLifetimeDefault::Empty) Some(ObjectLifetimeDefault::Empty)
} }
}; }
tcx.arena.alloc_from_iter(generics.params.iter().filter_map(process_param))
} }
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
@ -1744,13 +1690,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
generics generics
.params .params
.iter() .iter()
.filter_map(|param| match param.kind { .filter_map(|param| self.tcx.object_lifetime_default(param.def_id))
GenericParamDefKind::Type { object_lifetime_default, .. } => {
Some(object_lifetime_default)
}
GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty),
GenericParamDefKind::Lifetime => None,
})
.map(set_to_region) .map(set_to_region)
.collect() .collect()
}); });

@ -34,7 +34,6 @@ use rustc_hir::weak_lang_items;
use rustc_hir::{GenericParamKind, HirId, Node}; use rustc_hir::{GenericParamKind, HirId, Node};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; 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::mir::mono::Linkage;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::subst::InternalSubsts;
@ -1598,7 +1597,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: false, has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false, synthetic: false,
}, },
}); });
@ -1642,8 +1640,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
kind: ty::GenericParamDefKind::Lifetime, kind: ty::GenericParamDefKind::Lifetime,
})); }));
let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id.owner);
// Now create the real type and const parameters. // Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32; let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0; let mut i = 0;
@ -1668,13 +1664,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
} }
} }
let kind = ty::GenericParamDefKind::Type { let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults
.as_ref()
.map_or(ObjectLifetimeDefault::Empty, |o| o[i]),
synthetic,
};
let param_def = ty::GenericParamDef { let param_def = ty::GenericParamDef {
index: type_start + i as u32, index: type_start + i as u32,
@ -1726,11 +1716,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
name: Symbol::intern(arg), name: Symbol::intern(arg),
def_id, def_id,
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false,
},
})); }));
} }
@ -1743,11 +1729,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
name: Symbol::intern("<const_ty>"), name: Symbol::intern("<const_ty>"),
def_id, def_id,
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
has_default: false,
object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false,
},
}); });
} }
} }