X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_resolve%2Fsrc%2Flate.rs;h=533302a758f17f763ae3f78d7bd3554cc41c3001;hb=6e1b0105c60cfca15930a6fdf8a3b07db528c749;hp=73d6566e3cd977655f2c1b5c07476aefe8aef1c3;hpb=20976bae5c426c738262db376eadbd8859aafc08;p=rust.git diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 73d6566e3cd..533302a758f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,6 +12,10 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; +use diagnostics::{ + original_label, original_lifetime, original_lifetime_param, shadower_label, shadower_lifetime, +}; + use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; @@ -172,6 +176,23 @@ pub(crate) fn contains_params(&self) -> bool { AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, } } + + /// This rib forbids referring to labels defined in upwards ribs. + fn is_label_barrier(self) -> bool { + match self { + NormalRibKind | MacroDefinition(..) => false, + + AssocItemRibKind + | ClosureOrAsyncRibKind + | FnItemRibKind + | ItemRibKind(..) + | ConstantItemRibKind(..) + | ModuleRibKind(..) + | ForwardGenericParamBanRibKind + | ConstParamTyRibKind + | InlineAsmSymRibKind => true, + } + } } /// A single local scope. @@ -732,7 +753,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { // Create a value rib for the function. self.with_rib(ValueNS, rib_kind, |this| { // Create a label rib for the function. - this.with_label_rib(rib_kind, |this| { + this.with_label_rib(FnItemRibKind, |this| { let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id()); if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind { @@ -1585,22 +1606,8 @@ fn is_label_valid_from_rib(&self, rib_index: usize) -> bool { let ribs = &self.label_ribs[rib_index + 1..]; for rib in ribs { - match rib.kind { - NormalRibKind | MacroDefinition(..) => { - // Nothing to do. Continue. - } - - AssocItemRibKind - | ClosureOrAsyncRibKind - | FnItemRibKind - | ItemRibKind(..) - | ConstantItemRibKind(..) - | ModuleRibKind(..) - | ForwardGenericParamBanRibKind - | ConstParamTyRibKind - | InlineAsmSymRibKind => { - return false; - } + if rib.kind.is_label_barrier() { + return false; } } @@ -1895,6 +1902,7 @@ fn with_generic_param_rib<'c, F>( let mut function_value_rib = Rib::new(kind); let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind); let mut seen_bindings = FxHashMap::default(); + let mut seen_lifetimes = FxHashMap::default(); // We also can't shadow bindings from the parent item if let AssocItemRibKind = kind { @@ -1910,20 +1918,52 @@ fn with_generic_param_rib<'c, F>( add_bindings_for_ns(TypeNS); } + // Forbid shadowing lifetime bindings + for rib in self.lifetime_ribs.iter().rev() { + seen_lifetimes.extend( + rib.bindings.iter().map(|(ident, _)| (*ident, original_lifetime(ident.span))), + ); + if let LifetimeRibKind::Item = rib.kind { + break; + } + } + for rib in self.label_ribs.iter().rev() { + if rib.kind.is_label_barrier() { + break; + } + seen_lifetimes + .extend(rib.bindings.iter().map(|(ident, _)| (*ident, original_label(ident.span)))); + } + for param in params { let ident = param.ident.normalize_to_macros_2_0(); debug!("with_generic_param_rib: {}", param.id); - match seen_bindings.entry(ident) { - Entry::Occupied(entry) => { - let span = *entry.get(); - let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); - if !matches!(param.kind, GenericParamKind::Lifetime) { - self.report_error(param.ident.span, err); + if let GenericParamKind::Lifetime = param.kind { + match seen_lifetimes.entry(ident) { + Entry::Occupied(entry) => { + let original = *entry.get(); + diagnostics::signal_shadowing_problem( + self.r.session, + ident.name, + original, + shadower_lifetime(param.ident.span), + ) + } + Entry::Vacant(entry) => { + entry.insert(original_lifetime_param(param.ident.span)); } } - Entry::Vacant(entry) => { - entry.insert(param.ident.span); + } else { + match seen_bindings.entry(ident) { + Entry::Occupied(entry) => { + let span = *entry.get(); + let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); + self.report_error(param.ident.span, err); + } + Entry::Vacant(entry) => { + entry.insert(param.ident.span); + } } } @@ -3114,8 +3154,35 @@ fn with_resolved_label(&mut self, label: Option