Auto merge of #96296 - cjgillot:remove-label-lt-shadow, r=petrochenkov

Remove label/lifetime shadowing warnings

This PR removes some pre-1.0 shadowing warnings for labels and lifetimes.

The current behaviour of the compiler is to warn
* labels that shadow unrelated labels in the same function --> removed
```rust
'a: loop {}
'a: loop {} // STOP WARNING
```

* labels that shadow enclosing labels --> kept, but only if shadowing is hygienic
```rust
'a: loop {
  'a: loop {} // KEEP WARNING
}
```

* labels that shadow lifetime --> removed
```rust
fn foo<'a>() {
  'a: loop {} // STOP WARNING
}
```

* lifetimes that shadow labels --> removed
```rust
'a: loop {
  let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>; // STOP WARNING
}
```

* lifetimes that shadow lifetimes --> kept
```rust
fn foo<'a>() {
  let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>; // KEEP WARNING
}
```

Closes https://github.com/rust-lang/rust/issues/31745.

-----

From `@petrochenkov` in https://github.com/rust-lang/rust/pull/95781#issuecomment-1105199014
> I think we should remove these silly checks entirely.
> They were introduced long time ago in case some new language features appear and require this space.
> Now we have another mechanism for such language changes - editions, and if "lifetimes in expressions" or something like that needs to be introduced it could be introduced as an edition change.
> However, there was no plans to introduce anything like for years, so it's unlikely that even the edition mechanism will be necessary.

r? rust-lang/lang
This commit is contained in:
bors 2022-06-03 07:27:09 +00:00
commit 3a90bedb33
31 changed files with 223 additions and 1751 deletions

View file

@ -1848,14 +1848,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
let (name, kind) = match param.kind {
GenericParamKind::Lifetime => {
let param_name = if param.ident.name == kw::StaticLifetime
|| param.ident.name == kw::UnderscoreLifetime
{
ParamName::Error
} else {
let ident = self.lower_ident(param.ident);
ParamName::Plain(ident)
};
// AST resolution emitted an error on those parameters, so we lower them using
// `ParamName::Error`.
let param_name =
if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) {
ParamName::Error
} else {
let ident = self.lower_ident(param.ident);
ParamName::Plain(ident)
};
let kind =
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit };
@ -1880,10 +1881,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
}
};
let name = match name {
hir::ParamName::Plain(ident) => hir::ParamName::Plain(self.lower_ident(ident)),
name => name,
};
let hir_id = self.lower_node_id(param.id);
self.lower_attrs(hir_id, &param.attrs);

View file

@ -1,8 +1,10 @@
#### Note: this error code is no longer emitted by the compiler.
A lifetime was declared more than once in the same scope.
Erroneous code example:
```compile_fail,E0263
```compile_fail,E0403
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str, z: &'a str) { // error!
}
```

View file

@ -172,6 +172,23 @@ impl RibKind<'_> {
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 +749,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// 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 {
@ -1531,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
/// 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;
// 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() {
let rib = &self.label_ribs[i];
@ -1553,18 +1566,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
let definition_span = ident.span;
return if self.is_label_valid_from_rib(i) {
Some(*id)
Ok((*id, definition_span))
} else {
self.report_error(
original_span,
ResolutionError::UnreachableLabel {
name: label.name,
definition_span,
suggestion,
},
);
None
Err(ResolutionError::UnreachableLabel {
name: label.name,
definition_span,
suggestion,
})
};
}
@ -1573,11 +1581,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
}
self.report_error(
original_span,
ResolutionError::UndeclaredLabel { name: label.name, suggestion },
);
None
Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion })
}
/// Determine whether or not a label from the `rib_index`th label rib is reachable.
@ -1585,22 +1589,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
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 +1885,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let mut function_value_rib = Rib::new(kind);
let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);
let mut seen_bindings = FxHashMap::default();
// Store all seen lifetimes names from outer scopes.
let mut seen_lifetimes = FxHashSet::default();
// We also can't shadow bindings from the parent item
if let AssocItemRibKind = kind {
@ -1910,16 +1902,36 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
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));
if let LifetimeRibKind::Item = rib.kind {
break;
}
}
for param in params {
let ident = param.ident.normalize_to_macros_2_0();
debug!("with_generic_param_rib: {}", param.id);
if let GenericParamKind::Lifetime = param.kind
&& let Some(&original) = seen_lifetimes.get(&ident)
{
diagnostics::signal_lifetime_shadowing(self.r.session, original, param.ident);
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_res(param.id, LifetimeRes::Error);
continue;
}
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);
self.report_error(param.ident.span, err);
if let GenericParamKind::Lifetime = param.kind {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_res(param.id, LifetimeRes::Error);
continue;
}
}
Entry::Vacant(entry) => {
@ -1936,6 +1948,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
)
.span_label(param.ident.span, "`'_` is a reserved lifetime name")
.emit();
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_res(param.id, LifetimeRes::Error);
continue;
}
@ -1949,6 +1963,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
)
.span_label(param.ident.span, "'static is a reserved lifetime name")
.emit();
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_res(param.id, LifetimeRes::Error);
continue;
}
@ -3114,6 +3130,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
if label.ident.as_str().as_bytes()[1] != b'_' {
self.diagnostic_metadata.unused_labels.insert(id, label.ident.span);
}
if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
diagnostics::signal_label_shadowing(self.r.session, orig_span, label.ident)
}
self.with_label_rib(NormalRibKind, |this| {
let ident = label.ident.normalize_to_macro_rules();
this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
@ -3219,10 +3240,15 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
if let Some(node_id) = self.resolve_label(label.ident) {
// Since this res is a label, it is never read.
self.r.label_res_map.insert(expr.id, node_id);
self.diagnostic_metadata.unused_labels.remove(&node_id);
match self.resolve_label(label.ident) {
Ok((node_id, _)) => {
// Since this res is a label, it is never read.
self.r.label_res_map.insert(expr.id, node_id);
self.diagnostic_metadata.unused_labels.remove(&node_id);
}
Err(error) => {
self.report_error(label.ident.span, error);
}
}
// visit `break` argument if any

View file

@ -25,6 +25,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::PrimTy;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
use rustc_span::lev_distance::find_best_match_for_name;
@ -2036,6 +2037,34 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
/// Report lifetime/lifetime shadowing as an error.
pub fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
let mut err = 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(shadower.span, format!("lifetime `{}` already in scope", orig.name));
err.emit();
}
/// Shadowing involving a label is only a warning for historical reasons.
//FIXME: make this a proper lint.
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(
shadower,
&format!("label name `{}` shadows a label name that is already in scope", name),
);
err.span_label(orig, "first declared here");
err.span_label(shadower, format!("label `{}` already in scope", name));
err.emit();
}
impl<'tcx> LifetimeContext<'_, 'tcx> {
pub(crate) fn report_missing_lifetime_specifiers(
&self,

View file

@ -23,7 +23,7 @@ use rustc_middle::middle::resolve_lifetime::*;
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use std::borrow::Cow;
use std::cell::Cell;
@ -161,9 +161,6 @@ pub(crate) struct LifetimeContext<'a, 'tcx> {
/// we eventually need lifetimes resolve for trait items.
trait_definition_only: bool,
/// List of labels in the function/method currently under analysis.
labels_in_fn: Vec<Ident>,
/// Cache for cross-crate per-definition object lifetime defaults.
xcrate_object_lifetime_defaults: DefIdMap<Vec<ObjectLifetimeDefault>>,
@ -434,7 +431,6 @@ fn do_resolve(
map: &mut named_region_map,
scope: ROOT_SCOPE,
trait_definition_only,
labels_in_fn: vec![],
xcrate_object_lifetime_defaults: Default::default(),
missing_named_lifetime_spots: vec![],
};
@ -641,14 +637,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
// Each body has their own set of labels, save labels.
let saved = take(&mut self.labels_in_fn);
let body = self.tcx.hir().body(body);
extract_labels(self, body);
self.with(Scope::Body { id: body.id(), s: self.scope }, |_, this| {
self.with(Scope::Body { id: body.id(), s: self.scope }, |this| {
this.visit_body(body);
});
self.labels_in_fn = saved;
}
fn visit_fn(
@ -683,9 +675,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: true,
};
self.with(scope, move |_old_scope, this| {
intravisit::walk_fn(this, fk, fd, b, s, hir_id)
});
self.with(scope, move |this| intravisit::walk_fn(this, fk, fd, b, s, hir_id));
}
}
}
@ -720,7 +710,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => {
// No lifetime parameters, but implied 'static.
let scope = Scope::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE };
self.with(scope, |_, this| intravisit::walk_item(this, item));
self.with(scope, |this| intravisit::walk_item(this, item));
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
// Opaque types are visited when we visit the
@ -807,10 +797,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
s: ROOT_SCOPE,
allow_late_bound: false,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
intravisit::walk_item(this, item);
});
});
@ -873,10 +862,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: true,
};
self.with(scope, |old_scope, this| {
self.with(scope, |this| {
// a bare fn has no bounds, so everything
// contained within is scoped within its binder.
this.check_lifetime_params(old_scope, &c.generic_params);
intravisit::walk_ty(this, ty);
});
self.missing_named_lifetime_spots.pop();
@ -884,7 +872,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
hir::TyKind::TraitObject(bounds, ref lifetime, _) => {
debug!(?bounds, ?lifetime, "TraitObject");
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |_, this| {
self.with(scope, |this| {
for bound in bounds {
this.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
}
@ -923,7 +911,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(),
s: self.scope,
};
self.with(scope, |_, this| this.visit_ty(&mt.ty));
self.with(scope, |this| this.visit_ty(&mt.ty));
}
hir::TyKind::OpaqueDef(item_id, lifetimes) => {
// Resolve the lifetimes in the bounds to the lifetime defs in the generics.
@ -944,9 +932,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// Elided lifetimes are not allowed in non-return
// position impl Trait
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |_, this| {
self.with(scope, |this| {
let scope = Scope::Elision { elide: Elide::Forbid, s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
intravisit::walk_item(this, opaque_ty);
})
});
@ -1052,7 +1040,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
if let Some(elision_region) = elision {
let scope =
Scope::Elision { elide: Elide::Exact(elision_region), s: self.scope };
self.with(scope, |_old_scope, this| {
self.with(scope, |this| {
let scope = Scope::Binder {
hir_id: ty.hir_id,
lifetimes,
@ -1062,10 +1050,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: false,
};
this.with(scope, |_old_scope, this| {
this.with(scope, |this| {
this.visit_generics(generics);
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
for bound in bounds {
this.visit_param_bound(bound);
}
@ -1082,9 +1070,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: false,
};
self.with(scope, |_old_scope, this| {
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
this.visit_generics(generics);
for bound in bounds {
this.visit_param_bound(bound);
@ -1141,10 +1129,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: false,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
this.visit_generics(generics);
for bound in bounds {
this.visit_param_bound(bound);
@ -1210,10 +1197,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: true,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |_, this| {
this.with(scope, |this| {
this.visit_generics(generics);
this.visit_ty(ty);
})
@ -1300,7 +1286,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |_, this| {
self.with(scope, |this| {
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
@ -1354,8 +1340,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: true,
};
this.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &bound_generic_params);
this.with(scope, |this| {
this.visit_ty(&bounded_ty);
walk_list!(this, visit_param_bound, bounds);
})
@ -1427,7 +1412,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type,
allow_late_bound: true,
};
self.with(scope, |_, this| {
self.with(scope, |this| {
intravisit::walk_param_bound(this, bound);
});
}
@ -1479,8 +1464,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
scope_type,
allow_late_bound: true,
};
self.with(scope, |old_scope, this| {
this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params);
self.with(scope, |this| {
walk_list!(this, visit_generic_param, trait_ref.bound_generic_params);
this.visit_trait_ref(&trait_ref.trait_ref);
});
@ -1491,154 +1475,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
}
}
#[derive(Copy, Clone, PartialEq)]
enum ShadowKind {
Label,
Lifetime,
}
struct Original {
kind: ShadowKind,
span: Span,
}
struct Shadower {
kind: ShadowKind,
span: Span,
}
fn original_label(span: Span) -> Original {
Original { kind: ShadowKind::Label, span }
}
fn shadower_label(span: Span) -> Shadower {
Shadower { kind: ShadowKind::Label, span }
}
fn original_lifetime(span: Span) -> Original {
Original { kind: ShadowKind::Lifetime, span }
}
fn shadower_lifetime(param: &hir::GenericParam<'_>) -> Shadower {
Shadower { kind: ShadowKind::Lifetime, span: param.span }
}
impl ShadowKind {
fn desc(&self) -> &'static str {
match *self {
ShadowKind::Label => "label",
ShadowKind::Lifetime => "lifetime",
}
}
}
fn signal_shadowing_problem(tcx: TyCtxt<'_>, 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
struct_span_err!(
tcx.sess,
shadower.span,
E0496,
"{} name `{}` shadows a \
{} name that is already in scope",
shadower.kind.desc(),
name,
orig.kind.desc()
)
.forget_guarantee()
} else {
// shadowing involving a label is only a warning, due to issues with
// labels and lifetimes not being macro-hygienic.
tcx.sess.struct_span_warn(
shadower.span,
&format!(
"{} name `{}` shadows a \
{} name that is already in scope",
shadower.kind.desc(),
name,
orig.kind.desc()
),
)
};
err.span_label(orig.span, "first declared here");
err.span_label(shadower.span, format!("{} `{}` already in scope", orig.kind.desc(), name));
err.emit();
}
// Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning
// if one of the label shadows a lifetime or another label.
fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) {
struct GatherLabels<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
scope: ScopeRef<'a>,
labels_in_fn: &'a mut Vec<Ident>,
}
let mut gather =
GatherLabels { tcx: ctxt.tcx, scope: ctxt.scope, labels_in_fn: &mut ctxt.labels_in_fn };
gather.visit_body(body);
impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> {
fn visit_expr(&mut self, ex: &hir::Expr<'_>) {
if let Some(label) = expression_label(ex) {
for prior_label in &self.labels_in_fn[..] {
// FIXME (#24278): non-hygienic comparison
if label.name == prior_label.name {
signal_shadowing_problem(
self.tcx,
label.name,
original_label(prior_label.span),
shadower_label(label.span),
);
}
}
check_if_label_shadows_lifetime(self.tcx, self.scope, label);
self.labels_in_fn.push(label);
}
intravisit::walk_expr(self, ex)
}
}
fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> {
match ex.kind {
hir::ExprKind::Loop(_, Some(label), ..) => Some(label.ident),
hir::ExprKind::Block(_, Some(label)) => Some(label.ident),
_ => None,
}
}
fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) {
loop {
match *scope {
Scope::Body { s, .. }
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
scope = s;
}
Scope::Root => {
return;
}
Scope::Binder { ref lifetimes, s, .. } => {
// FIXME (#24278): non-hygienic comparison
if let Some(def) =
lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0()))
{
signal_shadowing_problem(
tcx,
label.name,
original_lifetime(tcx.def_span(def.id().unwrap().expect_local())),
shadower_label(label.span),
);
return;
}
scope = s;
}
}
}
}
}
fn compute_object_lifetime_defaults<'tcx>(
tcx: TyCtxt<'tcx>,
item: &hir::Item<'_>,
@ -1774,10 +1610,9 @@ fn object_lifetime_defaults_for_item<'tcx>(
impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
where
F: for<'b> FnOnce(ScopeRef<'_>, &mut LifetimeContext<'b, 'tcx>),
F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
{
let LifetimeContext { tcx, map, .. } = self;
let labels_in_fn = take(&mut self.labels_in_fn);
let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults);
let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots);
let mut this = LifetimeContext {
@ -1785,16 +1620,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
map,
scope: &wrap_scope,
trait_definition_only: self.trait_definition_only,
labels_in_fn,
xcrate_object_lifetime_defaults,
missing_named_lifetime_spots,
};
let span = tracing::debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope));
{
let _enter = span.enter();
f(self.scope, &mut this);
f(&mut this);
}
self.labels_in_fn = this.labels_in_fn;
self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults;
self.missing_named_lifetime_spots = this.missing_named_lifetime_spots;
}
@ -1891,10 +1724,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
scope_type: BinderScopeType::Normal,
allow_late_bound: true,
};
self.with(scope, move |old_scope, this| {
this.check_lifetime_params(old_scope, &generics.params);
walk(this);
});
self.with(scope, walk);
}
fn next_early_index_helper(&self, only_opaque_type_parent: bool) -> u32 {
@ -2165,7 +1995,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
GenericArg::Type(ty) => {
if let Some(&lt) = object_lifetime_defaults.get(i) {
let scope = Scope::ObjectLifetimeDefault { lifetime: lt, s: self.scope };
self.with(scope, |_, this| this.visit_ty(ty));
self.with(scope, |this| this.visit_ty(ty));
} else {
self.visit_ty(ty);
}
@ -2222,15 +2052,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
type_def_id,
binding.ident,
);
self.with(scope, |_, this| {
self.with(scope, |this| {
let scope = Scope::Supertrait {
lifetimes: lifetimes.unwrap_or_default(),
s: this.scope,
};
this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
this.with(scope, |this| this.visit_assoc_type_binding(binding));
});
} else {
self.with(scope, |_, this| this.visit_assoc_type_binding(binding));
self.with(scope, |this| this.visit_assoc_type_binding(binding));
}
}
}
@ -2346,7 +2176,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
elide: Elide::FreshLateAnon(named_late_bound_vars, Cell::new(0)),
s: self.scope,
};
self.with(arg_scope, |_, this| {
self.with(arg_scope, |this| {
for input in inputs {
this.visit_ty(input);
}
@ -2466,7 +2296,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
visitor.visit_ty(&inputs[0]);
if let Set1::One(lifetime) = visitor.lifetime {
let scope = Scope::Elision { elide: Elide::Exact(lifetime), s: self.scope };
self.with(scope, |_, this| this.visit_ty(output));
self.with(scope, |this| this.visit_ty(output));
return;
}
}
@ -2517,7 +2347,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
debug!(?elide);
let scope = Scope::Elision { elide, s: self.scope };
self.with(scope, |_, this| this.visit_ty(output));
self.with(scope, |this| this.visit_ty(output));
struct GatherLifetimes<'a> {
map: &'a NamedRegionMap,
@ -2789,101 +2619,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
}
fn check_lifetime_params(
&mut self,
old_scope: ScopeRef<'_>,
params: &'tcx [hir::GenericParam<'tcx>],
) {
let lifetimes: Vec<_> = params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
Some((param, param.name.normalize_to_macros_2_0()))
}
_ => None,
})
.collect();
for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() {
if let hir::ParamName::Plain(_) = lifetime_i_name {
let name = lifetime_i_name.ident().name;
if name == kw::UnderscoreLifetime || name == kw::StaticLifetime {
self.tcx.sess.delay_span_bug(
lifetime_i.span,
&format!("invalid lifetime parameter name: `{}`", lifetime_i.name.ident()),
);
}
}
// It is a hard error to shadow a lifetime within the same scope.
for (lifetime_j, lifetime_j_name) in lifetimes.iter().skip(i + 1) {
if lifetime_i_name == lifetime_j_name {
struct_span_err!(
self.tcx.sess,
lifetime_j.span,
E0263,
"lifetime name `{}` declared twice in the same scope",
lifetime_j.name.ident()
)
.span_label(lifetime_j.span, "declared twice")
.span_label(lifetime_i.span, "previous declaration here")
.emit();
}
}
// It is a soft error to shadow a lifetime within a parent scope.
self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i);
}
}
fn check_lifetime_param_for_shadowing(
&self,
mut old_scope: ScopeRef<'_>,
param: &'tcx hir::GenericParam<'tcx>,
) {
for label in &self.labels_in_fn {
// FIXME (#24278): non-hygienic comparison
if param.name.ident().name == label.name {
signal_shadowing_problem(
self.tcx,
label.name,
original_label(label.span),
shadower_lifetime(&param),
);
return;
}
}
loop {
match *old_scope {
Scope::Body { s, .. }
| Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
old_scope = s;
}
Scope::Root => {
return;
}
Scope::Binder { ref lifetimes, s, .. } => {
if let Some(&def) = lifetimes.get(&param.name.normalize_to_macros_2_0()) {
signal_shadowing_problem(
self.tcx,
param.name.ident().name,
original_lifetime(self.tcx.def_span(def.id().unwrap())),
shadower_lifetime(&param),
);
return;
}
old_scope = s;
}
}
}
}
#[tracing::instrument(level = "debug", skip(self))]
fn insert_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime, def: Region) {
debug!(

View file

@ -1,5 +1,5 @@
fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
//~^ ERROR E0263
//~^ ERROR E0403
}
fn main() {}

View file

@ -1,11 +1,11 @@
error[E0263]: lifetime name `'a` declared twice in the same scope
error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters
--> $DIR/E0263.rs:1:16
|
LL | fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
| -- ^^ declared twice
| -- ^^ already used
| |
| previous declaration here
| first use of `'a`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0263`.
For more information about this error, try `rustc --explain E0403`.

View file

@ -102,7 +102,7 @@ fn label_break_match(c: u8, xe: u8, ye: i8) {
0 => break 'a 0,
v if { if v % 2 == 0 { break 'a 1; }; v % 3 == 0 } => { x += 1; },
v if { 'b: { break 'b v == 5; } } => { x = 41; },
_ => 'b: { //~ WARNING `'b` shadows a label
_ => 'b: {
break 'b ();
},
}
@ -128,8 +128,8 @@ fn label_break_macro() {
0
};
assert_eq!(x, 0);
let x: u8 = 'a: { //~ WARNING `'a` shadows a label
'b: { //~ WARNING `'b` shadows a label
let x: u8 = 'a: {
'b: {
if true {
mac1!('a, 1);
}

View file

@ -1,28 +0,0 @@
warning: label name `'b` shadows a label name that is already in scope
--> $DIR/label_break_value.rs:105:18
|
LL | v if { 'b: { break 'b v == 5; } } => { x = 41; },
| -- first declared here
LL | _ => 'b: {
| ^^ label `'b` already in scope
warning: label name `'a` shadows a label name that is already in scope
--> $DIR/label_break_value.rs:131:17
|
LL | let x: u8 = 'a: {
| -- first declared here
...
LL | let x: u8 = 'a: {
| ^^ label `'a` already in scope
warning: label name `'b` shadows a label name that is already in scope
--> $DIR/label_break_value.rs:132:9
|
LL | 'b: {
| -- first declared here
...
LL | 'b: {
| ^^ label `'b` already in scope
warning: 3 warnings emitted

View file

@ -20,14 +20,11 @@ fn lbv_macro_test_hygiene_respected() {
macro_rules! mac3 {
($val:expr) => {
'a: {
//~^ WARNING `'a` shadows a label
//~| WARNING `'a` shadows a label
//~| WARNING `'a` shadows a label
$val
}
};
}
let x: u8 = mac3!('b: { //~ WARNING `'b` shadows a label
let x: u8 = mac3!('b: {
if true {
break 'a 3; //~ ERROR undeclared label `'a` [E0426]
}

View file

@ -10,7 +10,7 @@ LL | mac2!(2);
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0426]: use of undeclared label `'a`
--> $DIR/label_break_value_invalid.rs:32:19
--> $DIR/label_break_value_invalid.rs:29:19
|
LL | let x: u8 = mac3!('b: {
| -- a label with a similar name is reachable
@ -22,68 +22,11 @@ LL | break 'a 3;
| help: try using similarly named label: `'b`
error[E0426]: use of undeclared label `'a`
--> $DIR/label_break_value_invalid.rs:37:29
--> $DIR/label_break_value_invalid.rs:34:29
|
LL | let x: u8 = mac3!(break 'a 4);
| ^^ undeclared label `'a`
warning: label name `'a` shadows a label name that is already in scope
--> $DIR/label_break_value_invalid.rs:22:13
|
LL | let x: u8 = 'a: {
| -- first declared here
...
LL | 'a: {
| ^^ label `'a` already in scope
...
LL | let x: u8 = mac3!('b: {
| _________________-
LL | | if true {
LL | | break 'a 3;
LL | | }
LL | | 0
LL | | });
| |______- in this macro invocation
|
= note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'b` shadows a label name that is already in scope
--> $DIR/label_break_value_invalid.rs:30:23
|
LL | 'b: {
| -- first declared here
...
LL | let x: u8 = mac3!('b: {
| ^^ label `'b` already in scope
warning: label name `'a` shadows a label name that is already in scope
--> $DIR/label_break_value_invalid.rs:22:13
|
LL | let x: u8 = 'a: {
| -- first declared here
...
LL | 'a: {
| ^^ label `'a` already in scope
...
LL | let x: u8 = mac3!(break 'a 4);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'a` shadows a label name that is already in scope
--> $DIR/label_break_value_invalid.rs:22:13
|
LL | 'a: {
| ^^
| |
| first declared here
| label `'a` already in scope
...
LL | let x: u8 = mac3!(break 'a 4);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `mac3` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors; 4 warnings emitted
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0426`.

View file

@ -1,3 +1,19 @@
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
--> $DIR/shadowing.rs:4:14
|
LL | trait Shadow<'a> {
| -- first declared here
LL | type Bar<'a>;
| ^^ lifetime `'a` already in scope
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
--> $DIR/shadowing.rs:13:14
|
LL | impl<'a> NoShadow<'a> for &'a u32 {
| -- first declared here
LL | type Bar<'a> = i32;
| ^^ lifetime `'a` already in scope
error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters
--> $DIR/shadowing.rs:18:14
|
@ -14,22 +30,6 @@ LL | impl<T> NoShadowT<T> for Option<T> {
LL | type Bar<T> = i32;
| ^ already used
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
--> $DIR/shadowing.rs:13:14
|
LL | impl<'a> NoShadow<'a> for &'a u32 {
| -- first declared here
LL | type Bar<'a> = i32;
| ^^ lifetime `'a` already in scope
error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope
--> $DIR/shadowing.rs:4:14
|
LL | trait Shadow<'a> {
| -- first declared here
LL | type Bar<'a>;
| ^^ lifetime `'a` already in scope
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0403, E0496.

View file

@ -5,12 +5,12 @@
#[rustc_macro_transparency = "semitransparent"]
macro m($a:lifetime) {
fn g<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
fn g<$a, 'a>() {} //~ ERROR the name `'a` is already used for a generic parameter
}
#[rustc_macro_transparency = "transparent"]
macro n($a:lifetime) {
fn h<$a, 'a>() {} //~ ERROR lifetime name `'a` declared twice
fn h<$a, 'a>() {} //~ ERROR the name `'a` is already used for a generic parameter
}
m!('a);

View file

@ -1,31 +1,31 @@
error[E0263]: lifetime name `'a` declared twice in the same scope
error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters
--> $DIR/duplicate_lifetimes.rs:8:14
|
LL | fn g<$a, 'a>() {}
| ^^ declared twice
| ^^ already used
...
LL | m!('a);
| ------
| | |
| | previous declaration here
| | first use of `'a`
| in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0263]: lifetime name `'a` declared twice in the same scope
error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters
--> $DIR/duplicate_lifetimes.rs:13:14
|
LL | fn h<$a, 'a>() {}
| ^^ declared twice
| ^^ already used
...
LL | n!('a);
| ------
| | |
| | previous declaration here
| | first use of `'a`
| in this macro invocation
|
= note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0263`.
For more information about this error, try `rustc --explain E0403`.

View file

@ -13,38 +13,28 @@
macro_rules! loop_x {
($e: expr) => {
// $e shouldn't be able to interact with this 'x
'x: loop { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: loop {
$e
}
};
}
macro_rules! while_true {
($e: expr) => {
// $e shouldn't be able to interact with this 'x
'x: while 1 + 1 == 2 { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: while 1 + 1 == 2 {
$e
}
};
}
macro_rules! run_once {
($e: expr) => {
// ditto
'x: for _ in 0..1 { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: for _ in 0..1 {
$e
}
};
}
pub fn main() {
@ -62,8 +52,6 @@ pub fn main() {
let k: isize = {
'x: for _ in 0..1 {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
// ditto
loop_x!(break 'x);
i += 1;
@ -74,10 +62,6 @@ pub fn main() {
let l: isize = {
'x: for _ in 0..1 {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
// ditto
while_true!(break 'x);
i += 1;
@ -88,12 +72,6 @@ pub fn main() {
let n: isize = {
'x: for _ in 0..1 {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
// ditto
run_once!(continue 'x);
i += 1;

View file

@ -1,334 +0,0 @@
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:16:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
LL | // this 'x should refer to the outer loop, lexically
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:64:9
|
LL | 'x: loop {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:64:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:16:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:16:9
|
LL | 'x: loop { $e }
| ^^
| |
| first declared here
| label `'x` already in scope
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:16:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:76:9
|
LL | 'x: loop {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:76:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:76:9
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:76:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:27:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | while_true!(break 'x);
| --------------------- in this macro invocation
|
= note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:27:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | while_true!(break 'x);
| --------------------- in this macro invocation
|
= note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:27:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | while_true!(break 'x);
| --------------------- in this macro invocation
|
= note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:27:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | while_true!(break 'x);
| --------------------- in this macro invocation
|
= note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:27:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | while_true!(break 'x);
| --------------------- in this macro invocation
|
= note: this warning originates in the macro `while_true` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: loop {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:90:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels-in-let.rs:39:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 28 warnings emitted

View file

@ -10,38 +10,28 @@
macro_rules! loop_x {
($e: expr) => {
// $e shouldn't be able to interact with this 'x
'x: loop { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: loop {
$e
}
};
}
macro_rules! run_once {
($e: expr) => {
// ditto
'x: for _ in 0..1 { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: for _ in 0..1 {
$e
}
};
}
macro_rules! while_x {
($e: expr) => {
// ditto
'x: while 1 + 1 == 2 { $e }
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
}
'x: while 1 + 1 == 2 {
$e
}
};
}
pub fn main() {
@ -52,32 +42,17 @@ pub fn main() {
}
'x: loop {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
// ditto
loop_x!(break 'x);
panic!("break doesn't act hygienically inside infinite loop");
}
'x: while 1 + 1 == 2 {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
while_x!(break 'x);
panic!("break doesn't act hygienically inside infinite while loop");
}
'x: for _ in 0..1 {
//~^ WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
//~| WARNING shadows a label name that is already in scope
// ditto
run_once!(continue 'x);
panic!("continue doesn't act hygienically inside for loop");

View file

@ -1,334 +0,0 @@
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:13:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
LL | // this 'x should refer to the outer loop, lexically
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:54:5
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: loop {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:54:5
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: loop {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:13:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:13:9
|
LL | 'x: loop { $e }
| ^^
| |
| first declared here
| label `'x` already in scope
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:13:9
|
LL | 'x: loop { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | loop_x!(break 'x);
| ----------------- in this macro invocation
|
= note: this warning originates in the macro `loop_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:63:5
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:63:5
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:63:5
|
LL | 'x: loop {
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:63:5
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:38:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | while_x!(break 'x);
| ------------------ in this macro invocation
|
= note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:38:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | while_x!(break 'x);
| ------------------ in this macro invocation
|
= note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:38:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | while_x!(break 'x);
| ------------------ in this macro invocation
|
= note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:38:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | while_x!(break 'x);
| ------------------ in this macro invocation
|
= note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:38:9
|
LL | 'x: while 1 + 1 == 2 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: while 1 + 1 == 2 {
| -- first declared here
...
LL | while_x!(break 'x);
| ------------------ in this macro invocation
|
= note: this warning originates in the macro `while_x` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: loop {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: while 1 + 1 == 2 {
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:73:5
|
LL | 'x: while 1 + 1 == 2 { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 {
| ^^ label `'x` already in scope
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: loop {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: loop { $e }
| -- first declared here
...
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: while 1 + 1 == 2 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: while 1 + 1 == 2 { $e }
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: label name `'x` shadows a label name that is already in scope
--> $DIR/hygienic-labels.rs:24:9
|
LL | 'x: for _ in 0..1 { $e }
| ^^ label `'x` already in scope
...
LL | 'x: for _ in 0..1 {
| -- first declared here
...
LL | run_once!(continue 'x);
| ---------------------- in this macro invocation
|
= note: this warning originates in the macro `run_once` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 28 warnings emitted

View file

@ -1,3 +1,12 @@
warning: label name `'many_used_shadowed` shadows a label name that is already in scope
--> $DIR/unused_labels.rs:62:9
|
LL | 'many_used_shadowed: for _ in 0..10 {
| ------------------- first declared here
LL |
LL | 'many_used_shadowed: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope
warning: unused label
--> $DIR/unused_labels.rs:11:5
|
@ -52,14 +61,5 @@ warning: unused label
LL | 'unused_block_label: {
| ^^^^^^^^^^^^^^^^^^^
warning: label name `'many_used_shadowed` shadows a label name that is already in scope
--> $DIR/unused_labels.rs:62:9
|
LL | 'many_used_shadowed: for _ in 0..10 {
| ------------------- first declared here
LL |
LL | 'many_used_shadowed: for _ in 0..10 {
| ^^^^^^^^^^^^^^^^^^^ label `'many_used_shadowed` already in scope
warning: 9 warnings emitted

View file

@ -1,36 +0,0 @@
// check-pass
#![feature(label_break_value)]
// Issue #21633: reject duplicate loop labels and block labels in function bodies.
//
// This is testing the generalization (to the whole function body)
// discussed here:
// https://internals.rust-lang.org/t/psa-rejecting-duplicate-loop-labels/1833
#[allow(unused_labels)]
pub fn foo() {
{ 'fl: for _ in 0..10 { break; } }
{ 'fl: loop { break; } } //~ WARN label name `'fl` shadows a label name that is already in scope
{ 'lf: loop { break; } }
{ 'lf: for _ in 0..10 { break; } } //~ WARN label name `'lf` shadows a label name that is already in scope
{ 'wl: while 2 > 1 { break; } }
{ 'wl: loop { break; } } //~ WARN label name `'wl` shadows a label name that is already in scope
{ 'lw: loop { break; } }
{ 'lw: while 2 > 1 { break; } } //~ WARN label name `'lw` shadows a label name that is already in scope
{ 'fw: for _ in 0..10 { break; } }
{ 'fw: while 2 > 1 { break; } } //~ WARN label name `'fw` shadows a label name that is already in scope
{ 'wf: while 2 > 1 { break; } }
{ 'wf: for _ in 0..10 { break; } } //~ WARN label name `'wf` shadows a label name that is already in scope
{ 'tl: while let Some(_) = None::<i32> { break; } }
{ 'tl: loop { break; } } //~ WARN label name `'tl` shadows a label name that is already in scope
{ 'lt: loop { break; } }
{ 'lt: while let Some(_) = None::<i32> { break; } }
//~^ WARN label name `'lt` shadows a label name that is already in scope
{ 'bl: {} }
{ 'bl: {} } //~ WARN label name `'bl` shadows a label name that is already in scope
}
pub fn main() {
foo();
}

View file

@ -1,74 +0,0 @@
warning: label name `'fl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:13:7
|
LL | { 'fl: for _ in 0..10 { break; } }
| --- first declared here
LL | { 'fl: loop { break; } }
| ^^^ label `'fl` already in scope
warning: label name `'lf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:15:7
|
LL | { 'lf: loop { break; } }
| --- first declared here
LL | { 'lf: for _ in 0..10 { break; } }
| ^^^ label `'lf` already in scope
warning: label name `'wl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:17:7
|
LL | { 'wl: while 2 > 1 { break; } }
| --- first declared here
LL | { 'wl: loop { break; } }
| ^^^ label `'wl` already in scope
warning: label name `'lw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:19:7
|
LL | { 'lw: loop { break; } }
| --- first declared here
LL | { 'lw: while 2 > 1 { break; } }
| ^^^ label `'lw` already in scope
warning: label name `'fw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:21:7
|
LL | { 'fw: for _ in 0..10 { break; } }
| --- first declared here
LL | { 'fw: while 2 > 1 { break; } }
| ^^^ label `'fw` already in scope
warning: label name `'wf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:23:7
|
LL | { 'wf: while 2 > 1 { break; } }
| --- first declared here
LL | { 'wf: for _ in 0..10 { break; } }
| ^^^ label `'wf` already in scope
warning: label name `'tl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:25:7
|
LL | { 'tl: while let Some(_) = None::<i32> { break; } }
| --- first declared here
LL | { 'tl: loop { break; } }
| ^^^ label `'tl` already in scope
warning: label name `'lt` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:27:7
|
LL | { 'lt: loop { break; } }
| --- first declared here
LL | { 'lt: while let Some(_) = None::<i32> { break; } }
| ^^^ label `'lt` already in scope
warning: label name `'bl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels-2.rs:30:7
|
LL | { 'bl: {} }
| --- first declared here
LL | { 'bl: {} }
| ^^^ label `'bl` already in scope
warning: 9 warnings emitted

View file

@ -1,49 +0,0 @@
// check-pass
#![feature(label_break_value)]
// Issue #21633: reject duplicate loop labels and block labels in function bodies.
#[allow(unused_labels)]
fn foo() {
'fl: for _ in 0..10 { break; }
'fl: loop { break; } //~ WARN label name `'fl` shadows a label name that is already in scope
'lf: loop { break; }
'lf: for _ in 0..10 { break; } //~ WARN label name `'lf` shadows a label name that is already in scope
'wl: while 2 > 1 { break; }
'wl: loop { break; } //~ WARN label name `'wl` shadows a label name that is already in scope
'lw: loop { break; }
'lw: while 2 > 1 { break; } //~ WARN label name `'lw` shadows a label name that is already in scope
'fw: for _ in 0..10 { break; }
'fw: while 2 > 1 { break; } //~ WARN label name `'fw` shadows a label name that is already in scope
'wf: while 2 > 1 { break; }
'wf: for _ in 0..10 { break; } //~ WARN label name `'wf` shadows a label name that is already in scope
'tl: while let Some(_) = None::<i32> { break; }
'tl: loop { break; } //~ WARN label name `'tl` shadows a label name that is already in scope
'lt: loop { break; }
'lt: while let Some(_) = None::<i32> { break; }
//~^ WARN label name `'lt` shadows a label name that is already in scope
'bl: {}
'bl: {} //~ WARN label name `'bl` shadows a label name that is already in scope
}
// Note however that it is okay for the same label to be reused in
// different methods of one impl, as illustrated here.
struct S;
impl S {
fn m1(&self) { 'okay: loop { break 'okay; } }
fn m2(&self) { 'okay: loop { break 'okay; } }
fn m3(&self) { 'okay: { break 'okay; } }
fn m4(&self) { 'okay: { break 'okay; } }
}
pub fn main() {
let s = S;
s.m1();
s.m2();
s.m3();
s.m4();
foo();
}

View file

@ -1,74 +0,0 @@
warning: label name `'fl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:9:5
|
LL | 'fl: for _ in 0..10 { break; }
| --- first declared here
LL | 'fl: loop { break; }
| ^^^ label `'fl` already in scope
warning: label name `'lf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:12:5
|
LL | 'lf: loop { break; }
| --- first declared here
LL | 'lf: for _ in 0..10 { break; }
| ^^^ label `'lf` already in scope
warning: label name `'wl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:14:5
|
LL | 'wl: while 2 > 1 { break; }
| --- first declared here
LL | 'wl: loop { break; }
| ^^^ label `'wl` already in scope
warning: label name `'lw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:16:5
|
LL | 'lw: loop { break; }
| --- first declared here
LL | 'lw: while 2 > 1 { break; }
| ^^^ label `'lw` already in scope
warning: label name `'fw` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:18:5
|
LL | 'fw: for _ in 0..10 { break; }
| --- first declared here
LL | 'fw: while 2 > 1 { break; }
| ^^^ label `'fw` already in scope
warning: label name `'wf` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:20:5
|
LL | 'wf: while 2 > 1 { break; }
| --- first declared here
LL | 'wf: for _ in 0..10 { break; }
| ^^^ label `'wf` already in scope
warning: label name `'tl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:22:5
|
LL | 'tl: while let Some(_) = None::<i32> { break; }
| --- first declared here
LL | 'tl: loop { break; }
| ^^^ label `'tl` already in scope
warning: label name `'lt` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:24:5
|
LL | 'lt: loop { break; }
| --- first declared here
LL | 'lt: while let Some(_) = None::<i32> { break; }
| ^^^ label `'lt` already in scope
warning: label name `'bl` shadows a label name that is already in scope
--> $DIR/loops-reject-duplicate-labels.rs:27:5
|
LL | 'bl: {}
| --- first declared here
LL | 'bl: {}
| ^^^ label `'bl` already in scope
warning: 9 warnings emitted

View file

@ -1,109 +0,0 @@
// Issue #21633: reject duplicate loop labels in function bodies.
// This is testing interaction between lifetime-params and labels.
// check-pass
#![allow(dead_code, unused_variables)]
fn foo() {
fn foo<'a>() {
'a: loop { break 'a; }
//~^ WARN label name `'a` shadows a lifetime name that is already in scope
}
struct Struct<'b, 'c> { _f: &'b i8, _g: &'c i8 }
enum Enum<'d, 'e> { A(&'d i8), B(&'e i8) }
impl<'d, 'e> Struct<'d, 'e> {
fn meth_okay() {
'a: loop { break 'a; }
'b: loop { break 'b; }
'c: loop { break 'c; }
}
}
impl <'d, 'e> Enum<'d, 'e> {
fn meth_okay() {
'a: loop { break 'a; }
'b: loop { break 'b; }
'c: loop { break 'c; }
}
}
impl<'bad, 'c> Struct<'bad, 'c> {
fn meth_bad(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
impl<'b, 'bad> Struct<'b, 'bad> {
fn meth_bad2(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
impl<'b, 'c> Struct<'b, 'c> {
fn meth_bad3<'bad>(x: &'bad i8) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
impl <'bad, 'e> Enum<'bad, 'e> {
fn meth_bad(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
impl <'d, 'bad> Enum<'d, 'bad> {
fn meth_bad2(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
impl <'d, 'e> Enum<'d, 'e> {
fn meth_bad3<'bad>(x: &'bad i8) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
fn meth_bad4<'a,'bad>(x: &'bad i8) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
trait HasDefaultMethod1<'bad> {
fn meth_okay() {
'c: loop { break 'c; }
}
fn meth_bad(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
trait HasDefaultMethod2<'a,'bad> {
fn meth_bad(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
trait HasDefaultMethod3<'a,'b> {
fn meth_bad<'bad>(&self) {
'bad: loop { break 'bad; }
//~^ WARN label name `'bad` shadows a lifetime name that is already in scope
}
}
}
pub fn main() {
foo();
}

View file

@ -1,104 +0,0 @@
warning: label name `'a` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:10:9
|
LL | fn foo<'a>() {
| -- first declared here
LL | 'a: loop { break 'a; }
| ^^ lifetime `'a` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:35:13
|
LL | impl<'bad, 'c> Struct<'bad, 'c> {
| ---- first declared here
LL | fn meth_bad(&self) {
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:42:13
|
LL | impl<'b, 'bad> Struct<'b, 'bad> {
| ---- first declared here
LL | fn meth_bad2(&self) {
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:49:13
|
LL | fn meth_bad3<'bad>(x: &'bad i8) {
| ---- first declared here
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:54:13
|
LL | fn meth_bad4<'a,'bad>(x: &'a i8, y: &'bad i8) {
| ---- first declared here
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:61:13
|
LL | impl <'bad, 'e> Enum<'bad, 'e> {
| ---- first declared here
LL | fn meth_bad(&self) {
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:67:13
|
LL | impl <'d, 'bad> Enum<'d, 'bad> {
| ---- first declared here
LL | fn meth_bad2(&self) {
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:73:13
|
LL | fn meth_bad3<'bad>(x: &'bad i8) {
| ---- first declared here
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:78:13
|
LL | fn meth_bad4<'a,'bad>(x: &'bad i8) {
| ---- first declared here
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:88:13
|
LL | trait HasDefaultMethod1<'bad> {
| ---- first declared here
...
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:94:13
|
LL | trait HasDefaultMethod2<'a,'bad> {
| ---- first declared here
LL | fn meth_bad(&self) {
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: label name `'bad` shadows a lifetime name that is already in scope
--> $DIR/loops-reject-labels-shadowing-lifetimes.rs:100:13
|
LL | fn meth_bad<'bad>(&self) {
| ---- first declared here
LL | 'bad: loop { break 'bad; }
| ^^^^ lifetime `'bad` already in scope
warning: 12 warnings emitted

View file

@ -1,36 +0,0 @@
// check-pass
#![feature(label_break_value)]
#![allow(dead_code, unused_variables)]
// Issue #21633: reject duplicate loop labels and block labels in function bodies.
//
// Test rejection of lifetimes in *expressions* that shadow labels.
fn foo() {
// Reusing lifetime `'a` in function item is okay.
fn foo<'a>(x: &'a i8) -> i8 { *x }
// So is reusing `'a` in struct item
struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} }
// and a method item
struct S2; impl S2 { fn m<'a>(&self) {} }
let z = 3_i8;
'a: loop {
let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
//~^ WARN lifetime name `'a` shadows a label name that is already in scope
assert_eq!((*b)(&z), z);
break 'a;
}
'b: {
let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
//~^ WARN lifetime name `'b` shadows a label name that is already in scope
break 'b;
}
}
pub fn main() {
foo();
}

View file

@ -1,18 +0,0 @@
warning: lifetime name `'a` shadows a label name that is already in scope
--> $DIR/loops-reject-lifetime-shadowing-label.rs:21:55
|
LL | 'a: loop {
| -- first declared here
LL | let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
| ^^ label `'a` already in scope
warning: lifetime name `'b` shadows a label name that is already in scope
--> $DIR/loops-reject-lifetime-shadowing-label.rs:28:55
|
LL | 'b: {
| -- first declared here
LL | let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
| ^^ label `'b` already in scope
warning: 2 warnings emitted

View file

@ -18,7 +18,7 @@ macro_rules! br {
}
macro_rules! br2 {
($b:lifetime) => {
'b: loop { //~ WARNING `'b` shadows a label name that is already in scope
'b: loop {
break $b; // this $b should refer to the outer loop.
}
}

View file

@ -1,15 +0,0 @@
warning: label name `'b` shadows a label name that is already in scope
--> $DIR/macro-lifetime-used-with-labels.rs:21:9
|
LL | 'b: loop {
| ^^ label `'b` already in scope
...
LL | 'b: loop {
| -- first declared here
LL | br2!('b);
| -------- in this macro invocation
|
= note: this warning originates in the macro `br2` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted

View file

@ -1,5 +1,6 @@
struct Foo<'a, 'a> { //~ ERROR lifetime name `'a` declared twice
x: &'a isize
struct Foo<'a, 'a> {
//~^ ERROR the name `'a` is already used for a generic parameter
x: &'a isize,
}
fn main() {}

View file

@ -1,11 +1,11 @@
error[E0263]: lifetime name `'a` declared twice in the same scope
error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters
--> $DIR/regions-name-duplicated.rs:1:16
|
LL | struct Foo<'a, 'a> {
| -- ^^ declared twice
| -- ^^ already used
| |
| previous declaration here
| first use of `'a`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0263`.
For more information about this error, try `rustc --explain E0403`.