about summary refs log tree commit diff
path: root/compiler/rustc_ty_utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src')
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs12
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs88
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs19
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs15
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs1
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs2
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs88
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(&region) {
+                            *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