Skip to content

Commit aa6737a

Browse files
More non-lifetime binder stuff
1 parent 24c6468 commit aa6737a

File tree

10 files changed

+176
-105
lines changed

10 files changed

+176
-105
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15771577
bounds,
15781578
span,
15791579
bound_generic_params: &[],
1580+
binder_predicates: &[],
15801581
origin,
15811582
}))
15821583
}
@@ -1605,6 +1606,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
16051606
hir_id: self.next_id(),
16061607
bound_generic_params: self
16071608
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
1609+
binder_predicates: self.arena.alloc_from_iter(
1610+
bound_generic_params.iter().filter_map(|param| {
1611+
self.lower_generic_bound_predicate(
1612+
param.ident,
1613+
param.id,
1614+
&param.kind,
1615+
&param.bounds,
1616+
param.colon_span,
1617+
*span,
1618+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1619+
PredicateOrigin::GenericParam,
1620+
)
1621+
}),
1622+
),
16081623
bounded_ty: self
16091624
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
16101625
bounds: self.lower_param_bounds(

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,9 +756,11 @@ pub struct WhereBoundPredicate<'hir> {
756756
pub origin: PredicateOrigin,
757757
/// Any generics from a `for` binding.
758758
pub bound_generic_params: &'hir [GenericParam<'hir>],
759+
/// Predicates on the `for<T>` binder itself, such as `for<T: Trait> ...`
760+
pub binder_predicates: &'hir [WherePredicate<'hir>],
759761
/// The type being bounded.
760762
pub bounded_ty: &'hir Ty<'hir>,
761-
/// Trait and lifetime bounds (e.g., `Clone + Send + 'static`).
763+
/// Trait and lifetime bounds for `bounded_ty` (e.g., `Clone + Send + 'static`).
762764
pub bounds: GenericBounds<'hir>,
763765
}
764766

compiler/rustc_hir/src/intravisit.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,11 +904,13 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
904904
bound_generic_params,
905905
origin: _,
906906
span: _,
907+
binder_predicates,
907908
}) => {
908909
visitor.visit_id(hir_id);
909910
visitor.visit_ty(bounded_ty);
910911
walk_list!(visitor, visit_param_bound, bounds);
911912
walk_list!(visitor, visit_generic_param, bound_generic_params);
913+
walk_list!(visitor, visit_where_predicate, binder_predicates);
912914
}
913915
WherePredicate::RegionPredicate(WhereRegionPredicate {
914916
ref lifetime,

compiler/rustc_hir_analysis/src/astconv/bounds.rs

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use rustc_data_structures::fx::FxHashMap;
1+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
22
use rustc_errors::struct_span_err;
33
use rustc_hir as hir;
44
use rustc_hir::def::{DefKind, Res};
55
use rustc_hir::def_id::{DefId, LocalDefId};
6-
use rustc_middle::ty::{self as ty, Ty};
6+
use rustc_middle::ty::{self as ty, ToPredicate, Ty};
77
use rustc_span::symbol::Ident;
88
use rustc_span::{ErrorGuaranteed, Span};
99
use rustc_trait_selection::traits;
@@ -16,6 +16,132 @@ use crate::bounds::Bounds;
1616
use crate::errors;
1717

1818
impl<'tcx> dyn AstConv<'tcx> + '_ {
19+
pub(crate) fn lower_where_predicates(
20+
&self,
21+
params: &'tcx [hir::GenericParam<'tcx>],
22+
hir_predicates: &'tcx [hir::WherePredicate<'tcx>],
23+
predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>,
24+
) {
25+
// Collect the predicates that were written inline by the user on each
26+
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
27+
// for each const parameter.
28+
for param in params {
29+
match param.kind {
30+
hir::GenericParamKind::Lifetime { .. } => (),
31+
hir::GenericParamKind::Type { .. } => {
32+
let param_ty =
33+
ty::fold::shift_vars(self.tcx(), self.hir_id_to_bound_ty(param.hir_id), 1);
34+
let mut bounds = Bounds::default();
35+
// Params are implicitly sized unless a `?Sized` bound is found
36+
self.add_implicitly_sized(
37+
&mut bounds,
38+
param_ty,
39+
&[],
40+
Some((param.def_id, hir_predicates)),
41+
param.span,
42+
);
43+
trace!(?bounds);
44+
predicates.extend(bounds.clauses());
45+
trace!(?predicates);
46+
}
47+
hir::GenericParamKind::Const { .. } => {
48+
let ct_ty = self
49+
.tcx()
50+
.type_of(param.def_id.to_def_id())
51+
.no_bound_vars()
52+
.expect("const parameters cannot be generic");
53+
let ct = ty::fold::shift_vars(
54+
self.tcx(),
55+
self.hir_id_to_bound_const(param.hir_id, ct_ty),
56+
1,
57+
);
58+
predicates.insert((
59+
ty::Binder::bind_with_vars(
60+
ty::ClauseKind::ConstArgHasType(ct, ct_ty),
61+
ty::List::empty(),
62+
)
63+
.to_predicate(self.tcx()),
64+
param.span,
65+
));
66+
}
67+
}
68+
}
69+
70+
// Add in the bounds that appear in the where-clause.
71+
for predicate in hir_predicates {
72+
match predicate {
73+
hir::WherePredicate::BoundPredicate(bound_pred) => {
74+
let ty = self.ast_ty_to_ty(bound_pred.bounded_ty);
75+
let bound_vars = self.tcx().late_bound_vars(bound_pred.hir_id);
76+
77+
let mut binder_predicates = FxIndexSet::default();
78+
self.lower_where_predicates(
79+
bound_pred.bound_generic_params,
80+
bound_pred.binder_predicates,
81+
&mut binder_predicates,
82+
);
83+
let binder_predicates = self.tcx().mk_clauses_from_iter(
84+
binder_predicates.into_iter().map(|(clause, _)| clause),
85+
);
86+
if !binder_predicates.is_empty() {
87+
println!("binder_predicates = {binder_predicates:#?}");
88+
}
89+
90+
// Keep the type around in a dummy predicate, in case of no bounds.
91+
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
92+
// is still checked for WF.
93+
if bound_pred.bounds.is_empty() {
94+
if let ty::Param(_) = ty.kind() {
95+
// This is a `where T:`, which can be in the HIR from the
96+
// transformation that moves `?Sized` to `T`'s declaration.
97+
// We can skip the predicate because type parameters are
98+
// trivially WF, but also we *should*, to avoid exposing
99+
// users who never wrote `where Type:,` themselves, to
100+
// compiler/tooling bugs from not handling WF predicates.
101+
} else {
102+
let span = bound_pred.bounded_ty.span;
103+
let predicate = ty::Binder::bind_with_vars(
104+
ty::ClauseKind::WellFormed(ty.into()),
105+
bound_vars,
106+
);
107+
predicates.insert((predicate.to_predicate(self.tcx()), span));
108+
}
109+
}
110+
111+
let mut bounds = Bounds::default();
112+
self.add_bounds(
113+
ty,
114+
bound_pred.bounds.iter(),
115+
&mut bounds,
116+
bound_vars,
117+
binder_predicates,
118+
OnlySelfBounds(false),
119+
);
120+
predicates.extend(bounds.clauses());
121+
}
122+
123+
hir::WherePredicate::RegionPredicate(region_pred) => {
124+
let r1 = self.ast_region_to_region(&region_pred.lifetime, None);
125+
predicates.extend(region_pred.bounds.iter().map(|bound| {
126+
let (r2, span) = match bound {
127+
hir::GenericBound::Outlives(lt) => {
128+
(self.ast_region_to_region(lt, None), lt.ident.span)
129+
}
130+
_ => bug!(),
131+
};
132+
let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
133+
.to_predicate(self.tcx());
134+
(pred, span)
135+
}))
136+
}
137+
138+
hir::WherePredicate::EqPredicate(..) => {
139+
// FIXME(#20041)
140+
}
141+
}
142+
}
143+
}
144+
19145
/// Sets `implicitly_sized` to true on `Bounds` if necessary
20146
pub(crate) fn add_implicitly_sized(
21147
&self,
@@ -32,7 +158,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
32158
let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| {
33159
for ab in ast_bounds {
34160
if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
35-
unbounds.push(ptr)
161+
unbounds.push(ptr);
36162
}
37163
}
38164
};
@@ -106,6 +232,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
106232
ast_bounds: I,
107233
bounds: &mut Bounds<'tcx>,
108234
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
235+
binder_predicates: &'tcx ty::List<ty::Clause<'tcx>>,
109236
only_self_bounds: OnlySelfBounds,
110237
) {
111238
for ast_bound in ast_bounds {
@@ -123,6 +250,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
123250
}
124251
hir::TraitBoundModifier::Maybe => continue,
125252
};
253+
254+
// TODO: Add in the binder preds from the poly trait ref.
255+
let binder_predicates = binder_predicates;
256+
126257
let _ = self.instantiate_poly_trait_ref(
127258
&poly_trait_ref.trait_ref,
128259
poly_trait_ref.span,
@@ -131,6 +262,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
131262
param_ty,
132263
bounds,
133264
false,
265+
binder_predicates,
134266
only_self_bounds,
135267
);
136268
}
@@ -199,6 +331,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
199331
}),
200332
&mut bounds,
201333
ty::List::empty(),
334+
ty::List::empty(),
202335
only_self_bounds,
203336
);
204337
debug!(?bounds);
@@ -503,6 +636,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
503636
ast_bounds.iter(),
504637
bounds,
505638
projection_ty.bound_vars(),
639+
// TODO: This is wrong, should take preds from binder
640+
ty::List::empty(),
506641
only_self_bounds,
507642
);
508643
}

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
707707
self_ty: Ty<'tcx>,
708708
bounds: &mut Bounds<'tcx>,
709709
speculative: bool,
710+
_binder_predicates: &'tcx ty::List<ty::Clause<'tcx>>,
710711
only_self_bounds: OnlySelfBounds,
711712
) -> GenericArgCountResult {
712713
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4545
dummy_self,
4646
&mut bounds,
4747
false,
48+
// TODO: dyn traits should have no binder preds
49+
ty::List::empty(),
4850
// FIXME: This should be `true`, but we don't really handle
4951
// associated type bounds or type aliases in objects in a way
5052
// that makes this meaningful, I think.

compiler/rustc_hir_analysis/src/bounds.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ impl<'tcx> Bounds<'tcx> {
9898
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
9999
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
100100
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
101-
self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
101+
self.clauses.insert(
102+
0,
103+
(ty::Binder::bind_with_vars(trait_ref, ty::List::empty()).to_predicate(tcx), span),
104+
);
102105
}
103106

104107
pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {

0 commit comments

Comments
 (0)