diff options
Diffstat (limited to 'compiler/rustc_ty_utils/src')
| -rw-r--r-- | compiler/rustc_ty_utils/src/assoc.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/implied_bounds.rs | 88 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/lib.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/needs_drop.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 88 |
7 files changed, 131 insertions, 94 deletions
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 4a544232174..780f7ea426f 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -346,8 +346,16 @@ fn associated_type_for_impl_trait_in_impl( ) -> LocalDefId { let impl_local_def_id = tcx.local_parent(impl_fn_def_id); - // FIXME fix the span, we probably want the def_id of the return type of the function - let span = tcx.def_span(impl_fn_def_id); + let decl = tcx + .hir() + .find_by_def_id(impl_fn_def_id) + .expect("expected item") + .fn_decl() + .expect("expected decl"); + let span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id), + hir::FnRetTy::Return(ty) => ty.span, + }; let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy); let local_def_id = impl_assoc_ty.def_id(); diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index be063a097c0..7eb1042d2f8 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -1,13 +1,22 @@ +use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_middle::middle::resolve_bound_vars as rbv; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use std::iter; pub fn provide(providers: &mut Providers) { - *providers = Providers { assumed_wf_types, ..*providers }; + *providers = Providers { + assumed_wf_types, + assumed_wf_types_for_rpitit: |tcx, def_id| { + assert!(tcx.is_impl_trait_in_trait(def_id.to_def_id())); + tcx.assumed_wf_types(def_id) + }, + ..*providers + }; } fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { @@ -42,6 +51,81 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' let mut impl_spans = impl_spans(tcx, def_id); tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) } + DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => match data { + ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { + let hir::OpaqueTy { lifetime_mapping, .. } = + *tcx.hir().expect_item(opaque_def_id.expect_local()).expect_opaque_ty(); + // We need to remap all of the late-bound lifetimes in theassumed wf types + // of the fn (which are represented as ReFree) to the early-bound lifetimes + // of the RPITIT (which are represented by ReEarlyBound owned by the opaque). + // Luckily, this is very easy to do because we already have that mapping + // stored in the HIR of this RPITIT. + // + // Side-note: We don't really need to do this remapping for early-bound + // lifetimes because they're already "linked" by the bidirectional outlives + // predicates we insert in the `explicit_predicates_of` query for RPITITs. + let mut mapping = FxHashMap::default(); + let generics = tcx.generics_of(def_id); + for &(lifetime, new_early_bound_def_id) in + lifetime_mapping.expect("expected lifetime mapping for RPITIT") + { + if let Some(rbv::ResolvedArg::LateBound(_, _, def_id)) = + tcx.named_bound_var(lifetime.hir_id) + { + let name = tcx.hir().name(lifetime.hir_id); + let index = generics + .param_def_id_to_index(tcx, new_early_bound_def_id.to_def_id()) + .unwrap(); + mapping.insert( + ty::Region::new_free( + tcx, + fn_def_id, + ty::BoundRegionKind::BrNamed(def_id, name), + ), + ty::Region::new_early_bound( + tcx, + ty::EarlyBoundRegion { + def_id: new_early_bound_def_id.to_def_id(), + index, + name, + }, + ), + ); + } + } + // FIXME: This could use a real folder, I guess. + let remapped_wf_tys = tcx.fold_regions( + tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(), + |region, _| { + // If `region` is a `ReFree` that is captured by the + // opaque, remap it to its corresponding the early- + // bound region. + if let Some(remapped_region) = mapping.get(®ion) { + *remapped_region + } else { + region + } + }, + ); + tcx.arena.alloc_from_iter(remapped_wf_tys) + } + // Assumed wf types for RPITITs in an impl just inherit (and instantiate) + // the assumed wf types of the trait's RPITIT GAT. + ty::ImplTraitInTraitData::Impl { .. } => { + let impl_def_id = tcx.local_parent(def_id); + let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap(); + let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( + tcx, + impl_def_id.to_def_id(), + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args, + ); + tcx.arena.alloc_from_iter( + ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id)) + .iter_instantiated_copied(tcx, args) + .chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()), + ) + } + }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { DefKind::TyAlias => ty::List::empty(), @@ -51,7 +135,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' // assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself // and `&'static T`. DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"), - def_kind @ _ => { + def_kind => { bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}") } }, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 16b1836ba9f..a21b5ef05e6 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -2,7 +2,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::traits::CodegenObligationError; +use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitableExt}; use rustc_span::sym; @@ -177,12 +177,15 @@ fn resolve_associated_item<'tcx>( Some(ty::Instance::new(leaf_def.item.def_id, args)) } - traits::ImplSource::Object(ref data) => { - traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { - Instance { def: ty::InstanceDef::Virtual(trait_item_id, index), args: rcvr_args } - }) + traits::ImplSource::Builtin(BuiltinImplSource::Object { vtable_base }, _) => { + traits::get_vtable_index_of_object_method(tcx, *vtable_base, trait_item_id).map( + |index| Instance { + def: ty::InstanceDef::Virtual(trait_item_id, index), + args: rcvr_args, + }, + ) } - traits::ImplSource::Builtin(..) => { + traits::ImplSource::Builtin(BuiltinImplSource::Misc, _) => { let lang_items = tcx.lang_items(); if Some(trait_ref.def_id) == lang_items.clone_trait() { // FIXME(eddyb) use lang items for methods instead of names. @@ -290,7 +293,9 @@ fn resolve_associated_item<'tcx>( None } } - traits::ImplSource::Param(..) | traits::ImplSource::TraitUpcasting(_) => None, + traits::ImplSource::Param(..) + | traits::ImplSource::Builtin(BuiltinImplSource::TraitUpcasting { .. }, _) + | traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => None, }) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b840ff184e0..3500c2cc370 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -96,6 +96,13 @@ fn layout_of_uncached<'tcx>( cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, ty: Ty<'tcx>, ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> { + // Types that reference `ty::Error` pessimistically don't have a meaningful layout. + // The only side-effect of this is possibly worse diagnostics in case the layout + // was actually computable (like if the `ty::Error` showed up only in a `PhantomData`). + if let Err(guar) = ty.error_reported() { + return Err(error(cx, LayoutError::ReferencesError(guar))); + } + let tcx = cx.tcx; let param_env = cx.param_env; let dl = cx.data_layout(); @@ -564,11 +571,15 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) | ty::Infer(_) => { + ty::Bound(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Infer(_) + | ty::Error(_) => { bug!("Layout::compute: unexpected type `{}`", ty) } - ty::Placeholder(..) | ty::Param(_) | ty::Error(_) => { + ty::Placeholder(..) | ty::Param(_) => { return Err(error(cx, LayoutError::Unknown(ty))); } }) diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 55b8857ed39..147b600f7ba 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -8,6 +8,7 @@ #![feature(assert_matches)] #![feature(iterator_try_collect)] #![feature(let_chains)] +#![feature(if_let_guard)] #![feature(never_type)] #![feature(box_patterns)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index e173bba49be..f89558a4599 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -133,7 +133,7 @@ where _ => { tcx.sess.delay_span_bug( tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP), - format!("unexpected generator witness type {:?}", witness), + format!("unexpected generator witness type {witness:?}"), ); return Some(Err(AlwaysRequiresDrop)); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 505f78d0e5f..791a1f4fa99 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -129,7 +129,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // sure that this will succeed without errors anyway. if tcx.def_kind(def_id) == DefKind::AssocFn - && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer + && let assoc_item = tcx.associated_item(def_id) + && assoc_item.container == ty::AssocItemContainer::TraitContainer + && assoc_item.defaultness(tcx).has_value() { let sig = tcx.fn_sig(def_id).instantiate_identity(); // We accounted for the binder of the fn sig, so skip the binder. @@ -144,85 +146,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { } let local_did = def_id.as_local(); - // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for - // RPITITs in const trait fn. - let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id)); - - // FIXME(consts): This is not exactly in line with the constness query. - 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.is_const_default_method(def_id) => - { - 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::ConstBlock(_) - | 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::Type(..) | hir::ImplItemKind::Fn(..), - .. - }) => { - let parent_hir_id = tcx.hir().parent_id(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, - }, - // FIXME(consts): It's suspicious that a param-env for a foreign item - // will always have NotConst param-env, though we don't typically use - // that param-env for anything meaningful right now, so it's likely - // not an issue. - None => hir::Constness::NotConst, - }; let unnormalized_env = - ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing, constness); + ty::ParamEnv::new(tcx.mk_clauses(&predicates), traits::Reveal::UserFacing); let body_id = local_did.unwrap_or(CRATE_DEF_ID); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); @@ -255,8 +181,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind() - && self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id) - && self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id + && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. } + | ty::ImplTraitInTraitData::Impl { fn_def_id, .. }) + = self.tcx.opt_rpitit_info(unshifted_alias_ty.def_id) + && fn_def_id == self.fn_def_id && self.seen.insert(unshifted_alias_ty.def_id) { // We have entered some binders as we've walked into the |
