Skip to content

Commit ff7c3b8

Browse files
Don't install default opaque projection predicates in RPITIT associated type's param-env
1 parent 0949da8 commit ff7c3b8

12 files changed

+78
-21
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -1545,21 +1545,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15451545
if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
15461546
&& assoc_item.container == ty::AssocItemContainer::TraitContainer
15471547
{
1548+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
1549+
// strategy, we can't just call `check_associated_item` on the new RPITITs,
1550+
// because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
1551+
// That's because we need to check that the bounds of the RPITIT hold using
1552+
// the special substs that we create during opaque type lowering, otherwise we're
1553+
// getting a bunch of early bound and free regions mixed up... Haven't looked too
1554+
// deep into this, though.
15481555
for arg in fn_output.walk() {
15491556
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1550-
&& let ty::Alias(ty::Opaque, proj) = ty.kind()
1551-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) we should just check
1552-
// `tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder`. Right now
1553-
// `check_associated_type_bounds` is not called for RPITITs synthesized as
1554-
// associated types. See `check_mod_type_wf` to see how synthesized associated
1555-
// types are missed due to iterating over HIR.
1556-
&& tcx.is_impl_trait_in_trait(proj.def_id)
1557-
&& tcx.impl_trait_in_trait_parent_fn(proj.def_id) == fn_def_id.to_def_id()
1557+
// RPITITs are always eagerly normalized into opaques, so always look for an
1558+
// opaque here.
1559+
&& let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
1560+
&& let Some(opaque_def_id) = opaque_ty.def_id.as_local()
1561+
&& let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
1562+
&& let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
1563+
&& source == fn_def_id
15581564
{
1559-
let span = tcx.def_span(proj.def_id);
1560-
let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
1565+
let span = tcx.def_span(opaque_ty.def_id);
1566+
let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
15611567
let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
1562-
let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
1568+
let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
15631569
let normalized_bound = wfcx.normalize(span, None, bound);
15641570
traits::wf::predicate_obligations(
15651571
wfcx.infcx,

compiler/rustc_ty_utils/src/ty.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,22 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
117117

118118
/// See `ParamEnv` struct definition for details.
119119
fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
120-
// When computing the param_env of an RPITIT, copy param_env of the containing function. The
121-
// synthesized associated type doesn't have extra predicates to assume.
122-
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
123-
return tcx.param_env(fn_def_id);
124-
}
125-
126120
// Compute the bounds on Self and the type parameters.
127121
let ty::InstantiatedPredicates { mut predicates, .. } =
128122
tcx.predicates_of(def_id).instantiate_identity(tcx);
129123

124+
// When computing the param_env of an RPITIT, use predicates of the containing function,
125+
// *except* for the additional assumption that the RPITIT normalizes to the trait method's
126+
// default opaque type. This is needed to properly check the item bounds of the assoc
127+
// type hold (`check_type_bounds`), since that method already installs a similar projection
128+
// bound, so they will conflict.
129+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
130+
// at least be making sure that the generics in RPITITs and their parent fn don't
131+
// get out of alignment, or else we do actually need to substitute these predicates.
132+
if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
133+
predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
134+
}
135+
130136
// Finally, we have to normalize the bounds in the environment, in
131137
// case they contain any associated type projections. This process
132138
// 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<'_> {
160166
}
161167

162168
let local_did = def_id.as_local();
163-
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
169+
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for
170+
// RPITITs in const trait fn.
171+
let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id));
164172

165173
// FIXME(consts): This is not exactly in line with the constness query.
166174
let constness = match hir_id {

tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr renamed to tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/box-coerce-span-in-default.rs:3:12
2+
--> $DIR/box-coerce-span-in-default.rs:5:12
33
|
44
LL | #![feature(return_position_impl_trait_in_trait)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/box-coerce-span-in-default.rs:5:12
3+
|
4+
LL | #![feature(return_position_impl_trait_in_trait)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: 1 warning emitted
11+

tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// check-pass
2+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
3+
// revisions: current next
24

35
#![feature(return_position_impl_trait_in_trait)]
46
//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete

tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr renamed to tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/default-body-type-err-2.rs:8:9
2+
--> $DIR/default-body-type-err-2.rs:10:9
33
|
44
LL | 42
55
| ^^- help: try using a conversion method: `.to_string()`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/default-body-type-err-2.rs:10:9
3+
|
4+
LL | 42
5+
| ^^- help: try using a conversion method: `.to_string()`
6+
| |
7+
| expected `String`, found integer
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0308`.

tests/ui/impl-trait/in-trait/default-body-type-err-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// edition:2021
2+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
3+
// revisions: current next
24

35
#![allow(incomplete_features)]
46
#![feature(async_fn_in_trait)]

tests/ui/impl-trait/in-trait/default-body-type-err.stderr renamed to tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
2-
--> $DIR/default-body-type-err.rs:7:22
2+
--> $DIR/default-body-type-err.rs:10:22
33
|
44
LL | fn lol(&self) -> impl Deref<Target = String> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
2+
--> $DIR/default-body-type-err.rs:10:22
3+
|
4+
LL | fn lol(&self) -> impl Deref<Target = String> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
6+
LL |
7+
LL | &1i32
8+
| ----- return type was inferred to be `&i32` here
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0271`.

tests/ui/impl-trait/in-trait/default-body-type-err.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
2+
// revisions: current next
3+
14
#![allow(incomplete_features)]
25
#![feature(return_position_impl_trait_in_trait)]
36

tests/ui/impl-trait/in-trait/default-body.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// check-pass
22
// edition:2021
3+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
4+
// revisions: current next
35

46
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
57
#![allow(incomplete_features)]

0 commit comments

Comments
 (0)