Skip to content

Commit 307dd93

Browse files
committed
Auto merge of #101454 - cjgillot:concat-binders, r=estebank
Do not overwrite lifetime binders for another HirId. This PR makes higher-ranked bounds in where clauses a bit more principled. We used to conflate `for<'a> T: Trait` with `(for<'a> T): Trait`. This PR separates both binders. This caused issued with fn types, which have their own binder, causing us to overwrite the predicates's binders with `fn`'s binders, ICEing. Fixes #98594
2 parents 09ae784 + dd69ce3 commit 307dd93

File tree

9 files changed

+118
-31
lines changed

9 files changed

+118
-31
lines changed

compiler/rustc_ast_lowering/src/item.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14781478
let bounded_ty =
14791479
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
14801480
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1481+
hir_id: self.next_id(),
14811482
bounded_ty: self.arena.alloc(bounded_ty),
14821483
bounds,
14831484
span,
@@ -1508,6 +1509,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15081509
ref bounds,
15091510
span,
15101511
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
1512+
hir_id: self.next_id(),
15111513
bound_generic_params: self.lower_generic_params(bound_generic_params),
15121514
bounded_ty: self
15131515
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),

compiler/rustc_hir/src/hir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ pub enum PredicateOrigin {
731731
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
732732
#[derive(Debug, HashStable_Generic)]
733733
pub struct WhereBoundPredicate<'hir> {
734+
pub hir_id: HirId,
734735
pub span: Span,
735736
/// Origin of the predicate.
736737
pub origin: PredicateOrigin,

compiler/rustc_hir/src/intravisit.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -847,20 +847,28 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
847847
) {
848848
match *predicate {
849849
WherePredicate::BoundPredicate(WhereBoundPredicate {
850+
hir_id,
850851
ref bounded_ty,
851852
bounds,
852853
bound_generic_params,
853-
..
854+
origin: _,
855+
span: _,
854856
}) => {
857+
visitor.visit_id(hir_id);
855858
visitor.visit_ty(bounded_ty);
856859
walk_list!(visitor, visit_param_bound, bounds);
857860
walk_list!(visitor, visit_generic_param, bound_generic_params);
858861
}
859-
WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
862+
WherePredicate::RegionPredicate(WhereRegionPredicate {
863+
ref lifetime,
864+
bounds,
865+
span: _,
866+
in_where_clause: _,
867+
}) => {
860868
visitor.visit_lifetime(lifetime);
861869
walk_list!(visitor, visit_param_bound, bounds);
862870
}
863-
WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
871+
WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => {
864872
visitor.visit_ty(lhs_ty);
865873
visitor.visit_ty(rhs_ty);
866874
}

compiler/rustc_hir_analysis/src/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ impl<'tcx> ItemCtxt<'tcx> {
697697
} else {
698698
None
699699
};
700-
let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id);
700+
let bvars = self.tcx.late_bound_vars(bp.hir_id);
701701

702702
bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
703703
|(_, b, _)| match assoc_name {
@@ -2295,7 +2295,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
22952295
match predicate {
22962296
hir::WherePredicate::BoundPredicate(bound_pred) => {
22972297
let ty = icx.to_ty(bound_pred.bounded_ty);
2298-
let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id);
2298+
let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id);
22992299

23002300
// Keep the type around in a dummy predicate, in case of no bounds.
23012301
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`

compiler/rustc_resolve/src/late/lifetimes.rs

+35-20
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
326326
}
327327

328328
debug!(?rl.defs);
329+
debug!(?rl.late_bound_vars);
329330
rl
330331
}
331332

@@ -507,7 +508,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
507508
})
508509
.unzip();
509510

510-
self.map.late_bound_vars.insert(e.hir_id, binders);
511+
self.record_late_bound_vars(e.hir_id, binders);
511512
let scope = Scope::Binder {
512513
hir_id: e.hir_id,
513514
lifetimes,
@@ -531,7 +532,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
531532
match &item.kind {
532533
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
533534
if let Some(of_trait) = of_trait {
534-
self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default());
535+
self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
535536
}
536537
}
537538
_ => {}
@@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
583584
resolved_lifetimes.late_bound_vars.iter()
584585
{
585586
late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
586-
self.map.late_bound_vars.insert(
587+
self.record_late_bound_vars(
587588
hir::HirId { owner, local_id },
588589
late_bound_vars.clone(),
589590
);
@@ -614,7 +615,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
614615
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
615616
})
616617
.collect();
617-
self.map.late_bound_vars.insert(item.hir_id(), vec![]);
618+
self.record_late_bound_vars(item.hir_id(), vec![]);
618619
let scope = Scope::Binder {
619620
hir_id: item.hir_id(),
620621
lifetimes,
@@ -663,7 +664,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
663664
(pair, r)
664665
})
665666
.unzip();
666-
self.map.late_bound_vars.insert(ty.hir_id, binders);
667+
self.record_late_bound_vars(ty.hir_id, binders);
667668
let scope = Scope::Binder {
668669
hir_id: ty.hir_id,
669670
lifetimes,
@@ -817,7 +818,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
817818
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
818819
}
819820
}
820-
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
821+
self.record_late_bound_vars(ty.hir_id, vec![]);
821822

822823
let scope = Scope::Binder {
823824
hir_id: ty.hir_id,
@@ -861,7 +862,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
861862
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
862863
})
863864
.collect();
864-
self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
865+
self.record_late_bound_vars(trait_item.hir_id(), vec![]);
865866
let scope = Scope::Binder {
866867
hir_id: trait_item.hir_id(),
867868
lifetimes,
@@ -909,9 +910,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
909910
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
910911
})
911912
.collect();
912-
self.map.late_bound_vars.insert(ty.hir_id, vec![]);
913+
self.record_late_bound_vars(impl_item.hir_id(), vec![]);
913914
let scope = Scope::Binder {
914-
hir_id: ty.hir_id,
915+
hir_id: impl_item.hir_id(),
915916
lifetimes,
916917
s: self.scope,
917918
scope_type: BinderScopeType::Normal,
@@ -995,33 +996,38 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
995996
for predicate in generics.predicates {
996997
match predicate {
997998
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
999+
hir_id,
9981000
ref bounded_ty,
9991001
bounds,
10001002
ref bound_generic_params,
10011003
origin,
10021004
..
10031005
}) => {
1004-
let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
1006+
let lifetimes: FxIndexMap<LocalDefId, Region> =
10051007
bound_generic_params
10061008
.iter()
10071009
.filter(|param| {
10081010
matches!(param.kind, GenericParamKind::Lifetime { .. })
10091011
})
10101012
.enumerate()
10111013
.map(|(late_bound_idx, param)| {
1012-
let pair =
1013-
Region::late(late_bound_idx as u32, this.tcx.hir(), param);
1014-
let r = late_region_as_bound_region(this.tcx, &pair.1);
1015-
(pair, r)
1014+
Region::late(late_bound_idx as u32, this.tcx.hir(), param)
1015+
})
1016+
.collect();
1017+
let binders: Vec<_> =
1018+
lifetimes
1019+
.iter()
1020+
.map(|(_, region)| {
1021+
late_region_as_bound_region(this.tcx, region)
10161022
})
1017-
.unzip();
1018-
this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
1023+
.collect();
1024+
this.record_late_bound_vars(hir_id, binders.clone());
10191025
// Even if there are no lifetimes defined here, we still wrap it in a binder
10201026
// scope. If there happens to be a nested poly trait ref (an error), that
10211027
// will be `Concatenating` anyways, so we don't have to worry about the depth
10221028
// being wrong.
10231029
let scope = Scope::Binder {
1024-
hir_id: bounded_ty.hir_id,
1030+
hir_id,
10251031
lifetimes,
10261032
s: this.scope,
10271033
scope_type: BinderScopeType::Normal,
@@ -1089,7 +1095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
10891095
// imagine there's a better way to go about this.
10901096
let (binders, scope_type) = self.poly_trait_ref_binder_info();
10911097

1092-
self.map.late_bound_vars.insert(*hir_id, binders);
1098+
self.record_late_bound_vars(*hir_id, binders);
10931099
let scope = Scope::Binder {
10941100
hir_id: *hir_id,
10951101
lifetimes: FxIndexMap::default(),
@@ -1127,7 +1133,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
11271133
binders.extend(binders_iter);
11281134

11291135
debug!(?binders);
1130-
self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders);
1136+
self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders);
11311137

11321138
// Always introduce a scope here, even if this is in a where clause and
11331139
// we introduced the binders around the bounded Ty. In that case, we
@@ -1211,6 +1217,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
12111217
}
12121218
}
12131219

1220+
fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec<ty::BoundVariableKind>) {
1221+
if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
1222+
bug!(
1223+
"overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
1224+
self.map.late_bound_vars[&hir_id]
1225+
)
1226+
}
1227+
}
1228+
12141229
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
12151230
///
12161231
/// Handles visiting fns and methods. These are a bit complicated because we must distinguish
@@ -1268,7 +1283,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
12681283
late_region_as_bound_region(self.tcx, &pair.1)
12691284
})
12701285
.collect();
1271-
self.map.late_bound_vars.insert(hir_id, binders);
1286+
self.record_late_bound_vars(hir_id, binders);
12721287
let scope = Scope::Binder {
12731288
hir_id,
12741289
lifetimes,

src/test/ui/stats/hir-stats.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,11 @@ hir-stats - Expr 32 ( 0.3%) 1
140140
hir-stats FnDecl 120 ( 1.2%) 3 40
141141
hir-stats Attribute 128 ( 1.3%) 4 32
142142
hir-stats GenericArgs 144 ( 1.5%) 3 48
143-
hir-stats Variant 160 ( 1.7%) 2 80
144-
hir-stats WherePredicate 168 ( 1.7%) 3 56
145-
hir-stats - BoundPredicate 168 ( 1.7%) 3
143+
hir-stats Variant 160 ( 1.6%) 2 80
146144
hir-stats GenericBound 192 ( 2.0%) 4 48
147145
hir-stats - Trait 192 ( 2.0%) 4
146+
hir-stats WherePredicate 192 ( 2.0%) 3 64
147+
hir-stats - BoundPredicate 192 ( 2.0%) 3
148148
hir-stats Block 288 ( 3.0%) 6 48
149149
hir-stats Pat 360 ( 3.7%) 5 72
150150
hir-stats - Wild 72 ( 0.7%) 1
@@ -169,10 +169,10 @@ hir-stats - Enum 80 ( 0.8%) 1
169169
hir-stats - ExternCrate 80 ( 0.8%) 1
170170
hir-stats - ForeignMod 80 ( 0.8%) 1
171171
hir-stats - Impl 80 ( 0.8%) 1
172-
hir-stats - Fn 160 ( 1.7%) 2
172+
hir-stats - Fn 160 ( 1.6%) 2
173173
hir-stats - Use 400 ( 4.1%) 5
174-
hir-stats Path 1_536 (15.9%) 32 48
174+
hir-stats Path 1_536 (15.8%) 32 48
175175
hir-stats PathSegment 2_240 (23.1%) 40 56
176176
hir-stats ----------------------------------------------------------------
177-
hir-stats Total 9_680
177+
hir-stats Total 9_704
178178
hir-stats
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied
2+
--> $DIR/higher-ranked-fn-type.rs:20:5
3+
|
4+
LL | called()
5+
| ^^^^^^ the trait `for<'b> Foo` is not implemented for `for<'b> fn(&'b ())`
6+
|
7+
note: required by a bound in `called`
8+
--> $DIR/higher-ranked-fn-type.rs:12:25
9+
|
10+
LL | fn called()
11+
| ------ required by a bound in this
12+
LL | where
13+
LL | for<'b> fn(&'b ()): Foo,
14+
| ^^^ required by this bound in `called`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// revisions: quiet verbose
2+
// [verbose]compile-flags: -Zverbose
3+
4+
#![allow(unused_parens)]
5+
6+
trait Foo {
7+
type Assoc;
8+
}
9+
10+
fn called()
11+
where
12+
for<'b> fn(&'b ()): Foo,
13+
{
14+
}
15+
16+
fn caller()
17+
where
18+
(for<'a> fn(&'a ())): Foo,
19+
{
20+
called()
21+
//[quiet]~^ ERROR the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied
22+
//[verbose]~^^ ERROR the trait bound `for<'b> fn(&ReLateBound(
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the trait bound `for<'b> fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied
2+
--> $DIR/higher-ranked-fn-type.rs:20:5
3+
|
4+
LL | called()
5+
| ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())`
6+
|
7+
note: required by a bound in `called`
8+
--> $DIR/higher-ranked-fn-type.rs:12:25
9+
|
10+
LL | fn called()
11+
| ------ required by a bound in this
12+
LL | where
13+
LL | for<'b> fn(&'b ()): Foo,
14+
| ^^^ required by this bound in `called`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)