From 337a73da6e819a9c6374e9c4ce07565cde8f91e2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 5 Sep 2022 17:21:19 +0200 Subject: [PATCH] Do not overwrite binders for another HirId. --- compiler/rustc_ast_lowering/src/item.rs | 2 + compiler/rustc_hir/src/hir.rs | 1 + compiler/rustc_hir/src/intravisit.rs | 14 ++++- compiler/rustc_hir_analysis/src/collect.rs | 4 +- compiler/rustc_resolve/src/late/lifetimes.rs | 55 ++++++++++++------- .../higher-ranked-fn-type.quiet.stderr | 18 ++++++ .../ui/where-clauses/higher-ranked-fn-type.rs | 25 +++++++++ .../higher-ranked-fn-type.verbose.stderr | 18 ++++++ 8 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.rs create mode 100644 src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d9b18d68e537f..9a46444d82398 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1478,6 +1478,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let bounded_ty = self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path)); Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id: self.next_id(), bounded_ty: self.arena.alloc(bounded_ty), bounds, span, @@ -1508,6 +1509,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ref bounds, span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id: self.next_id(), bound_generic_params: self.lower_generic_params(bound_generic_params), bounded_ty: self .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c1948052e3c51..cde8ec7370124 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -731,6 +731,7 @@ pub enum PredicateOrigin { /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). #[derive(Debug, HashStable_Generic)] pub struct WhereBoundPredicate<'hir> { + pub hir_id: HirId, pub span: Span, /// Origin of the predicate. pub origin: PredicateOrigin, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8f5f314ecae1d..8777a54ba09b4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -847,20 +847,28 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( ) { match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate { + hir_id, ref bounded_ty, bounds, bound_generic_params, - .. + origin: _, + span: _, }) => { + visitor.visit_id(hir_id); visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } - WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => { + WherePredicate::RegionPredicate(WhereRegionPredicate { + ref lifetime, + bounds, + span: _, + in_where_clause: _, + }) => { visitor.visit_lifetime(lifetime); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => { + WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => { visitor.visit_ty(lhs_ty); visitor.visit_ty(rhs_ty); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e7deae2b557cd..97cdfff74d7eb 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -697,7 +697,7 @@ impl<'tcx> ItemCtxt<'tcx> { } else { None }; - let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id); + let bvars = self.tcx.late_bound_vars(bp.hir_id); bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter( |(_, b, _)| match assoc_name { @@ -2295,7 +2295,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { let ty = icx.to_ty(bound_pred.bounded_ty); - let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id); + let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 9fb1af20ac976..0c29ff364dcdf 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -326,6 +326,7 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime } debug!(?rl.defs); + debug!(?rl.late_bound_vars); rl } @@ -507,7 +508,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .unzip(); - self.map.late_bound_vars.insert(e.hir_id, binders); + self.record_late_bound_vars(e.hir_id, binders); let scope = Scope::Binder { hir_id: e.hir_id, lifetimes, @@ -531,7 +532,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match &item.kind { hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { if let Some(of_trait) = of_trait { - self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default()); + self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default()); } } _ => {} @@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { resolved_lifetimes.late_bound_vars.iter() { late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| { - self.map.late_bound_vars.insert( + self.record_late_bound_vars( hir::HirId { owner, local_id }, late_bound_vars.clone(), ); @@ -614,7 +615,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(item.hir_id(), vec![]); + self.record_late_bound_vars(item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: item.hir_id(), lifetimes, @@ -663,7 +664,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { (pair, r) }) .unzip(); - self.map.late_bound_vars.insert(ty.hir_id, binders); + self.record_late_bound_vars(ty.hir_id, binders); let scope = Scope::Binder { hir_id: ty.hir_id, lifetimes, @@ -817,7 +818,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {} } } - self.map.late_bound_vars.insert(ty.hir_id, vec![]); + self.record_late_bound_vars(ty.hir_id, vec![]); let scope = Scope::Binder { hir_id: ty.hir_id, @@ -861,7 +862,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]); + self.record_late_bound_vars(trait_item.hir_id(), vec![]); let scope = Scope::Binder { hir_id: trait_item.hir_id(), lifetimes, @@ -909,9 +910,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None, }) .collect(); - self.map.late_bound_vars.insert(ty.hir_id, vec![]); + self.record_late_bound_vars(impl_item.hir_id(), vec![]); let scope = Scope::Binder { - hir_id: ty.hir_id, + hir_id: impl_item.hir_id(), lifetimes, s: self.scope, scope_type: BinderScopeType::Normal, @@ -995,13 +996,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { for predicate in generics.predicates { match predicate { &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + hir_id, ref bounded_ty, bounds, ref bound_generic_params, origin, .. }) => { - let (lifetimes, binders): (FxIndexMap, Vec<_>) = + let lifetimes: FxIndexMap = bound_generic_params .iter() .filter(|param| { @@ -1009,19 +1011,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) .enumerate() .map(|(late_bound_idx, param)| { - let pair = - Region::late(late_bound_idx as u32, this.tcx.hir(), param); - let r = late_region_as_bound_region(this.tcx, &pair.1); - (pair, r) + Region::late(late_bound_idx as u32, this.tcx.hir(), param) + }) + .collect(); + let binders: Vec<_> = + lifetimes + .iter() + .map(|(_, region)| { + late_region_as_bound_region(this.tcx, region) }) - .unzip(); - this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone()); + .collect(); + this.record_late_bound_vars(hir_id, binders.clone()); // Even if there are no lifetimes defined here, we still wrap it in a binder // scope. If there happens to be a nested poly trait ref (an error), that // will be `Concatenating` anyways, so we don't have to worry about the depth // being wrong. let scope = Scope::Binder { - hir_id: bounded_ty.hir_id, + hir_id, lifetimes, s: this.scope, scope_type: BinderScopeType::Normal, @@ -1089,7 +1095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // imagine there's a better way to go about this. let (binders, scope_type) = self.poly_trait_ref_binder_info(); - self.map.late_bound_vars.insert(*hir_id, binders); + self.record_late_bound_vars(*hir_id, binders); let scope = Scope::Binder { hir_id: *hir_id, lifetimes: FxIndexMap::default(), @@ -1127,7 +1133,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { binders.extend(binders_iter); debug!(?binders); - self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, binders); + self.record_late_bound_vars(trait_ref.trait_ref.hir_ref_id, binders); // Always introduce a scope here, even if this is in a where clause and // we introduced the binders around the bounded Ty. In that case, we @@ -1211,6 +1217,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } + fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec) { + if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) { + bug!( + "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}", + self.map.late_bound_vars[&hir_id] + ) + } + } + /// Visits self by adding a scope and handling recursive walk over the contents with `walk`. /// /// Handles visiting fns and methods. These are a bit complicated because we must distinguish @@ -1268,7 +1283,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { late_region_as_bound_region(self.tcx, &pair.1) }) .collect(); - self.map.late_bound_vars.insert(hir_id, binders); + self.record_late_bound_vars(hir_id, binders); let scope = Scope::Binder { hir_id, lifetimes, diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr new file mode 100644 index 0000000000000..d9950a3d9b7cd --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ the trait `for<'b> Foo` is not implemented for `for<'b> fn(&'b ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.rs b/src/test/ui/where-clauses/higher-ranked-fn-type.rs new file mode 100644 index 0000000000000..0d8893e08d319 --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.rs @@ -0,0 +1,25 @@ +// revisions: quiet verbose +// [verbose]compile-flags: -Zverbose + +#![allow(unused_parens)] + +trait Foo { + type Assoc; +} + +fn called() +where + for<'b> fn(&'b ()): Foo, +{ +} + +fn caller() +where + (for<'a> fn(&'a ())): Foo, +{ + called() + //[quiet]~^ ERROR the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied + //[verbose]~^^ ERROR the trait bound `for<'b> fn(&ReLateBound( +} + +fn main() {} diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr new file mode 100644 index 0000000000000..24660ec3539e6 --- /dev/null +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -0,0 +1,18 @@ +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 + --> $DIR/higher-ranked-fn-type.rs:20:5 + | +LL | called() + | ^^^^^^ 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) }) ())` + | +note: required by a bound in `called` + --> $DIR/higher-ranked-fn-type.rs:12:25 + | +LL | fn called() + | ------ required by a bound in this +LL | where +LL | for<'b> fn(&'b ()): Foo, + | ^^^ required by this bound in `called` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.