Skip to content

Commit 692d764

Browse files
authored
Rollup merge of #114267 - compiler-errors:rpitit-opaque-bounds, r=spastorino
Map RPITIT's opaque type bounds back from projections to opaques An RPITIT in a program's AST is eventually translated into both a projection GAT and an opaque. The opaque is used for default trait methods, like: ``` trait Foo { fn bar() -> impl Sized { 0i32 } } ``` The item bounds for both the projection and opaque are identical, and both have a *projection* self ty. This is mostly okay, since we can normalize this projection within the default trait method body to the opaque, but it does two things: 1. it leads to bugs in places where we don't normalize item bounds, like `deduce_future_output_from_obligations` 2. it leads to extra match arms that are both suspicious looking and also easy to miss This PR maps the opaque type bounds of the RPITIT's *opaque* back to the opaque's self type to avoid this quirk. Then we can fix the UI test for #108304 (1.) and also remove a bunch of match arms (2.). Fixes #108304 r? `@spastorino`
2 parents 95b7116 + 6f5c51f commit 692d764

File tree

9 files changed

+54
-72
lines changed

9 files changed

+54
-72
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+1-15
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,6 @@ fn find_and_apply_rpit_args<'tcx>(
576576
struct Visitor<'tcx> {
577577
tcx: TyCtxt<'tcx>,
578578
opaque: DefId,
579-
function: DefId,
580579
seen: FxHashSet<DefId>,
581580
}
582581
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for Visitor<'tcx> {
@@ -601,19 +600,6 @@ fn find_and_apply_rpit_args<'tcx>(
601600
}
602601
}
603602
}
604-
ty::Alias(ty::Projection, alias) => {
605-
if self.tcx.is_impl_trait_in_trait(alias.def_id)
606-
&& self.tcx.impl_trait_in_trait_parent_fn(alias.def_id) == self.function
607-
{
608-
// If we're lowering to associated item, install the opaque type which is just
609-
// the `type_of` of the trait's associated item. If we're using the old lowering
610-
// strategy, then just reinterpret the associated type like an opaque :^)
611-
self.tcx
612-
.type_of(alias.def_id)
613-
.instantiate(self.tcx, alias.args)
614-
.visit_with(self)?;
615-
}
616-
}
617603
ty::Alias(ty::Weak, alias) => {
618604
self.tcx
619605
.type_of(alias.def_id)
@@ -627,7 +613,7 @@ fn find_and_apply_rpit_args<'tcx>(
627613
}
628614
}
629615
if let ControlFlow::Break(args) =
630-
ret.visit_with(&mut Visitor { tcx, function, opaque, seen: Default::default() })
616+
ret.visit_with(&mut Visitor { tcx, opaque, seen: Default::default() })
631617
{
632618
trace!(?args);
633619
trace!("expected: {hidden_ty:#?}");

compiler/rustc_hir_analysis/src/collect/item_bounds.rs

+46-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::astconv::{AstConv, PredicateFilter};
33
use rustc_hir as hir;
44
use rustc_infer::traits::util;
55
use rustc_middle::ty::GenericArgs;
6-
use rustc_middle::ty::{self, Ty, TyCtxt};
6+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder};
77
use rustc_span::def_id::{DefId, LocalDefId};
88
use rustc_span::Span;
99

@@ -113,14 +113,35 @@ pub(super) fn explicit_item_bounds(
113113
..
114114
}) => associated_type_bounds(tcx, def_id, bounds, *span),
115115
hir::Node::Item(hir::Item {
116-
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
116+
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
117117
span,
118118
..
119119
}) => {
120120
let args = GenericArgs::identity_for_item(tcx, def_id);
121121
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
122122
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
123123
}
124+
// Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
125+
// for the item bounds of the *opaques* in a trait's default method signature, we
126+
// need to map these projections back to opaques.
127+
hir::Node::Item(hir::Item {
128+
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: true, origin, .. }),
129+
span,
130+
..
131+
}) => {
132+
let (hir::OpaqueTyOrigin::FnReturn(fn_def_id)
133+
| hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = *origin
134+
else {
135+
bug!()
136+
};
137+
let args = GenericArgs::identity_for_item(tcx, def_id);
138+
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
139+
tcx.arena.alloc_slice(
140+
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
141+
.to_vec()
142+
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
143+
)
144+
}
124145
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
125146
_ => bug!("item_bounds called on {:?}", def_id),
126147
};
@@ -135,3 +156,26 @@ pub(super) fn item_bounds(
135156
tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
136157
})
137158
}
159+
160+
struct AssocTyToOpaque<'tcx> {
161+
tcx: TyCtxt<'tcx>,
162+
fn_def_id: DefId,
163+
}
164+
165+
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTyToOpaque<'tcx> {
166+
fn interner(&self) -> TyCtxt<'tcx> {
167+
self.tcx
168+
}
169+
170+
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
171+
if let ty::Alias(ty::Projection, projection_ty) = ty.kind()
172+
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. })
173+
= self.tcx.opt_rpitit_info(projection_ty.def_id)
174+
&& fn_def_id == self.fn_def_id
175+
{
176+
self.tcx.type_of(projection_ty.def_id).instantiate(self.tcx, projection_ty.args)
177+
} else {
178+
ty
179+
}
180+
}
181+
}

compiler/rustc_hir_typeck/src/_match.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -558,18 +558,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
558558
{
559559
let pred = clause.kind().rebind(match clause.kind().skip_binder() {
560560
ty::ClauseKind::Trait(trait_pred) => {
561-
// FIXME(rpitit): This will need to be fixed when we move to associated types
562561
assert!(matches!(
563562
*trait_pred.trait_ref.self_ty().kind(),
564-
ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. })
563+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
565564
if def_id == rpit_def_id && args == alias_args
566565
));
567566
ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
568567
}
569568
ty::ClauseKind::Projection(mut proj_pred) => {
570569
assert!(matches!(
571570
*proj_pred.projection_ty.self_ty().kind(),
572-
ty::Alias(_, ty::AliasTy { def_id, args: alias_args, .. })
571+
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args: alias_args, .. })
573572
if def_id == rpit_def_id && args == alias_args
574573
));
575574
proj_pred = proj_pred.with_self_ty(self.tcx, ty);

compiler/rustc_hir_typeck/src/closure.rs

-5
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
723723
.iter_instantiated_copied(self.tcx, args)
724724
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
725725
ty::Error(_) => return None,
726-
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
727-
.tcx
728-
.explicit_item_bounds(proj.def_id)
729-
.iter_instantiated_copied(self.tcx, proj.args)
730-
.find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
731726
_ => span_bug!(
732727
self.tcx.def_span(expr_def_id),
733728
"async fn generator return type not an inference variable: {ret_ty}"

compiler/rustc_infer/src/infer/opaque_types.rs

-7
Original file line numberDiff line numberDiff line change
@@ -619,13 +619,6 @@ impl<'tcx> InferCtxt<'tcx> {
619619
{
620620
hidden_ty
621621
}
622-
// FIXME(RPITIT): This can go away when we move to associated types
623-
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
624-
ty::Alias(ty::Projection, ty::AliasTy { def_id: def_id2, args: args2, .. })
625-
if def_id == def_id2 && args == args2 =>
626-
{
627-
hidden_ty
628-
}
629622
_ => ty,
630623
},
631624
lt_op: |lt| lt,

compiler/rustc_middle/src/ty/mod.rs

-13
Original file line numberDiff line numberDiff line change
@@ -2625,19 +2625,6 @@ impl<'tcx> TyCtxt<'tcx> {
26252625
matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
26262626
}
26272627

2628-
pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
2629-
match self.opt_rpitit_info(def_id) {
2630-
Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
2631-
| Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
2632-
None => {
2633-
while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
2634-
def_id = self.parent(def_id);
2635-
}
2636-
def_id
2637-
}
2638-
}
2639-
}
2640-
26412628
/// Returns the `DefId` of the item within which the `impl Trait` is declared.
26422629
/// For type-alias-impl-trait this is the `type` alias.
26432630
/// For impl-trait-in-assoc-type this is the assoc type.

compiler/rustc_ty_utils/src/ty.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
181181

182182
fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
183183
if let ty::Alias(ty::Projection, unshifted_alias_ty) = *ty.kind()
184-
&& self.tcx.is_impl_trait_in_trait(unshifted_alias_ty.def_id)
185-
&& self.tcx.impl_trait_in_trait_parent_fn(unshifted_alias_ty.def_id) == self.fn_def_id
184+
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }
185+
| ty::ImplTraitInTraitData::Impl { fn_def_id, .. })
186+
= self.tcx.opt_rpitit_info(unshifted_alias_ty.def_id)
187+
&& fn_def_id == self.fn_def_id
186188
&& self.seen.insert(unshifted_alias_ty.def_id)
187189
{
188190
// We have entered some binders as we've walked into the

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// edition:2021
2-
// known-bug: #108304
2+
// check-pass
33

44
#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
55
#![allow(incomplete_features)]

tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr

-24
This file was deleted.

0 commit comments

Comments
 (0)