Skip to content

Commit e8cc6d4

Browse files
Support trait predicates on poly trait refs
1 parent b1b8677 commit e8cc6d4

File tree

9 files changed

+70
-16
lines changed

9 files changed

+70
-16
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -2159,10 +2159,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21592159
itctx: &ImplTraitContext,
21602160
constness: ast::Const,
21612161
) -> hir::PolyTraitRef<'hir> {
2162+
let binder_predicates =
2163+
self.arena.alloc_from_iter(p.bound_generic_params.iter().filter_map(|param| {
2164+
self.lower_generic_bound_predicate(
2165+
param.ident,
2166+
param.id,
2167+
&param.kind,
2168+
&param.bounds,
2169+
param.colon_span,
2170+
p.span,
2171+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
2172+
hir::PredicateOrigin::GenericParam,
2173+
)
2174+
}));
21622175
let bound_generic_params =
21632176
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
21642177
let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
2165-
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
2178+
hir::PolyTraitRef {
2179+
bound_generic_params,
2180+
binder_predicates,
2181+
trait_ref,
2182+
span: self.lower_span(p.span),
2183+
}
21662184
}
21672185

21682186
fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> {
@@ -2469,6 +2487,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24692487
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
24702488
let principal = hir::PolyTraitRef {
24712489
bound_generic_params: &[],
2490+
binder_predicates: &[],
24722491
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
24732492
span: self.lower_span(span),
24742493
};

compiler/rustc_hir/src/hir.rs

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

3001+
/// Predicates on the `for<T>` binder itself, such as `for<T: Trait> ...`
3002+
pub binder_predicates: &'hir [WherePredicate<'hir>],
3003+
30013004
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
30023005
pub trait_ref: TraitRef<'hir>,
30033006

compiler/rustc_hir/src/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericB
10881088
pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>) {
10891089
walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
10901090
visitor.visit_trait_ref(&trait_ref.trait_ref);
1091+
walk_list!(visitor, visit_where_predicate, trait_ref.binder_predicates);
10911092
}
10921093

10931094
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 unbound = None;
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
if unbound.is_none() {
@@ -244,8 +244,16 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
244244
hir::TraitBoundModifier::Maybe => continue,
245245
};
246246

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

250258
let _ = self.instantiate_poly_trait_ref(
251259
&poly_trait_ref.trait_ref,

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
3434
let mut potential_assoc_types = Vec::new();
3535
let dummy_self = self.tcx().types.trait_object_dummy_self;
3636
for trait_bound in hir_trait_bounds.iter().rev() {
37+
assert!(
38+
trait_bound.binder_predicates.is_empty(),
39+
"FIXME(non_lifetime_binders): object types should not have binders"
40+
);
3741
if let GenericArgCountResult {
3842
correct:
3943
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
@@ -46,7 +50,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4650
dummy_self,
4751
&mut bounds,
4852
false,
49-
// TODO: dyn traits should have no binder preds
5053
ty::List::empty(),
5154
// FIXME: This should be `true`, but we don't really handle
5255
// 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
@@ -683,6 +683,16 @@ impl<'tcx> ItemCtxt<'tcx> {
683683
}
684684
};
685685

686+
let mut binder_predicates = FxIndexSet::default();
687+
self.astconv().lower_where_predicates(
688+
predicate.bound_generic_params,
689+
predicate.binder_predicates,
690+
&mut binder_predicates,
691+
);
692+
let binder_predicates = self
693+
.tcx
694+
.mk_clauses_from_iter(binder_predicates.into_iter().map(|(clause, _)| clause));
695+
686696
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
687697
// want to only consider predicates with `Self: ...`, but we don't want
688698
// `OnlySelfBounds(true)` since we want to collect the nested associated
@@ -704,8 +714,7 @@ impl<'tcx> ItemCtxt<'tcx> {
704714
}),
705715
&mut bounds,
706716
bound_vars,
707-
// TODO: convert `where_bound_predicate` above accordingly
708-
ty::List::empty(),
717+
binder_predicates,
709718
only_self_bounds,
710719
);
711720
}

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+1
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
395395
self.with(scope, |this| {
396396
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
397397
this.visit_trait_ref(&trait_ref.trait_ref);
398+
walk_list!(this, visit_where_predicate, trait_ref.binder_predicates);
398399
});
399400
}
400401
}

compiler/rustc_hir_analysis/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ pub fn hir_trait_to_predicates<'tcx>(
283283
self_ty,
284284
&mut bounds,
285285
true,
286-
// TODO: This is probably wrong!
286+
// FIXME(non_lifetime_binders): This is probably not right.
287287
ty::List::empty(),
288288
OnlySelfBounds(false),
289289
);

compiler/rustc_middle/src/ty/mod.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -809,18 +809,28 @@ impl<'tcx> Clause<'tcx> {
809809
let pred_bound_vars = bound_pred.bound_vars();
810810
let trait_bound_vars = trait_ref.bound_vars();
811811
// 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
812-
let shifted_pred =
813-
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
812+
let (shifted_pred, shifted_bound_clauses) = tcx.shift_bound_var_indices(
813+
trait_bound_vars.len(),
814+
(bound_pred.skip_binder(), bound_pred.skip_binder_predicates()),
815+
);
814816
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
815817
let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
816818
// 3) ['x] + ['b] -> ['x, 'b]
817819
let bound_vars =
818820
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
819821

822+
let binder_predicates = tcx.mk_clauses_from_iter(
823+
trait_ref.skip_binder_predicates().into_iter().chain(shifted_bound_clauses),
824+
);
825+
820826
// FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
821827
tcx.reuse_or_mk_predicate(
822828
self.as_predicate(),
823-
ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
829+
ty::Binder::bind_with_vars_and_predicates(
830+
PredicateKind::Clause(new),
831+
bound_vars,
832+
binder_predicates,
833+
),
824834
)
825835
.expect_clause()
826836
}

0 commit comments

Comments
 (0)