Do not report mixed label/lifetime shadowing.
This commit is contained in:
parent
85cbd0bc18
commit
257d8fce3e
2 changed files with 46 additions and 112 deletions
|
@ -12,10 +12,6 @@ use crate::{path_names_to_string, BindingError, Finalize, LexicalScopeBinding};
|
||||||
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
|
use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
|
||||||
use crate::{ResolutionError, Resolver, Segment, UseError};
|
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::ptr::P;
|
||||||
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
|
||||||
use rustc_ast::*;
|
use rustc_ast::*;
|
||||||
|
@ -1902,6 +1898,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
let mut function_value_rib = Rib::new(kind);
|
let mut function_value_rib = Rib::new(kind);
|
||||||
let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
|
let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
|
||||||
let mut seen_bindings = FxHashMap::default();
|
let mut seen_bindings = FxHashMap::default();
|
||||||
|
// Store all seen lifetimes names, and whether they were created in the currently processed
|
||||||
|
// parameter set.
|
||||||
let mut seen_lifetimes = FxHashMap::default();
|
let mut seen_lifetimes = FxHashMap::default();
|
||||||
|
|
||||||
// We also can't shadow bindings from the parent item
|
// We also can't shadow bindings from the parent item
|
||||||
|
@ -1920,20 +1918,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
|
|
||||||
// Forbid shadowing lifetime bindings
|
// Forbid shadowing lifetime bindings
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
for rib in self.lifetime_ribs.iter().rev() {
|
||||||
seen_lifetimes.extend(
|
seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| (*ident, false)));
|
||||||
rib.bindings.iter().map(|(ident, _)| (*ident, original_lifetime(ident.span))),
|
|
||||||
);
|
|
||||||
if let LifetimeRibKind::Item = rib.kind {
|
if let LifetimeRibKind::Item = rib.kind {
|
||||||
break;
|
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 {
|
for param in params {
|
||||||
let ident = param.ident.normalize_to_macros_2_0();
|
let ident = param.ident.normalize_to_macros_2_0();
|
||||||
|
@ -1942,16 +1931,17 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
if let GenericParamKind::Lifetime = param.kind {
|
if let GenericParamKind::Lifetime = param.kind {
|
||||||
match seen_lifetimes.entry(ident) {
|
match seen_lifetimes.entry(ident) {
|
||||||
Entry::Occupied(entry) => {
|
Entry::Occupied(entry) => {
|
||||||
let original = *entry.get();
|
let original = *entry.key();
|
||||||
diagnostics::signal_shadowing_problem(
|
let orig_is_param = *entry.get();
|
||||||
|
diagnostics::signal_lifetime_shadowing(
|
||||||
self.r.session,
|
self.r.session,
|
||||||
ident.name,
|
|
||||||
original,
|
original,
|
||||||
shadower_lifetime(param.ident.span),
|
param.ident,
|
||||||
)
|
orig_is_param,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
entry.insert(original_lifetime_param(param.ident.span));
|
entry.insert(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3155,26 +3145,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
|
self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forbid shadowing lifetime bindings
|
|
||||||
let ident = label.ident.normalize_to_macro_rules();
|
let ident = label.ident.normalize_to_macro_rules();
|
||||||
for rib in self.lifetime_ribs.iter().rev() {
|
|
||||||
if let Some((orig_ident, _)) = rib.bindings.get_key_value(&ident) {
|
|
||||||
diagnostics::signal_shadowing_problem(
|
|
||||||
self.r.session,
|
|
||||||
label.ident.name,
|
|
||||||
original_lifetime(orig_ident.span),
|
|
||||||
shadower_label(label.ident.span),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for rib in self.label_ribs.iter_mut().rev() {
|
for rib in self.label_ribs.iter_mut().rev() {
|
||||||
if let Some((orig_ident, _)) = rib.bindings.get_key_value(&ident) {
|
if let Some((&orig_ident, _)) = rib.bindings.get_key_value(&ident) {
|
||||||
diagnostics::signal_shadowing_problem(
|
diagnostics::signal_label_shadowing(self.r.session, orig_ident, label.ident)
|
||||||
self.r.session,
|
|
||||||
label.ident.name,
|
|
||||||
original_label(orig_ident.span),
|
|
||||||
shadower_label(label.ident.span),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if rib.kind.is_label_barrier() {
|
if rib.kind.is_label_barrier() {
|
||||||
rib.bindings.insert(ident, id);
|
rib.bindings.insert(ident, id);
|
||||||
|
|
|
@ -2037,84 +2037,44 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
/// Report lifetime/lifetime shadowing as an error.
|
||||||
enum ShadowKind {
|
pub fn signal_lifetime_shadowing(
|
||||||
Label,
|
sess: &Session,
|
||||||
Lifetime,
|
orig: Ident,
|
||||||
}
|
shadower: Ident,
|
||||||
#[derive(Copy, Clone)]
|
orig_is_param: bool,
|
||||||
pub struct Original {
|
) {
|
||||||
kind: ShadowKind,
|
let mut err = if orig_is_param {
|
||||||
span: Span,
|
struct_span_err!(
|
||||||
param: bool,
|
sess,
|
||||||
}
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct Shadower {
|
|
||||||
kind: ShadowKind,
|
|
||||||
span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn original_label(span: Span) -> Original {
|
|
||||||
Original { kind: ShadowKind::Label, span, param: false }
|
|
||||||
}
|
|
||||||
pub fn shadower_label(span: Span) -> Shadower {
|
|
||||||
Shadower { kind: ShadowKind::Label, span }
|
|
||||||
}
|
|
||||||
pub fn original_lifetime(span: Span) -> Original {
|
|
||||||
Original { kind: ShadowKind::Lifetime, span, param: false }
|
|
||||||
}
|
|
||||||
pub fn original_lifetime_param(span: Span) -> Original {
|
|
||||||
Original { kind: ShadowKind::Lifetime, span, param: true }
|
|
||||||
}
|
|
||||||
pub fn shadower_lifetime(span: Span) -> Shadower {
|
|
||||||
Shadower { kind: ShadowKind::Lifetime, span }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ShadowKind {
|
|
||||||
fn desc(&self) -> &'static str {
|
|
||||||
match *self {
|
|
||||||
ShadowKind::Label => "label",
|
|
||||||
ShadowKind::Lifetime => "lifetime",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn signal_shadowing_problem(sess: &Session, name: Symbol, orig: Original, shadower: Shadower) {
|
|
||||||
let mut err = if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
|
|
||||||
// lifetime/lifetime shadowing is an error
|
|
||||||
if orig.param {
|
|
||||||
struct_span_err!(
|
|
||||||
sess,
|
|
||||||
shadower.span,
|
|
||||||
E0263,
|
|
||||||
"lifetime name `{}` declared twice in the same scope",
|
|
||||||
name,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
struct_span_err!(
|
|
||||||
sess,
|
|
||||||
shadower.span,
|
|
||||||
E0496,
|
|
||||||
"lifetime name `{}` shadows a lifetime name that is already in scope",
|
|
||||||
name,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.forget_guarantee()
|
|
||||||
} else {
|
|
||||||
// shadowing involving a label is only a warning, due to issues with
|
|
||||||
// labels and lifetimes not being macro-hygienic.
|
|
||||||
sess.struct_span_warn(
|
|
||||||
shadower.span,
|
shadower.span,
|
||||||
&format!(
|
E0263,
|
||||||
"{} name `{}` shadows a {} name that is already in scope",
|
"lifetime name `{}` declared twice in the same scope",
|
||||||
shadower.kind.desc(),
|
orig.name,
|
||||||
name,
|
)
|
||||||
orig.kind.desc()
|
} else {
|
||||||
),
|
struct_span_err!(
|
||||||
|
sess,
|
||||||
|
shadower.span,
|
||||||
|
E0496,
|
||||||
|
"lifetime name `{}` shadows a lifetime name that is already in scope",
|
||||||
|
orig.name,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
err.span_label(orig.span, "first declared here");
|
err.span_label(orig.span, "first declared here");
|
||||||
err.span_label(shadower.span, format!("{} `{}` already in scope", orig.kind.desc(), name));
|
err.span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name));
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shadowing involving a label is only a warning, due to issues with
|
||||||
|
/// labels and lifetimes not being macro-hygienic.
|
||||||
|
pub fn signal_label_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
|
||||||
|
let mut err = sess.struct_span_warn(
|
||||||
|
shadower.span,
|
||||||
|
&format!("label name `{}` shadows a label name that is already in scope", orig.name),
|
||||||
|
);
|
||||||
|
err.span_label(orig.span, "first declared here");
|
||||||
|
err.span_label(shadower.span, format!("label `{}` already in scope", orig.name));
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue