Skip to content

Commit 21047f1

Browse files
Support default-body trait functions with RPITIT
1 parent d4846f9 commit 21047f1

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

compiler/rustc_hir_analysis/src/collect/type_of.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
340340
..
341341
}) => {
342342
if in_trait {
343-
span_bug!(item.span, "impl-trait in trait has no default")
344-
} else {
345-
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
343+
assert!(tcx.impl_defaultness(owner).has_value());
346344
}
345+
find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
347346
}
348347
ItemKind::Trait(..)
349348
| ItemKind::TraitAlias(..)

compiler/rustc_trait_selection/src/traits/project.rs

+43-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,15 @@ enum ProjectionCandidate<'tcx> {
7171
/// From an "impl" (or a "pseudo-impl" returned by select)
7272
Select(Selection<'tcx>),
7373

74-
ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
74+
ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>),
75+
}
76+
77+
#[derive(PartialEq, Eq, Debug)]
78+
enum ImplTraitInTraitCandidate<'tcx> {
79+
// The `impl Trait` from a trait function's default body
80+
Trait,
81+
// A concrete type provided from a trait's `impl Trait` from an impl
82+
Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
7583
}
7684

7785
enum ProjectionCandidateSet<'tcx> {
@@ -1317,6 +1325,17 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
13171325
) {
13181326
let tcx = selcx.tcx();
13191327
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
1328+
// If we are trying to project an RPITIT with the _identity_ substs,
1329+
// then we must be within a default trait body.
1330+
if obligation.predicate.substs
1331+
== ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
1332+
{
1333+
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
1334+
ImplTraitInTraitCandidate::Trait,
1335+
));
1336+
return;
1337+
}
1338+
13201339
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
13211340
let trait_def_id = tcx.parent(trait_fn_def_id);
13221341
let trait_substs =
@@ -1329,7 +1348,9 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
13291348
let _ =
13301349
selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
13311350
Ok(Some(super::ImplSource::UserDefined(data))) => {
1332-
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
1351+
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
1352+
ImplTraitInTraitCandidate::Impl(data),
1353+
));
13331354
Ok(())
13341355
}
13351356
Ok(None) => {
@@ -1792,9 +1813,18 @@ fn confirm_candidate<'cx, 'tcx>(
17921813
ProjectionCandidate::Select(impl_source) => {
17931814
confirm_select_candidate(selcx, obligation, impl_source)
17941815
}
1795-
ProjectionCandidate::ImplTraitInTrait(data) => {
1816+
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => {
17961817
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
17971818
}
1819+
// If we're projecting an RPITIT for a default trait body, that's just
1820+
// the same def-id, but as an opaque type (with regular RPIT semantics).
1821+
ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
1822+
term: selcx
1823+
.tcx()
1824+
.mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
1825+
.into(),
1826+
obligations: vec![],
1827+
},
17981828
};
17991829

18001830
// When checking for cycle during evaluation, we compare predicates with
@@ -2212,6 +2242,16 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
22122242
return Progress { term: tcx.ty_error().into(), obligations };
22132243
}
22142244

2245+
// Use the default `impl Trait` for the trait, e.g., for a default trait body
2246+
if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
2247+
return Progress {
2248+
term: tcx
2249+
.mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
2250+
.into(),
2251+
obligations,
2252+
};
2253+
}
2254+
22152255
let impl_fn_def_id = leaf_def.item.def_id;
22162256
let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs);
22172257

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
// edition:2021
3+
4+
#![feature(return_position_impl_trait_in_trait)]
5+
#![allow(incomplete_features)]
6+
7+
use std::fmt::Debug;
8+
9+
trait Foo {
10+
async fn baz() -> impl Debug {
11+
Self::baz().await
12+
}
13+
}
14+
15+
fn main() {}

0 commit comments

Comments
 (0)