diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs | 62 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/errors.rs | 18 |
2 files changed, 75 insertions, 5 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index b14e65183aa..65a9052a60a 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -24,6 +24,8 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use std::fmt; +use crate::errors; + trait RegionExt { fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); @@ -161,6 +163,15 @@ enum Scope<'a> { s: ScopeRef<'a>, }, + /// Disallows capturing non-lifetime binders from parent scopes. + /// + /// This is necessary for something like `for<T> [(); { /* references T */ }]:`, + /// since we don't do something more correct like replacing any captured + /// late-bound vars with early-bound params in the const's own generics. + AnonConstBoundary { + s: ScopeRef<'a>, + }, + Root { opt_parent_item: Option<LocalDefId>, }, @@ -211,6 +222,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("s", &"..") .finish(), Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), + Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(), Scope::Root { opt_parent_item } => { f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish() } @@ -312,7 +324,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { break (vec![], BinderScopeType::Normal); } - Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => { + Scope::Elision { s, .. } + | Scope::ObjectLifetimeDefault { s, .. } + | Scope::AnonConstBoundary { s } => { scope = s; } @@ -1029,6 +1043,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) { self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow); } + + fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + self.with(Scope::AnonConstBoundary { s: self.scope }, |this| { + intravisit::walk_anon_const(this, c); + }); + } } fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault { @@ -1275,7 +1295,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { + | Scope::TraitRefBoundary { s, .. } + | Scope::AnonConstBoundary { s } => { scope = s; } } @@ -1340,7 +1361,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { + | Scope::TraitRefBoundary { s, .. } + | Scope::AnonConstBoundary { s } => { scope = s; } } @@ -1359,6 +1381,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // search. let mut late_depth = 0; let mut scope = self.scope; + let mut crossed_anon_const = false; let result = loop { match *scope { Scope::Body { s, .. } => { @@ -1392,10 +1415,36 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | Scope::TraitRefBoundary { s, .. } => { scope = s; } + + Scope::AnonConstBoundary { s } => { + crossed_anon_const = true; + scope = s; + } } }; if let Some(def) = result { + if let ResolvedArg::LateBound(..) = def && crossed_anon_const { + let use_span = self.tcx.hir().span(hir_id); + let def_span = self.tcx.def_span(param_def_id); + match self.tcx.def_kind(param_def_id) { + DefKind::ConstParam => { + self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const { + use_span, + def_span, + }); + } + DefKind::TyParam => { + self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type { + use_span, + def_span, + }); + } + _ => unreachable!(), + } + return; + } + self.map.defs.insert(hir_id, def); return; } @@ -1474,7 +1523,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { | Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { + | Scope::TraitRefBoundary { s, .. } + | Scope::AnonConstBoundary { s } => { scope = s; } } @@ -1710,7 +1760,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l, - Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { + Scope::Supertrait { s, .. } + | Scope::TraitRefBoundary { s, .. } + | Scope::AnonConstBoundary { s } => { scope = s; } } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 203e0f85cad..3e069275775 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -381,3 +381,21 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> { pub span: Span, pub conventions: &'a str, } + +#[derive(Diagnostic)] +pub(crate) enum CannotCaptureLateBoundInAnonConst { + #[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)] + Type { + #[primary_span] + use_span: Span, + #[label] + def_span: Span, + }, + #[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)] + Const { + #[primary_span] + use_span: Span, + #[label] + def_span: Span, + }, +} |
