about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-03-16 01:11:04 +0000
committerMichael Goulet <michael@errs.io>2023-03-16 01:59:41 +0000
commitff7c3b854df3f61380261fa2d32cd4c0843ebc83 (patch)
tree26f558e576f0cc33aac1af6c456a980417fc6c93 /compiler
parent0949da8f4e309ac5e5035250bd662dfdbd5c32b4 (diff)
downloadrust-ff7c3b854df3f61380261fa2d32cd4c0843ebc83.tar.gz
rust-ff7c3b854df3f61380261fa2d32cd4c0843ebc83.zip
Don't install default opaque projection predicates in RPITIT associated type's param-env
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs28
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs22
2 files changed, 32 insertions, 18 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1687aff56d6..c063b766227 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1545,21 +1545,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
         && assoc_item.container == ty::AssocItemContainer::TraitContainer
     {
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+        // strategy, we can't just call `check_associated_item` on the new RPITITs,
+        // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+        // That's because we need to check that the bounds of the RPITIT hold using
+        // the special substs that we create during opaque type lowering, otherwise we're
+        // getting a bunch of early bound and free regions mixed up... Haven't looked too
+        // deep into this, though.
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Alias(ty::Opaque, proj) = ty.kind()
-                // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) we should just check
-                // `tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder`. Right now
-                // `check_associated_type_bounds` is not called for RPITITs synthesized as
-                // associated types. See `check_mod_type_wf` to see how synthesized associated
-                // types are missed due to iterating over HIR.
-                && tcx.is_impl_trait_in_trait(proj.def_id)
-                && tcx.impl_trait_in_trait_parent_fn(proj.def_id) == fn_def_id.to_def_id()
+                // RPITITs are always eagerly normalized into opaques, so always look for an
+                // opaque here.
+                && let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
+                && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
+                && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+                && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+                && source == fn_def_id
             {
-                let span = tcx.def_span(proj.def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
+                let span = tcx.def_span(opaque_ty.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
-                    let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
+                    let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
                     traits::wf::predicate_obligations(
                         wfcx.infcx,
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index df4b8543ba6..9fed1e57c92 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -117,16 +117,22 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
 
 /// See `ParamEnv` struct definition for details.
 fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
-    // When computing the param_env of an RPITIT, copy param_env of the containing function. The
-    // synthesized associated type doesn't have extra predicates to assume.
-    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
-        return tcx.param_env(fn_def_id);
-    }
-
     // Compute the bounds on Self and the type parameters.
     let ty::InstantiatedPredicates { mut predicates, .. } =
         tcx.predicates_of(def_id).instantiate_identity(tcx);
 
+    // When computing the param_env of an RPITIT, use predicates of the containing function,
+    // *except* for the additional assumption that the RPITIT normalizes to the trait method's
+    // default opaque type. This is needed to properly check the item bounds of the assoc
+    // type hold (`check_type_bounds`), since that method already installs a similar projection
+    // bound, so they will conflict.
+    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
+    // at least be making sure that the generics in RPITITs and their parent fn don't
+    // get out of alignment, or else we do actually need to substitute these predicates.
+    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
+        predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+    }
+
     // Finally, we have to normalize the bounds in the environment, in
     // case they contain any associated type projections. This process
     // can yield errors if the put in illegal associated types, like
@@ -160,7 +166,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     }
 
     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));
+    // 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 {