Skip to content

Commit 6394032

Browse files
committed
Correctly lower bounds on GATs
1 parent 4b164f6 commit 6394032

File tree

1 file changed

+100
-19
lines changed

1 file changed

+100
-19
lines changed

src/librustc_typeck/collect.rs

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,25 +2300,7 @@ fn explicit_predicates_of(
23002300
// Add predicates from associated type bounds.
23012301
if let Some((self_trait_ref, trait_items)) = is_trait {
23022302
predicates.extend(trait_items.iter().flat_map(|trait_item_ref| {
2303-
let trait_item = tcx.hir().trait_item(trait_item_ref.id);
2304-
let bounds = match trait_item.kind {
2305-
hir::TraitItemKind::Type(ref bounds, _) => bounds,
2306-
_ => return Vec::new().into_iter()
2307-
};
2308-
2309-
let assoc_ty =
2310-
tcx.mk_projection(tcx.hir().local_def_id(trait_item.hir_id),
2311-
self_trait_ref.substs);
2312-
2313-
let bounds = AstConv::compute_bounds(
2314-
&ItemCtxt::new(tcx, def_id),
2315-
assoc_ty,
2316-
bounds,
2317-
SizedByDefault::Yes,
2318-
trait_item.span,
2319-
);
2320-
2321-
bounds.predicates(tcx, assoc_ty).into_iter()
2303+
associated_item_predicates(tcx, def_id, self_trait_ref, trait_item_ref)
23222304
}))
23232305
}
23242306

@@ -2352,6 +2334,105 @@ fn explicit_predicates_of(
23522334
result
23532335
}
23542336

2337+
fn associated_item_predicates(
2338+
tcx: TyCtxt<'tcx>,
2339+
def_id: DefId,
2340+
self_trait_ref: ty::TraitRef<'tcx>,
2341+
trait_item_ref: &hir::TraitItemRef,
2342+
) -> Vec<(ty::Predicate<'tcx>, Span)> {
2343+
let trait_item = tcx.hir().trait_item(trait_item_ref.id);
2344+
let item_def_id = tcx.hir().local_def_id(trait_item_ref.id.hir_id);
2345+
let bounds = match trait_item.kind {
2346+
hir::TraitItemKind::Type(ref bounds, _) => bounds,
2347+
_ => return Vec::new()
2348+
};
2349+
2350+
let is_gat = !tcx.generics_of(item_def_id).params.is_empty();
2351+
2352+
let mut had_error = false;
2353+
2354+
let mut unimplemented_error = |arg_kind: &str| {
2355+
if !had_error {
2356+
tcx.sess.struct_span_err(
2357+
trait_item.span,
2358+
&format!("{}-generic associated types are not yet implemented", arg_kind),
2359+
)
2360+
.note("for more information, see https://github.com/rust-lang/rust/issues/44265")
2361+
.emit();
2362+
had_error = true;
2363+
}
2364+
};
2365+
2366+
let mk_bound_param = |param: &ty::GenericParamDef, _: &_| {
2367+
match param.kind {
2368+
ty::GenericParamDefKind::Lifetime => {
2369+
tcx.mk_region(ty::RegionKind::ReLateBound(
2370+
ty::INNERMOST,
2371+
ty::BoundRegion::BrNamed(param.def_id, param.name)
2372+
)).into()
2373+
}
2374+
// FIXME(generic_associated_types): Use bound types and constants
2375+
// once they are handled by the trait system.
2376+
ty::GenericParamDefKind::Type { .. } => {
2377+
unimplemented_error("type");
2378+
tcx.types.err.into()
2379+
}
2380+
ty::GenericParamDefKind::Const => {
2381+
unimplemented_error("const");
2382+
tcx.consts.err.into()
2383+
}
2384+
}
2385+
};
2386+
2387+
let bound_substs = if is_gat {
2388+
// Given:
2389+
//
2390+
// trait X<'a, B, const C: usize> {
2391+
// type T<'d, E, const F: usize>: Default;
2392+
// }
2393+
//
2394+
// We need to create predicates on the trait:
2395+
//
2396+
// for<'d, E, const F: usize>
2397+
// <Self as X<'a, B, const C: usize>>::T<'d, E, const F: usize>: Sized + Default
2398+
//
2399+
// We substitute escaping bound parameters for the generic
2400+
// arguments to the associated type which are then bound by
2401+
// the `Binder` around the the predicate.
2402+
//
2403+
// FIXME(generic_associated_types): Currently only lifetimes are handled.
2404+
self_trait_ref.substs.extend_to(tcx, item_def_id, mk_bound_param)
2405+
} else {
2406+
self_trait_ref.substs
2407+
};
2408+
2409+
let assoc_ty = tcx.mk_projection(
2410+
tcx.hir().local_def_id(trait_item.hir_id),
2411+
bound_substs,
2412+
);
2413+
2414+
let bounds = AstConv::compute_bounds(
2415+
&ItemCtxt::new(tcx, def_id),
2416+
assoc_ty,
2417+
bounds,
2418+
SizedByDefault::Yes,
2419+
trait_item.span,
2420+
);
2421+
2422+
let predicates = bounds.predicates(tcx, assoc_ty);
2423+
2424+
if is_gat {
2425+
// We use shifts to get the regions that we're substituting to
2426+
// be bound by the binders in the `Predicate`s rather that
2427+
// escaping.
2428+
let shifted_in = ty::fold::shift_vars(tcx, &predicates, 1);
2429+
let substituted = shifted_in.subst(tcx, bound_substs);
2430+
ty::fold::shift_out_vars(tcx, &substituted, 1)
2431+
} else {
2432+
predicates
2433+
}
2434+
}
2435+
23552436
/// Converts a specific `GenericBound` from the AST into a set of
23562437
/// predicates that apply to the self type. A vector is returned
23572438
/// because this can be anywhere from zero predicates (`T: ?Sized` adds no

0 commit comments

Comments
 (0)