Reuse resolve_label to check lifetime shadowing.
This commit is contained in:
parent
c75409d5e4
commit
86bd99060c
2 changed files with 29 additions and 40 deletions
|
@ -1548,13 +1548,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
|
|
||||||
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
|
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
|
||||||
/// label and reports an error if the label is not found or is unreachable.
|
/// label and reports an error if the label is not found or is unreachable.
|
||||||
fn resolve_label(&mut self, mut label: Ident) -> Option<NodeId> {
|
fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'a>> {
|
||||||
let mut suggestion = None;
|
let mut suggestion = None;
|
||||||
|
|
||||||
// Preserve the original span so that errors contain "in this macro invocation"
|
|
||||||
// information.
|
|
||||||
let original_span = label.span;
|
|
||||||
|
|
||||||
for i in (0..self.label_ribs.len()).rev() {
|
for i in (0..self.label_ribs.len()).rev() {
|
||||||
let rib = &self.label_ribs[i];
|
let rib = &self.label_ribs[i];
|
||||||
|
|
||||||
|
@ -1570,18 +1566,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
|
if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
|
||||||
let definition_span = ident.span;
|
let definition_span = ident.span;
|
||||||
return if self.is_label_valid_from_rib(i) {
|
return if self.is_label_valid_from_rib(i) {
|
||||||
Some(*id)
|
Ok((*id, definition_span))
|
||||||
} else {
|
} else {
|
||||||
self.report_error(
|
Err(ResolutionError::UnreachableLabel {
|
||||||
original_span,
|
|
||||||
ResolutionError::UnreachableLabel {
|
|
||||||
name: label.name,
|
name: label.name,
|
||||||
definition_span,
|
definition_span,
|
||||||
suggestion,
|
suggestion,
|
||||||
},
|
})
|
||||||
);
|
|
||||||
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1590,11 +1581,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
|
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.report_error(
|
Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion })
|
||||||
original_span,
|
|
||||||
ResolutionError::UndeclaredLabel { name: label.name, suggestion },
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
|
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
|
||||||
|
@ -3152,17 +3139,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = label.ident.normalize_to_macro_rules();
|
if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
|
||||||
for rib in self.label_ribs.iter_mut().rev() {
|
diagnostics::signal_label_shadowing(self.r.session, orig_span, label.ident)
|
||||||
if let Some((&orig_ident, _)) = rib.bindings.get_key_value(&ident) {
|
|
||||||
diagnostics::signal_label_shadowing(self.r.session, orig_ident, label.ident)
|
|
||||||
}
|
|
||||||
if rib.kind.is_label_barrier() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.with_label_rib(NormalRibKind, |this| {
|
self.with_label_rib(NormalRibKind, |this| {
|
||||||
|
let ident = label.ident.normalize_to_macro_rules();
|
||||||
this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
|
this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
|
||||||
f(this);
|
f(this);
|
||||||
});
|
});
|
||||||
|
@ -3266,11 +3248,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
|
||||||
if let Some(node_id) = self.resolve_label(label.ident) {
|
match self.resolve_label(label.ident) {
|
||||||
|
Ok((node_id, _)) => {
|
||||||
// Since this res is a label, it is never read.
|
// Since this res is a label, it is never read.
|
||||||
self.r.label_res_map.insert(expr.id, node_id);
|
self.r.label_res_map.insert(expr.id, node_id);
|
||||||
self.diagnostic_metadata.unused_labels.remove(&node_id);
|
self.diagnostic_metadata.unused_labels.remove(&node_id);
|
||||||
}
|
}
|
||||||
|
Err(error) => {
|
||||||
|
self.report_error(label.ident.span, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// visit `break` argument if any
|
// visit `break` argument if any
|
||||||
visit::walk_expr(self, expr);
|
visit::walk_expr(self, expr);
|
||||||
|
|
|
@ -2066,15 +2066,17 @@ pub fn signal_lifetime_shadowing(
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shadowing involving a label is only a warning, due to issues with
|
/// Shadowing involving a label is only a warning for historical reasons.
|
||||||
/// labels and lifetimes not being macro-hygienic.
|
//FIXME: make this a proper lint.
|
||||||
pub fn signal_label_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
|
pub fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
|
||||||
|
let name = shadower.name;
|
||||||
|
let shadower = shadower.span;
|
||||||
let mut err = sess.struct_span_warn(
|
let mut err = sess.struct_span_warn(
|
||||||
shadower.span,
|
shadower,
|
||||||
&format!("label name `{}` shadows a label name that is already in scope", orig.name),
|
&format!("label name `{}` shadows a label name that is already in scope", name),
|
||||||
);
|
);
|
||||||
err.span_label(orig.span, "first declared here");
|
err.span_label(orig, "first declared here");
|
||||||
err.span_label(shadower.span, format!("label `{}` already in scope", orig.name));
|
err.span_label(shadower, format!("label `{}` already in scope", name));
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue