Skip to content

Commit a64db44

Browse files
Support trait predicates on poly trait refs
1 parent 9ba1590 commit a64db44

File tree

9 files changed

+71
-16
lines changed

9 files changed

+71
-16
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20112011
hir::GenericBound::Trait(
20122012
hir::PolyTraitRef {
20132013
bound_generic_params: &[],
2014+
binder_predicates: &[],
20142015
trait_ref: hir::TraitRef {
20152016
path: self.make_lang_item_path(
20162017
trait_lang_item,
@@ -2201,10 +2202,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22012202
itctx: &ImplTraitContext,
22022203
constness: ast::Const,
22032204
) -> hir::PolyTraitRef<'hir> {
2205+
let binder_predicates =
2206+
self.arena.alloc_from_iter(p.bound_generic_params.iter().filter_map(|param| {
2207+
self.lower_generic_bound_predicate(
2208+
param.ident,
2209+
param.id,
2210+
&param.kind,
2211+
&param.bounds,
2212+
param.colon_span,
2213+
p.span,
2214+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
2215+
hir::PredicateOrigin::GenericParam,
2216+
)
2217+
}));
22042218
let bound_generic_params =
22052219
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
22062220
let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
2207-
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
2221+
hir::PolyTraitRef {
2222+
bound_generic_params,
2223+
binder_predicates,
2224+
trait_ref,
2225+
span: self.lower_span(p.span),
2226+
}
22082227
}
22092228

22102229
fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> {
@@ -2510,6 +2529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
25102529
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
25112530
let principal = hir::PolyTraitRef {
25122531
bound_generic_params: &[],
2532+
binder_predicates: &[],
25132533
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
25142534
span: self.lower_span(span),
25152535
};

compiler/rustc_hir/src/hir.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2822,6 +2822,9 @@ pub struct PolyTraitRef<'hir> {
28222822
/// The `'a` in `for<'a> Foo<&'a T>`.
28232823
pub bound_generic_params: &'hir [GenericParam<'hir>],
28242824

2825+
/// Predicates on the `for<T>` binder itself, such as `for<T: Trait> ...`
2826+
pub binder_predicates: &'hir [WherePredicate<'hir>],
2827+
28252828
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
28262829
pub trait_ref: TraitRef<'hir>,
28272830

compiler/rustc_hir/src/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
10841084
pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) {
10851085
walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
10861086
visitor.visit_trait_ref(&trait_ref.trait_ref);
1087+
walk_list!(visitor, visit_where_predicate, trait_ref.binder_predicates);
10871088
}
10881089

10891090
pub fn walk_struct_def<'v, V: Visitor<'v>>(

compiler/rustc_hir_analysis/src/astconv/bounds.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::errors;
1818
impl<'tcx> dyn AstConv<'tcx> + '_ {
1919
pub(crate) fn lower_where_predicates(
2020
&self,
21-
params: &'tcx [hir::GenericParam<'tcx>],
22-
hir_predicates: &'tcx [hir::WherePredicate<'tcx>],
21+
params: &[hir::GenericParam<'_>],
22+
hir_predicates: &[hir::WherePredicate<'_>],
2323
predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>,
2424
) {
2525
// Collect the predicates that were written inline by the user on each
@@ -140,19 +140,19 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
140140
}
141141

142142
/// Sets `implicitly_sized` to true on `Bounds` if necessary
143-
pub(crate) fn add_implicitly_sized(
143+
pub(crate) fn add_implicitly_sized<'hir>(
144144
&self,
145145
bounds: &mut Bounds<'tcx>,
146146
self_ty: Ty<'tcx>,
147-
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
148-
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
147+
ast_bounds: &'hir [hir::GenericBound<'hir>],
148+
self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>,
149149
span: Span,
150150
) {
151151
let tcx = self.tcx();
152152

153153
// Try to find an unbound in bounds.
154154
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
155-
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
155+
let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| {
156156
for ab in ast_bounds {
157157
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
158158
unbounds.push(ptr);
@@ -248,8 +248,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
248248
hir::TraitBoundModifier::Maybe => continue,
249249
};
250250

251-
// TODO: Add in the binder preds from the poly trait ref.
252-
let binder_predicates = binder_predicates;
251+
let mut additional_binder_predicates = FxIndexSet::default();
252+
self.lower_where_predicates(
253+
poly_trait_ref.bound_generic_params,
254+
poly_trait_ref.binder_predicates,
255+
&mut additional_binder_predicates,
256+
);
257+
let binder_predicates =
258+
self.tcx().mk_clauses_from_iter(binder_predicates.into_iter().chain(
259+
additional_binder_predicates.into_iter().map(|(clause, _)| clause),
260+
));
253261

254262
let _ = self.instantiate_poly_trait_ref(
255263
&poly_trait_ref.trait_ref,

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3333
let mut potential_assoc_types = Vec::new();
3434
let dummy_self = self.tcx().types.trait_object_dummy_self;
3535
for trait_bound in hir_trait_bounds.iter().rev() {
36+
assert!(
37+
trait_bound.binder_predicates.is_empty(),
38+
"FIXME(non_lifetime_binders): object types should not have binders"
39+
);
3640
if let GenericArgCountResult {
3741
correct:
3842
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
@@ -45,7 +49,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4549
dummy_self,
4650
&mut bounds,
4751
false,
48-
// TODO: dyn traits should have no binder preds
4952
ty::List::empty(),
5053
// FIXME: This should be `true`, but we don't really handle
5154
// associated type bounds or type aliases in objects in a way

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,16 @@ impl<'tcx> ItemCtxt<'tcx> {
712712
}
713713
};
714714

715+
let mut binder_predicates = FxIndexSet::default();
716+
self.astconv().lower_where_predicates(
717+
predicate.bound_generic_params,
718+
predicate.binder_predicates,
719+
&mut binder_predicates,
720+
);
721+
let binder_predicates = self
722+
.tcx
723+
.mk_clauses_from_iter(binder_predicates.into_iter().map(|(clause, _)| clause));
724+
715725
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
716726
// want to only consider predicates with `Self: ...`, but we don't want
717727
// `OnlySelfBounds(true)` since we want to collect the nested associated
@@ -733,8 +743,7 @@ impl<'tcx> ItemCtxt<'tcx> {
733743
}),
734744
&mut bounds,
735745
bound_vars,
736-
// TODO: convert `where_bound_predicate` above accordingly
737-
ty::List::empty(),
746+
binder_predicates,
738747
only_self_bounds,
739748
);
740749
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+1
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
398398
self.with(scope, |this| {
399399
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
400400
this.visit_trait_ref(&trait_ref.trait_ref);
401+
walk_list!(this, visit_where_predicate, trait_ref.binder_predicates);
401402
});
402403
}
403404
}

compiler/rustc_hir_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ pub fn hir_trait_to_predicates<'tcx>(
267267
self_ty,
268268
&mut bounds,
269269
true,
270-
// TODO: This is probably wrong!
270+
// FIXME(non_lifetime_binders): This is probably not right.
271271
ty::List::empty(),
272272
OnlySelfBounds(false),
273273
);

compiler/rustc_middle/src/ty/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -747,18 +747,28 @@ impl<'tcx> Clause<'tcx> {
747747
let pred_bound_vars = bound_pred.bound_vars();
748748
let trait_bound_vars = trait_ref.bound_vars();
749749
// 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
750-
let shifted_pred =
751-
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
750+
let (shifted_pred, shifted_bound_clauses) = tcx.shift_bound_var_indices(
751+
trait_bound_vars.len(),
752+
(bound_pred.skip_binder(), bound_pred.skip_binder_predicates()),
753+
);
752754
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
753755
let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
754756
// 3) ['x] + ['b] -> ['x, 'b]
755757
let bound_vars =
756758
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
757759

760+
let binder_predicates = tcx.mk_clauses_from_iter(
761+
trait_ref.skip_binder_predicates().into_iter().chain(shifted_bound_clauses),
762+
);
763+
758764
// FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
759765
tcx.reuse_or_mk_predicate(
760766
self.as_predicate(),
761-
ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
767+
ty::Binder::bind_with_vars_and_predicates(
768+
PredicateKind::Clause(new),
769+
bound_vars,
770+
binder_predicates,
771+
),
762772
)
763773
.expect_clause()
764774
}

0 commit comments

Comments
 (0)