Skip to content

Commit 53cc20f

Browse files
More non-lifetime binder stuff
1 parent b1229c0 commit 53cc20f

File tree

10 files changed

+178
-99
lines changed

10 files changed

+178
-99
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
16001600
bounds,
16011601
span,
16021602
bound_generic_params: &[],
1603+
binder_predicates: &[],
16031604
origin,
16041605
}))
16051606
}
@@ -1628,6 +1629,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
16281629
hir_id: self.next_id(),
16291630
bound_generic_params: self
16301631
.lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
1632+
binder_predicates: self.arena.alloc_from_iter(
1633+
bound_generic_params.iter().filter_map(|param| {
1634+
self.lower_generic_bound_predicate(
1635+
param.ident,
1636+
param.id,
1637+
&param.kind,
1638+
&param.bounds,
1639+
param.colon_span,
1640+
*span,
1641+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1642+
PredicateOrigin::GenericParam,
1643+
)
1644+
}),
1645+
),
16311646
bounded_ty: self
16321647
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
16331648
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
@@ -779,9 +779,11 @@ pub struct WhereBoundPredicate<'hir> {
779779
pub origin: PredicateOrigin,
780780
/// Any generics from a `for` binding.
781781
pub bound_generic_params: &'hir [GenericParam<'hir>],
782+
/// Predicates on the `for<T>` binder itself, such as `for<T: Trait> ...`
783+
pub binder_predicates: &'hir [WherePredicate<'hir>],
782784
/// The type being bounded.
783785
pub bounded_ty: &'hir Ty<'hir>,
784-
/// Trait and lifetime bounds (e.g., `Clone + Send + 'static`).
786+
/// Trait and lifetime bounds for `bounded_ty` (e.g., `Clone + Send + 'static`).
785787
pub bounds: GenericBounds<'hir>,
786788
}
787789

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: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
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};
66
use rustc_lint_defs::Applicability;
7-
use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt};
7+
use rustc_middle::ty::{self as ty, ToPredicate, Ty, TypeVisitableExt};
88
use rustc_span::symbol::Ident;
99
use rustc_span::{ErrorGuaranteed, Span};
1010
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,
@@ -102,6 +228,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
102228
ast_bounds: I,
103229
bounds: &mut Bounds<'tcx>,
104230
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
231+
binder_predicates: &'tcx ty::List<ty::Clause<'tcx>>,
105232
only_self_bounds: OnlySelfBounds,
106233
) {
107234
for ast_bound in ast_bounds {
@@ -119,6 +246,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
119246
}
120247
hir::TraitBoundModifier::Maybe => continue,
121248
};
249+
250+
// TODO: Add in the binder preds from the poly trait ref.
251+
let binder_predicates = binder_predicates;
252+
122253
let _ = self.instantiate_poly_trait_ref(
123254
&poly_trait_ref.trait_ref,
124255
poly_trait_ref.span,
@@ -127,6 +258,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
127258
param_ty,
128259
bounds,
129260
false,
261+
binder_predicates,
130262
only_self_bounds,
131263
);
132264
}
@@ -208,6 +340,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
208340
}),
209341
&mut bounds,
210342
ty::List::empty(),
343+
ty::List::empty(),
211344
only_self_bounds,
212345
);
213346
debug!(?bounds);
@@ -577,6 +710,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
577710
ast_bounds.iter(),
578711
bounds,
579712
projection_ty.bound_vars(),
713+
// TODO: This is wrong, should take preds from binder
714+
ty::List::empty(),
580715
only_self_bounds,
581716
);
582717
}

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
687687
args: &GenericArgs<'_>,
688688
infer_args: bool,
689689
self_ty: Ty<'tcx>,
690+
_binder_predicates: &'tcx ty::List<ty::Clause<'tcx>>,
690691
only_self_bounds: OnlySelfBounds,
691692
) -> GenericArgCountResult {
692693
let (generic_args, arg_count) = self.create_args_for_ast_path(
@@ -774,6 +775,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
774775
self_ty: Ty<'tcx>,
775776
bounds: &mut Bounds<'tcx>,
776777
speculative: bool,
778+
binder_predicates: &'tcx ty::List<ty::Clause<'tcx>>,
777779
only_self_bounds: OnlySelfBounds,
778780
) -> GenericArgCountResult {
779781
let hir_id = trait_ref.hir_ref_id;
@@ -801,6 +803,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
801803
args,
802804
infer_args,
803805
self_ty,
806+
binder_predicates,
804807
only_self_bounds,
805808
)
806809
}
@@ -837,6 +840,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
837840
args,
838841
infer_args,
839842
self_ty,
843+
ty::List::empty(),
840844
only_self_bounds,
841845
);
842846
}

compiler/rustc_hir_analysis/src/astconv/object_safety.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
4646
dummy_self,
4747
&mut bounds,
4848
false,
49+
// TODO: dyn traits should have no binder preds
50+
ty::List::empty(),
4951
// FIXME: This should be `true`, but we don't really handle
5052
// associated type bounds or type aliases in objects in a way
5153
// 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
@@ -97,7 +97,10 @@ impl<'tcx> Bounds<'tcx> {
9797
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
9898
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
9999
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
100-
self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
100+
self.clauses.insert(
101+
0,
102+
(ty::Binder::bind_with_vars(trait_ref, ty::List::empty()).to_predicate(tcx), span),
103+
);
101104
}
102105

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

0 commit comments

Comments
 (0)