Skip to content

Commit 4265ef8

Browse files
Implement projection for ImplTraitPlaceholder
1 parent d34cb98 commit 4265ef8

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

compiler/rustc_privacy/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,9 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
20382038
// Visibility on them should have no effect, but to avoid the visibility
20392039
// query failing on some items, we provide it for opaque types as well.
20402040
| Node::Item(hir::Item {
2041-
kind: hir::ItemKind::Use(_, hir::UseKind::ListStem) | hir::ItemKind::OpaqueTy(..),
2041+
kind: hir::ItemKind::Use(_, hir::UseKind::ListStem)
2042+
| hir::ItemKind::OpaqueTy(..)
2043+
| hir::ItemKind::ImplTraitPlaceholder(..),
20422044
..
20432045
}) => ty::Visibility::Restricted(tcx.parent_module(hir_id)),
20442046
// Visibilities of trait impl items are inherited from their traits

compiler/rustc_trait_selection/src/traits/project.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use rustc_middle::traits::select::OverflowError;
3232
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
3333
use rustc_middle::ty::subst::Subst;
3434
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
35+
use rustc_middle::ty::DefIdTree;
3536
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
3637
use rustc_span::symbol::sym;
3738

@@ -70,6 +71,8 @@ enum ProjectionCandidate<'tcx> {
7071

7172
/// From an "impl" (or a "pseudo-impl" returned by select)
7273
Select(Selection<'tcx>),
74+
75+
ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
7376
}
7477

7578
enum ProjectionCandidateSet<'tcx> {
@@ -1265,6 +1268,8 @@ fn project<'cx, 'tcx>(
12651268

12661269
let mut candidates = ProjectionCandidateSet::None;
12671270

1271+
assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
1272+
12681273
// Make sure that the following procedures are kept in order. ParamEnv
12691274
// needs to be first because it has highest priority, and Select checks
12701275
// the return value of push_candidate which assumes it's ran at last.
@@ -1303,6 +1308,48 @@ fn project<'cx, 'tcx>(
13031308
}
13041309
}
13051310

1311+
/// The first thing we have to do is scan through the parameter
1312+
/// environment to see whether there are any projection predicates
1313+
/// there that can answer this question.
1314+
fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
1315+
selcx: &mut SelectionContext<'cx, 'tcx>,
1316+
obligation: &ProjectionTyObligation<'tcx>,
1317+
candidate_set: &mut ProjectionCandidateSet<'tcx>,
1318+
) {
1319+
let tcx = selcx.tcx();
1320+
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
1321+
let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id);
1322+
let trait_def_id = tcx.parent(trait_fn_def_id);
1323+
let trait_substs =
1324+
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
1325+
// FIXME(named-returns): Binders
1326+
let trait_predicate =
1327+
ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs })
1328+
.to_poly_trait_predicate();
1329+
1330+
let _ =
1331+
selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
1332+
Ok(Some(super::ImplSource::UserDefined(data))) => {
1333+
candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
1334+
Ok(())
1335+
}
1336+
Ok(None) => {
1337+
candidate_set.mark_ambiguous();
1338+
return Err(());
1339+
}
1340+
Ok(Some(_)) => {
1341+
// Don't know enough about the impl to provide a useful signature
1342+
return Err(());
1343+
}
1344+
Err(e) => {
1345+
debug!(error = ?e, "selection error");
1346+
candidate_set.mark_error(e);
1347+
return Err(());
1348+
}
1349+
});
1350+
}
1351+
}
1352+
13061353
/// The first thing we have to do is scan through the parameter
13071354
/// environment to see whether there are any projection predicates
13081355
/// there that can answer this question.
@@ -1745,6 +1792,9 @@ fn confirm_candidate<'cx, 'tcx>(
17451792
ProjectionCandidate::Select(impl_source) => {
17461793
confirm_select_candidate(selcx, obligation, impl_source)
17471794
}
1795+
ProjectionCandidate::ImplTraitInTrait(data) => {
1796+
confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
1797+
}
17481798
};
17491799

17501800
// When checking for cycle during evaluation, we compare predicates with
@@ -2107,6 +2157,73 @@ fn confirm_impl_candidate<'cx, 'tcx>(
21072157
}
21082158
}
21092159

2160+
fn confirm_impl_trait_in_trait_candidate<'tcx>(
2161+
selcx: &mut SelectionContext<'_, 'tcx>,
2162+
obligation: &ProjectionTyObligation<'tcx>,
2163+
data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
2164+
) -> Progress<'tcx> {
2165+
let tcx = selcx.tcx();
2166+
let mut obligations = data.nested;
2167+
2168+
let trait_fn_def_id = tcx.parent(obligation.predicate.item_def_id);
2169+
let Ok(leaf_def) = assoc_def(selcx, data.impl_def_id, trait_fn_def_id) else {
2170+
return Progress { term: tcx.ty_error().into(), obligations };
2171+
};
2172+
if !leaf_def.item.defaultness(tcx).has_value() {
2173+
return Progress { term: tcx.ty_error().into(), obligations };
2174+
}
2175+
2176+
let impl_fn_def_id = leaf_def.item.def_id;
2177+
let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs);
2178+
2179+
let sig = tcx
2180+
.bound_fn_sig(impl_fn_def_id)
2181+
.map_bound(|fn_sig| tcx.liberate_late_bound_regions(impl_fn_def_id, fn_sig))
2182+
.subst(tcx, impl_fn_substs);
2183+
2184+
let cause = ObligationCause::new(
2185+
obligation.cause.span,
2186+
obligation.cause.body_id,
2187+
super::ItemObligation(impl_fn_def_id),
2188+
);
2189+
let predicates = normalize_with_depth_to(
2190+
selcx,
2191+
obligation.param_env,
2192+
cause.clone(),
2193+
obligation.recursion_depth + 1,
2194+
tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
2195+
&mut obligations,
2196+
);
2197+
obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map(
2198+
|(pred, span)| {
2199+
Obligation::with_depth(
2200+
ObligationCause::new(
2201+
obligation.cause.span,
2202+
obligation.cause.body_id,
2203+
if span.is_dummy() {
2204+
super::ItemObligation(impl_fn_def_id)
2205+
} else {
2206+
super::BindingObligation(impl_fn_def_id, span)
2207+
},
2208+
),
2209+
obligation.recursion_depth + 1,
2210+
obligation.param_env,
2211+
pred,
2212+
)
2213+
},
2214+
));
2215+
2216+
let ty = super::normalize_to(
2217+
selcx,
2218+
obligation.param_env,
2219+
cause.clone(),
2220+
sig.output(),
2221+
&mut obligations,
2222+
);
2223+
2224+
Progress { term: ty.into(), obligations }
2225+
}
2226+
21102227
// Get obligations corresponding to the predicates from the where-clause of the
21112228
// associated type itself.
21122229
// Note: `feature(generic_associated_types)` is required to write such

0 commit comments

Comments
 (0)