diff options
Diffstat (limited to 'compiler/rustc_ty_utils')
| -rw-r--r-- | compiler/rustc_ty_utils/src/assoc.rs | 136 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/needs_drop.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/representability.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 246 |
6 files changed, 313 insertions, 215 deletions
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs new file mode 100644 index 00000000000..4142c999ca7 --- /dev/null +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -0,0 +1,136 @@ +use rustc_data_structures::fx::FxHashMap; +use rustc_hir as hir; +use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_middle::ty::{self, TyCtxt}; + +pub fn provide(providers: &mut ty::query::Providers) { + *providers = ty::query::Providers { + associated_item, + associated_item_def_ids, + associated_items, + impl_item_implementor_ids, + trait_of_item, + ..*providers + }; +} + +fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { + let item = tcx.hir().expect_item(def_id.expect_local()); + match item.kind { + hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( + trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), + ), + hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), + ), + hir::ItemKind::TraitAlias(..) => &[], + _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), + } +} + +fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { + let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); + ty::AssocItems::new(items) +} + +fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> { + tcx.associated_items(impl_id) + .in_definition_order() + .filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id))) + .collect() +} + +/// If the given `DefId` describes an item belonging to a trait, +/// returns the `DefId` of the trait that the trait item belongs to; +/// otherwise, returns `None`. +fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { + tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container { + ty::TraitContainer(def_id) => Some(def_id), + ty::ImplContainer(_) => None, + }) +} + +fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { + let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let parent_def_id = tcx.hir().get_parent_item(id); + let parent_item = tcx.hir().expect_item(parent_def_id); + match parent_item.kind { + hir::ItemKind::Impl(ref impl_) => { + if let Some(impl_item_ref) = + impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) + { + let assoc_item = + associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref); + debug_assert_eq!(assoc_item.def_id, def_id); + return assoc_item; + } + } + + hir::ItemKind::Trait(.., ref trait_item_refs) => { + if let Some(trait_item_ref) = + trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) + { + let assoc_item = + associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref); + debug_assert_eq!(assoc_item.def_id, def_id); + return assoc_item; + } + } + + _ => {} + } + + span_bug!( + parent_item.span, + "unexpected parent of trait or impl item or item not found: {:?}", + parent_item.kind + ) +} + +fn associated_item_from_trait_item_ref( + tcx: TyCtxt<'_>, + parent_def_id: LocalDefId, + trait_item_ref: &hir::TraitItemRef, +) -> ty::AssocItem { + let def_id = trait_item_ref.id.def_id; + let (kind, has_self) = match trait_item_ref.kind { + hir::AssocItemKind::Const => (ty::AssocKind::Const, false), + hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), + hir::AssocItemKind::Type => (ty::AssocKind::Type, false), + }; + + ty::AssocItem { + name: trait_item_ref.ident.name, + kind, + vis: tcx.visibility(def_id), + defaultness: trait_item_ref.defaultness, + def_id: def_id.to_def_id(), + trait_item_def_id: Some(def_id.to_def_id()), + container: ty::TraitContainer(parent_def_id.to_def_id()), + fn_has_self_parameter: has_self, + } +} + +fn associated_item_from_impl_item_ref( + tcx: TyCtxt<'_>, + parent_def_id: LocalDefId, + impl_item_ref: &hir::ImplItemRef, +) -> ty::AssocItem { + let def_id = impl_item_ref.id.def_id; + let (kind, has_self) = match impl_item_ref.kind { + hir::AssocItemKind::Const => (ty::AssocKind::Const, false), + hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), + hir::AssocItemKind::Type => (ty::AssocKind::Type, false), + }; + + ty::AssocItem { + name: impl_item_ref.ident.name, + kind, + vis: tcx.visibility(def_id), + defaultness: impl_item_ref.defaultness, + def_id: def_id.to_def_id(), + trait_item_def_id: impl_item_ref.trait_item_def_id, + container: ty::ImplContainer(parent_def_id.to_def_id()), + fn_has_self_parameter: has_self, + } +} diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 87b729faa54..e7cc0f69e9f 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -54,10 +54,6 @@ impl<'tcx> BoundVarsCollector<'tcx> { impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { type BreakTy = (); - fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> { - // Anon const substs do not contain bound vars by default. - None - } fn visit_binder<T: TypeFoldable<'tcx>>( &mut self, t: &Binder<'tcx, T>, @@ -152,8 +148,7 @@ fn inner_resolve_instance<'tcx>( let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) { debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); - let item = tcx.associated_item(def.did); - resolve_associated_item(tcx, &item, param_env, trait_def_id, substs) + resolve_associated_item(tcx, def.did, param_env, trait_def_id, substs) } else { let ty = tcx.type_of(def.def_id_for_type_of()); let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, ty); @@ -204,19 +199,12 @@ fn inner_resolve_instance<'tcx>( fn resolve_associated_item<'tcx>( tcx: TyCtxt<'tcx>, - trait_item: &ty::AssocItem, + trait_item_id: DefId, param_env: ty::ParamEnv<'tcx>, trait_id: DefId, rcvr_substs: SubstsRef<'tcx>, ) -> Result<Option<Instance<'tcx>>, ErrorReported> { - let def_id = trait_item.def_id; - debug!( - "resolve_associated_item(trait_item={:?}, \ - param_env={:?}, \ - trait_id={:?}, \ - rcvr_substs={:?})", - def_id, param_env, trait_id, rcvr_substs - ); + debug!(?trait_item_id, ?param_env, ?trait_id, ?rcvr_substs, "resolve_associated_item"); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); @@ -232,7 +220,7 @@ fn resolve_associated_item<'tcx>( traits::ImplSource::UserDefined(impl_data) => { debug!( "resolving ImplSource::UserDefined: {:?}, {:?}, {:?}, {:?}", - param_env, trait_item, rcvr_substs, impl_data + param_env, trait_item_id, rcvr_substs, impl_data ); assert!(!rcvr_substs.needs_infer()); assert!(!trait_ref.needs_infer()); @@ -241,9 +229,9 @@ fn resolve_associated_item<'tcx>( let trait_def = tcx.trait_def(trait_def_id); let leaf_def = trait_def .ancestors(tcx, impl_data.impl_def_id)? - .leaf_def(tcx, trait_item.ident, trait_item.kind) + .leaf_def(tcx, trait_item_id) .unwrap_or_else(|| { - bug!("{:?} not found in {:?}", trait_item, impl_data.impl_def_id); + bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); let substs = tcx.infer_ctxt().enter(|infcx| { @@ -297,22 +285,22 @@ fn resolve_associated_item<'tcx>( // performs (i.e. that the definition's type in the `impl` matches // the declaration in the `trait`), so that we can cheaply check // here if it failed, instead of approximating it. - if trait_item.kind == ty::AssocKind::Const - && trait_item.def_id != leaf_def.item.def_id + if leaf_def.item.kind == ty::AssocKind::Const + && trait_item_id != leaf_def.item.def_id && leaf_def.item.def_id.is_local() { let normalized_type_of = |def_id, substs| { tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id)) }; - let original_ty = normalized_type_of(trait_item.def_id, rcvr_substs); + let original_ty = normalized_type_of(trait_item_id, rcvr_substs); let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs); if original_ty != resolved_ty { let msg = format!( "Instance::resolve: inconsistent associated `const` type: \ was `{}: {}` but resolved to `{}: {}`", - tcx.def_path_str_with_substs(trait_item.def_id, rcvr_substs), + tcx.def_path_str_with_substs(trait_item_id, rcvr_substs), original_ty, tcx.def_path_str_with_substs(leaf_def.item.def_id, substs), resolved_ty, @@ -343,31 +331,34 @@ fn resolve_associated_item<'tcx>( } traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() { ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), + def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty), substs: rcvr_substs, }), _ => None, }, traits::ImplSource::Object(ref data) => { - let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); - Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) + let index = traits::get_vtable_index_of_object_method(tcx, data, trait_item_id); + Some(Instance { + def: ty::InstanceDef::Virtual(trait_item_id, index), + substs: rcvr_substs, + }) } traits::ImplSource::Builtin(..) => { if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() { // FIXME(eddyb) use lang items for methods instead of names. - let name = tcx.item_name(def_id); + let name = tcx.item_name(trait_item_id); if name == sym::clone { let self_ty = trait_ref.self_ty(); let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); match self_ty.kind() { _ if is_copy => (), - ty::Array(..) | ty::Closure(..) | ty::Tuple(..) => {} + ty::Closure(..) | ty::Tuple(..) => {} _ => return Ok(None), }; Some(Instance { - def: ty::InstanceDef::CloneShim(def_id, self_ty), + def: ty::InstanceDef::CloneShim(trait_item_id, self_ty), substs: rcvr_substs, }) } else { @@ -375,7 +366,7 @@ fn resolve_associated_item<'tcx>( // Use the default `fn clone_from` from `trait Clone`. let substs = tcx.erase_regions(rcvr_substs); - Some(ty::Instance::new(def_id, substs)) + Some(ty::Instance::new(trait_item_id, substs)) } } else { None diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 60f8e196bcb..55e19990761 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -16,6 +16,7 @@ extern crate tracing; use rustc_middle::ty::query::Providers; +mod assoc; mod common_traits; pub mod instance; mod needs_drop; @@ -23,6 +24,7 @@ pub mod representability; mod ty; pub fn provide(providers: &mut Providers) { + assoc::provide(providers); common_traits::provide(providers); needs_drop::provide(providers); ty::provide(providers); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 3f66e5b4ebf..fc309aa848c 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -17,7 +17,8 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> // needs drop. let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant); - let res = drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor).next().is_some(); + let res = + drop_tys_helper(tcx, query.value, query.param_env, adt_has_dtor, false).next().is_some(); debug!("needs_drop_raw({:?}) = {:?}", query, res); res @@ -27,10 +28,15 @@ fn has_significant_drop_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> bool { - let res = - drop_tys_helper(tcx, query.value, query.param_env, adt_consider_insignificant_dtor(tcx)) - .next() - .is_some(); + let res = drop_tys_helper( + tcx, + query.value, + query.param_env, + adt_consider_insignificant_dtor(tcx), + true, + ) + .next() + .is_some(); debug!("has_significant_drop_raw({:?}) = {:?}", query, res); res } @@ -141,9 +147,11 @@ where Ok(tys) => tys, }; for required_ty in tys { - let subst_ty = - tcx.normalize_erasing_regions(self.param_env, required_ty); - queue_type(self, subst_ty); + let required = tcx + .try_normalize_erasing_regions(self.param_env, required_ty) + .unwrap_or(required_ty); + + queue_type(self, required); } } ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => { @@ -186,16 +194,39 @@ fn drop_tys_helper<'tcx>( ty: Ty<'tcx>, param_env: rustc_middle::ty::ParamEnv<'tcx>, adt_has_dtor: impl Fn(&ty::AdtDef) -> Option<DtorType>, + only_significant: bool, ) -> impl Iterator<Item = NeedsDropResult<Ty<'tcx>>> { + fn with_query_cache<'tcx>( + tcx: TyCtxt<'tcx>, + iter: impl IntoIterator<Item = Ty<'tcx>>, + only_significant: bool, + ) -> NeedsDropResult<Vec<Ty<'tcx>>> { + iter.into_iter().try_fold(Vec::new(), |mut vec, subty| { + match subty.kind() { + ty::Adt(adt_id, subst) => { + for subty in if only_significant { + tcx.adt_significant_drop_tys(adt_id.did)? + } else { + tcx.adt_drop_tys(adt_id.did)? + } { + vec.push(subty.subst(tcx, subst)); + } + } + _ => vec.push(subty), + }; + Ok(vec) + }) + } + let adt_components = move |adt_def: &ty::AdtDef, substs: SubstsRef<'tcx>| { if adt_def.is_manually_drop() { debug!("drop_tys_helper: `{:?}` is manually drop", adt_def); - return Ok(Vec::new().into_iter()); + Ok(Vec::new()) } else if let Some(dtor_info) = adt_has_dtor(adt_def) { match dtor_info { DtorType::Significant => { debug!("drop_tys_helper: `{:?}` implements `Drop`", adt_def); - return Err(AlwaysRequiresDrop); + Err(AlwaysRequiresDrop) } DtorType::Insignificant => { debug!("drop_tys_helper: `{:?}` drop is insignificant", adt_def); @@ -203,22 +234,27 @@ fn drop_tys_helper<'tcx>( // Since the destructor is insignificant, we just want to make sure all of // the passed in type parameters are also insignificant. // Eg: Vec<T> dtor is insignificant when T=i32 but significant when T=Mutex. - return Ok(substs.types().collect::<Vec<Ty<'_>>>().into_iter()); + with_query_cache(tcx, substs.types(), only_significant) } } } else if adt_def.is_union() { debug!("drop_tys_helper: `{:?}` is a union", adt_def); - return Ok(Vec::new().into_iter()); + Ok(Vec::new()) + } else { + with_query_cache( + tcx, + adt_def.all_fields().map(|field| { + let r = tcx.type_of(field.did).subst(tcx, substs); + debug!( + "drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", + field, substs, r + ); + r + }), + only_significant, + ) } - Ok(adt_def - .all_fields() - .map(|field| { - let r = tcx.type_of(field.did).subst(tcx, substs); - debug!("drop_tys_helper: Subst into {:?} with {:?} gettng {:?}", field, substs, r); - r - }) - .collect::<Vec<_>>() - .into_iter()) + .map(|v| v.into_iter()) }; NeedsDropTypes::new(tcx, param_env, ty, adt_components) @@ -252,20 +288,24 @@ fn adt_drop_tys(tcx: TyCtxt<'_>, def_id: DefId) -> Result<&ty::List<Ty<'_>>, Alw // significant. let adt_has_dtor = |adt_def: &ty::AdtDef| adt_def.destructor(tcx).map(|_| DtorType::Significant); - drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor) + // `tcx.type_of(def_id)` identical to `tcx.make_adt(def, identity_substs)` + drop_tys_helper(tcx, tcx.type_of(def_id), tcx.param_env(def_id), adt_has_dtor, false) .collect::<Result<Vec<_>, _>>() .map(|components| tcx.intern_type_list(&components)) } - +// If `def_id` refers to a generic ADT, the queries above and below act as if they had been handed +// a `tcx.make_ty(def, identity_substs)` and as such it is legal to substitue the generic parameters +// of the ADT into the outputted `ty`s. fn adt_significant_drop_tys( tcx: TyCtxt<'_>, def_id: DefId, ) -> Result<&ty::List<Ty<'_>>, AlwaysRequiresDrop> { drop_tys_helper( tcx, - tcx.type_of(def_id), + tcx.type_of(def_id), // identical to `tcx.make_adt(def, identity_substs)` tcx.param_env(def_id), adt_consider_insignificant_dtor(tcx), + true, ) .collect::<Result<Vec<_>, _>>() .map(|components| tcx.intern_type_list(&components)) diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index d3eb9fd9557..fb7fdacf5e6 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -99,12 +99,7 @@ fn are_inner_types_recursive<'tcx>( // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); - let span = match field - .did - .as_local() - .map(|id| tcx.hir().local_def_id_to_hir_id(id)) - .and_then(|id| tcx.hir().find(id)) - { + let span = match field.did.as_local().and_then(|id| tcx.hir().find_by_def_id(id)) { Some(hir::Node::Field(field)) => field.ty.span, _ => sp, }; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 5a240a7dacf..b882a940d40 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,11 +1,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{ - self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, -}; -use rustc_span::Span; +use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; +use rustc_span::{sym, Span}; use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( @@ -73,93 +71,8 @@ fn sized_constraint_for_ty<'tcx>( result } -fn associated_item_from_trait_item_ref( - tcx: TyCtxt<'_>, - parent_def_id: LocalDefId, - trait_item_ref: &hir::TraitItemRef, -) -> ty::AssocItem { - let def_id = trait_item_ref.id.def_id; - let (kind, has_self) = match trait_item_ref.kind { - hir::AssocItemKind::Const => (ty::AssocKind::Const, false), - hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), - hir::AssocItemKind::Type => (ty::AssocKind::Type, false), - }; - - ty::AssocItem { - ident: trait_item_ref.ident, - kind, - vis: tcx.visibility(def_id), - defaultness: trait_item_ref.defaultness, - def_id: def_id.to_def_id(), - container: ty::TraitContainer(parent_def_id.to_def_id()), - fn_has_self_parameter: has_self, - } -} - -fn associated_item_from_impl_item_ref( - tcx: TyCtxt<'_>, - parent_def_id: LocalDefId, - impl_item_ref: &hir::ImplItemRef, -) -> ty::AssocItem { - let def_id = impl_item_ref.id.def_id; - let (kind, has_self) = match impl_item_ref.kind { - hir::AssocItemKind::Const => (ty::AssocKind::Const, false), - hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self), - hir::AssocItemKind::Type => (ty::AssocKind::Type, false), - }; - - ty::AssocItem { - ident: impl_item_ref.ident, - kind, - vis: tcx.visibility(def_id), - defaultness: impl_item_ref.defaultness, - def_id: def_id.to_def_id(), - container: ty::ImplContainer(parent_def_id.to_def_id()), - fn_has_self_parameter: has_self, - } -} - -fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { - let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let parent_id = tcx.hir().get_parent_item(id); - let parent_def_id = tcx.hir().local_def_id(parent_id); - let parent_item = tcx.hir().expect_item(parent_id); - match parent_item.kind { - hir::ItemKind::Impl(ref impl_) => { - if let Some(impl_item_ref) = - impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) - { - let assoc_item = - associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref); - debug_assert_eq!(assoc_item.def_id, def_id); - return assoc_item; - } - } - - hir::ItemKind::Trait(.., ref trait_item_refs) => { - if let Some(trait_item_ref) = - trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) - { - let assoc_item = - associated_item_from_trait_item_ref(tcx, parent_def_id, trait_item_ref); - debug_assert_eq!(assoc_item.def_id, def_id); - return assoc_item; - } - } - - _ => {} - } - - span_bug!( - parent_item.span, - "unexpected parent of trait or impl item or item not found: {:?}", - parent_item.kind - ) -} - fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.defaultness } else { @@ -168,8 +81,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { } fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.constness } else { @@ -201,26 +113,6 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain ty::AdtSizedConstraint(result) } -fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { - let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(id); - match item.kind { - hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( - trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), - ), - hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), - ), - hir::ItemKind::TraitAlias(..) => &[], - _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), - } -} - -fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> { - let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); - ty::AssocItems::new(items) -} - fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { tcx.hir() .get_if_local(def_id) @@ -236,22 +128,12 @@ fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> { .map(|ident| ident.span) } -/// If the given `DefId` describes an item belonging to a trait, -/// returns the `DefId` of the trait that the trait item belongs to; -/// otherwise, returns `None`. -fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> { - tcx.opt_associated_item(def_id).and_then(|associated_item| match associated_item.container { - ty::TraitContainer(def_id) => Some(def_id), - ty::ImplContainer(_) => None, - }) -} - /// See `ParamEnv` struct definition for details. #[instrument(level = "debug", skip(tcx))] fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -275,26 +157,85 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { predicates.extend(environment); } - // It's important that we include the default substs in unevaluated - // constants, since `Unevaluated` instances in predicates whose substs are None - // can lead to "duplicate" caller bounds candidates during trait selection, - // duplicate in the sense that both have their default substs, but the - // candidate that resulted from a superpredicate still uses `None` in its - // `substs_` field of `Unevaluated` to indicate that it has its default substs, - // whereas the other candidate has `substs_: Some(default_substs)`, see - // issue #89334 - predicates = tcx.expose_default_const_substs(predicates); - - let unnormalized_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); - - debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); - let body_id = def_id - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - .map_or(hir::CRATE_HIR_ID, |id| { - tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) - }); + let local_did = def_id.as_local(); + let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); + + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.has_attr(def_id, sym::default_method_body_is_const) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + None => hir::Constness::NotConst, + }; + + let unnormalized_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + traits::Reveal::UserFacing, + constness, + ); + + let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| { + tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) + }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) } @@ -316,7 +257,7 @@ fn well_formed_types_in_env<'tcx>( // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. @@ -328,8 +269,7 @@ fn well_formed_types_in_env<'tcx>( if !def_id.is_local() { return ty::List::empty(); } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let node = tcx.hir().get(hir_id); + let node = tcx.hir().get_by_def_id(def_id.expect_local()); enum NodeKind { TraitImpl, @@ -383,7 +323,7 @@ fn well_formed_types_in_env<'tcx>( // constituents are well-formed. NodeKind::InherentImpl => { let self_ty = tcx.type_of(def_id); - inputs.extend(self_ty.walk(tcx)); + inputs.extend(self_ty.walk()); } // In an fn, we assume that the arguments and all their constituents are @@ -392,7 +332,7 @@ fn well_formed_types_in_env<'tcx>( let fn_sig = tcx.fn_sig(def_id); let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig); - inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk(tcx))); + inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk())); } NodeKind::Other => (), @@ -485,9 +425,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Ty<'_>> { /// Check if a function is async. fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - - let node = tcx.hir().get(hir_id); + let node = tcx.hir().get_by_def_id(def_id.expect_local()); let fn_kind = node.fn_kind().unwrap_or_else(|| { bug!("asyncness: expected fn-like node but got `{:?}`", def_id); @@ -556,14 +494,10 @@ pub fn conservative_is_privately_uninhabited_raw<'tcx>( pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { asyncness, - associated_item, - associated_item_def_ids, - associated_items, adt_sized_constraint, def_ident_span, param_env, param_env_reveal_all_normalized, - trait_of_item, instance_def_size_estimate, issue33140_self_ty, impl_defaultness, |
