Skip to content

Commit 0949da8

Browse files
Install projection from RPITIT to default trait method opaque correctly
1 parent c5c4340 commit 0949da8

File tree

8 files changed

+64
-19
lines changed

8 files changed

+64
-19
lines changed

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
33
use rustc_hir as hir;
44
use rustc_infer::traits::util;
55
use rustc_middle::ty::subst::InternalSubsts;
6-
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
6+
use rustc_middle::ty::{self, Ty, TyCtxt};
77
use rustc_span::def_id::DefId;
88
use rustc_span::Span;
99

@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
7676
tcx: TyCtxt<'_>,
7777
def_id: DefId,
7878
) -> &'_ [(ty::Predicate<'_>, Span)] {
79-
// If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
80-
// generated the synthesized associate type.
81-
let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
82-
tcx.opt_rpitit_info(def_id)
83-
{
84-
Some(opaque_def_id)
85-
} else {
86-
None
87-
};
79+
match tcx.opt_rpitit_info(def_id) {
80+
// RPITIT's bounds are the same as opaque type bounds, but with
81+
// a projection self type.
82+
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
83+
let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
84+
let opaque_ty = item.expect_opaque_ty();
85+
return opaque_type_bounds(
86+
tcx,
87+
opaque_def_id,
88+
opaque_ty.bounds,
89+
tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
90+
item.span,
91+
);
92+
}
93+
// These should have been fed!
94+
Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
95+
None => {}
96+
}
8897

89-
let bounds_def_id = rpitit_info.unwrap_or(def_id);
90-
let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
98+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
9199
match tcx.hir().get(hir_id) {
92100
hir::Node::TraitItem(hir::TraitItem {
93101
kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
100108
..
101109
}) => {
102110
let substs = InternalSubsts::identity_for_item(tcx, def_id);
103-
let item_ty = if *in_trait || rpitit_info.is_some() {
111+
let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
104112
tcx.mk_projection(def_id, substs)
105113
} else {
106114
tcx.mk_opaque(def_id, substs)
107115
};
108-
opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
116+
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
109117
}
110118
_ => bug!("item_bounds called on {:?}", def_id),
111119
}

compiler/rustc_ty_utils/src/ty.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
268268

269269
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
270270
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
271-
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) need to project to the opaque, could
272-
// get it via type_of + subst.
273271
&& self.tcx.is_impl_trait_in_trait(alias_ty.def_id)
274272
&& self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
275273
&& self.seen.insert(alias_ty.def_id)
@@ -284,11 +282,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
284282
re
285283
}
286284
});
285+
286+
// If we're lowering to associated item, install the opaque type which is just
287+
// the `type_of` of the trait's associated item. If we're using the old lowering
288+
// strategy, then just reinterpret the associated type like an opaque :^)
289+
let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
290+
self
291+
.tcx
292+
.type_of(alias_ty.def_id)
293+
.subst(self.tcx, alias_ty.substs)
294+
} else {
295+
self.tcx.mk_alias(ty::Opaque, alias_ty)
296+
};
297+
287298
self.predicates.push(
288299
ty::Binder::bind_with_vars(
289300
ty::ProjectionPredicate {
290301
projection_ty: alias_ty,
291-
term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
302+
term: default_ty.into(),
292303
},
293304
self.bound_vars,
294305
)

tests/ui/async-await/in-trait/async-default-fn-overridden.stderr renamed to tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/async-default-fn-overridden.rs:4:12
2+
--> $DIR/async-default-fn-overridden.rs:6:12
33
|
44
LL | #![feature(async_fn_in_trait)]
55
| ^^^^^^^^^^^^^^^^^
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/async-default-fn-overridden.rs:6:12
3+
|
4+
LL | #![feature(async_fn_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/async-await/in-trait/async-default-fn-overridden.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// run-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)]
57
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use

tests/ui/impl-trait/in-trait/default-method-constraint.stderr renamed to tests/ui/impl-trait/in-trait/default-method-constraint.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/default-method-constraint.rs:5:12
2+
--> $DIR/default-method-constraint.rs:7: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/default-method-constraint.rs:7: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/default-method-constraint.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
// This didn't work in the previous default RPITIT method hack attempt
46

0 commit comments

Comments
 (0)