From 99e2d33315afa0168e971d929667dde0158200e7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 29 May 2022 20:15:34 +0200 Subject: [PATCH] Compute `object_lifetime_default` per parameter. --- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 5 + compiler/rustc_metadata/src/rmeta/mod.rs | 2 + compiler/rustc_middle/src/query/mod.rs | 5 +- compiler/rustc_middle/src/ty/generics.rs | 3 +- compiler/rustc_middle/src/ty/parameterized.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 28 +++++ compiler/rustc_resolve/src/late/lifetimes.rs | 106 ++++-------------- compiler/rustc_typeck/src/collect.rs | 24 +--- 9 files changed, 67 insertions(+), 108 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 38ce50e8323..14a28cf7d3f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -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 } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 33278367ce3..50a309f8785 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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 { + 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)); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 66bdecc30db..2f3493d1b19 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -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; @@ -357,6 +358,7 @@ define_tables! { codegen_fn_attrs: Table>, impl_trait_ref: Table>>, const_param_default: Table>>, + object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, promoted_mir: Table>>>, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index d8483e7e409..ff296116a1f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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 { + desc { "looking up lifetime defaults for generic parameter `{:?}`", key } + separate_provide_extern } query late_bound_vars_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index add2df25884..d6a55af51e5 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -1,4 +1,3 @@ -use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::ty; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::EarlyBinder; @@ -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 }, } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index e189ee2fc4d..067ad927a03 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -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, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index fde12b9eee6..33ab2e12edd 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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::{ @@ -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) + } _ => {} } @@ -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::>() + .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, diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index b96968f81e0..52980f15971 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -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 { @@ -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 @@ -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); + param_def_id: DefId, +) -> Option { + 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)?; - // 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::>>() - .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, 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 { + // 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()); + } } } @@ -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> { @@ -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() }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 1c1df4a2f7f..0ec2acafd07 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -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; @@ -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, }, }); @@ -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; @@ -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, @@ -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 }, })); } @@ -1743,11 +1729,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { name: Symbol::intern(""), 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 }, }); } }