Rollup merge of #61856 - c410-f3r:attrs-fn, r=matthewjasper
Lint attributes on function arguments Fixes #61238. cc #60406
This commit is contained in:
commit
a4cd2ecab2
28 changed files with 596 additions and 302 deletions
|
@ -210,6 +210,10 @@ pub trait Visitor<'v> : Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_arg(&mut self, arg: &'v Arg) {
|
||||||
|
walk_arg(self, arg)
|
||||||
|
}
|
||||||
|
|
||||||
/// Visits the top-level item and (optionally) nested items / impl items. See
|
/// Visits the top-level item and (optionally) nested items / impl items. See
|
||||||
/// `visit_nested_item` for details.
|
/// `visit_nested_item` for details.
|
||||||
fn visit_item(&mut self, i: &'v Item) {
|
fn visit_item(&mut self, i: &'v Item) {
|
||||||
|
@ -396,10 +400,7 @@ pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
|
pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
|
||||||
for argument in &body.arguments {
|
walk_list!(visitor, visit_arg, &body.arguments);
|
||||||
visitor.visit_id(argument.hir_id);
|
|
||||||
visitor.visit_pat(&argument.pat);
|
|
||||||
}
|
|
||||||
visitor.visit_expr(&body.value);
|
visitor.visit_expr(&body.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,6 +453,12 @@ pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
|
||||||
visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
|
visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_arg<'v, V: Visitor<'v>>(visitor: &mut V, arg: &'v Arg) {
|
||||||
|
visitor.visit_id(arg.hir_id);
|
||||||
|
visitor.visit_pat(&arg.pat);
|
||||||
|
walk_list!(visitor, visit_attribute, &arg.attrs);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
|
||||||
visitor.visit_vis(&item.vis);
|
visitor.visit_vis(&item.vis);
|
||||||
visitor.visit_ident(item.ident);
|
visitor.visit_ident(item.ident);
|
||||||
|
|
|
@ -2461,8 +2461,10 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
|
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
|
||||||
hir::Arg {
|
hir::Arg {
|
||||||
|
attrs: self.lower_attrs(&arg.attrs),
|
||||||
hir_id: self.lower_node_id(arg.id),
|
hir_id: self.lower_node_id(arg.id),
|
||||||
pat: self.lower_pat(&arg.pat),
|
pat: self.lower_pat(&arg.pat),
|
||||||
|
span: arg.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3279,19 +3281,29 @@ impl<'a> LoweringContext<'a> {
|
||||||
//
|
//
|
||||||
// If this is the simple case, this argument will end up being the same as the
|
// If this is the simple case, this argument will end up being the same as the
|
||||||
// original argument, but with a different pattern id.
|
// original argument, but with a different pattern id.
|
||||||
|
let mut stmt_attrs = ThinVec::new();
|
||||||
|
stmt_attrs.extend(argument.attrs.iter().cloned());
|
||||||
let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
|
let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
|
||||||
let new_argument = hir::Arg {
|
let new_argument = hir::Arg {
|
||||||
|
attrs: argument.attrs,
|
||||||
hir_id: argument.hir_id,
|
hir_id: argument.hir_id,
|
||||||
pat: new_argument_pat,
|
pat: new_argument_pat,
|
||||||
|
span: argument.span,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if is_simple_argument {
|
if is_simple_argument {
|
||||||
// If this is the simple case, then we only insert one statement that is
|
// If this is the simple case, then we only insert one statement that is
|
||||||
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
|
// `let <pat> = <pat>;`. We re-use the original argument's pattern so that
|
||||||
// `HirId`s are densely assigned.
|
// `HirId`s are densely assigned.
|
||||||
let expr = this.expr_ident(desugared_span, ident, new_argument_id);
|
let expr = this.expr_ident(desugared_span, ident, new_argument_id);
|
||||||
let stmt = this.stmt_let_pat(
|
let stmt = this.stmt_let_pat(
|
||||||
desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn);
|
stmt_attrs,
|
||||||
|
desugared_span,
|
||||||
|
Some(P(expr)),
|
||||||
|
argument.pat,
|
||||||
|
hir::LocalSource::AsyncFn
|
||||||
|
);
|
||||||
statements.push(stmt);
|
statements.push(stmt);
|
||||||
} else {
|
} else {
|
||||||
// If this is not the simple case, then we construct two statements:
|
// If this is not the simple case, then we construct two statements:
|
||||||
|
@ -3313,14 +3325,23 @@ impl<'a> LoweringContext<'a> {
|
||||||
desugared_span, ident, hir::BindingAnnotation::Mutable);
|
desugared_span, ident, hir::BindingAnnotation::Mutable);
|
||||||
let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
|
let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
|
||||||
let move_stmt = this.stmt_let_pat(
|
let move_stmt = this.stmt_let_pat(
|
||||||
desugared_span, Some(P(move_expr)), move_pat, hir::LocalSource::AsyncFn);
|
ThinVec::new(),
|
||||||
|
desugared_span,
|
||||||
|
Some(P(move_expr)),
|
||||||
|
move_pat,
|
||||||
|
hir::LocalSource::AsyncFn
|
||||||
|
);
|
||||||
|
|
||||||
// Construct the `let <pat> = __argN;` statement. We re-use the original
|
// Construct the `let <pat> = __argN;` statement. We re-use the original
|
||||||
// argument's pattern so that `HirId`s are densely assigned.
|
// argument's pattern so that `HirId`s are densely assigned.
|
||||||
let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
|
let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
|
||||||
let pattern_stmt = this.stmt_let_pat(
|
let pattern_stmt = this.stmt_let_pat(
|
||||||
desugared_span, Some(P(pattern_expr)), argument.pat,
|
stmt_attrs,
|
||||||
hir::LocalSource::AsyncFn);
|
desugared_span,
|
||||||
|
Some(P(pattern_expr)),
|
||||||
|
argument.pat,
|
||||||
|
hir::LocalSource::AsyncFn
|
||||||
|
);
|
||||||
|
|
||||||
statements.push(move_stmt);
|
statements.push(move_stmt);
|
||||||
statements.push(pattern_stmt);
|
statements.push(pattern_stmt);
|
||||||
|
@ -5030,6 +5051,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
// `let mut __next`
|
// `let mut __next`
|
||||||
let next_let = self.stmt_let_pat(
|
let next_let = self.stmt_let_pat(
|
||||||
|
ThinVec::new(),
|
||||||
desugared_span,
|
desugared_span,
|
||||||
None,
|
None,
|
||||||
next_pat,
|
next_pat,
|
||||||
|
@ -5039,6 +5061,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
// `let <pat> = __next`
|
// `let <pat> = __next`
|
||||||
let pat = self.lower_pat(pat);
|
let pat = self.lower_pat(pat);
|
||||||
let pat_let = self.stmt_let_pat(
|
let pat_let = self.stmt_let_pat(
|
||||||
|
ThinVec::new(),
|
||||||
head_sp,
|
head_sp,
|
||||||
Some(next_expr),
|
Some(next_expr),
|
||||||
pat,
|
pat,
|
||||||
|
@ -5533,19 +5556,20 @@ impl<'a> LoweringContext<'a> {
|
||||||
|
|
||||||
fn stmt_let_pat(
|
fn stmt_let_pat(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
attrs: ThinVec<Attribute>,
|
||||||
span: Span,
|
span: Span,
|
||||||
init: Option<P<hir::Expr>>,
|
init: Option<P<hir::Expr>>,
|
||||||
pat: P<hir::Pat>,
|
pat: P<hir::Pat>,
|
||||||
source: hir::LocalSource,
|
source: hir::LocalSource,
|
||||||
) -> hir::Stmt {
|
) -> hir::Stmt {
|
||||||
let local = hir::Local {
|
let local = hir::Local {
|
||||||
pat,
|
attrs,
|
||||||
ty: None,
|
|
||||||
init,
|
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
span,
|
init,
|
||||||
|
pat,
|
||||||
source,
|
source,
|
||||||
attrs: ThinVec::new()
|
span,
|
||||||
|
ty: None,
|
||||||
};
|
};
|
||||||
self.stmt(span, hir::StmtKind::Local(P(local)))
|
self.stmt(span, hir::StmtKind::Local(P(local)))
|
||||||
}
|
}
|
||||||
|
@ -5959,6 +5983,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
hir::BindingAnnotation::Mutable,
|
hir::BindingAnnotation::Mutable,
|
||||||
);
|
);
|
||||||
let pinned_let = self.stmt_let_pat(
|
let pinned_let = self.stmt_let_pat(
|
||||||
|
ThinVec::new(),
|
||||||
span,
|
span,
|
||||||
Some(expr),
|
Some(expr),
|
||||||
pinned_pat,
|
pinned_pat,
|
||||||
|
|
|
@ -363,6 +363,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||||
self.currently_in_body = prev_in_body;
|
self.currently_in_body = prev_in_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_arg(&mut self, arg: &'hir Arg) {
|
||||||
|
let node = Node::Arg(arg);
|
||||||
|
self.insert(arg.pat.span, arg.hir_id, node);
|
||||||
|
self.with_parent(arg.hir_id, |this| {
|
||||||
|
intravisit::walk_arg(this, arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, i: &'hir Item) {
|
fn visit_item(&mut self, i: &'hir Item) {
|
||||||
debug!("visit_item: {:?}", i);
|
debug!("visit_item: {:?}", i);
|
||||||
debug_assert_eq!(i.hir_id.owner,
|
debug_assert_eq!(i.hir_id.owner,
|
||||||
|
|
|
@ -360,6 +360,7 @@ impl<'hir> Map<'hir> {
|
||||||
Node::Pat(_) |
|
Node::Pat(_) |
|
||||||
Node::Binding(_) |
|
Node::Binding(_) |
|
||||||
Node::Local(_) |
|
Node::Local(_) |
|
||||||
|
Node::Arg(_) |
|
||||||
Node::Arm(_) |
|
Node::Arm(_) |
|
||||||
Node::Lifetime(_) |
|
Node::Lifetime(_) |
|
||||||
Node::Visibility(_) |
|
Node::Visibility(_) |
|
||||||
|
@ -932,6 +933,7 @@ impl<'hir> Map<'hir> {
|
||||||
pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
|
pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] {
|
||||||
self.read(id); // reveals attributes on the node
|
self.read(id); // reveals attributes on the node
|
||||||
let attrs = match self.find_entry(id).map(|entry| entry.node) {
|
let attrs = match self.find_entry(id).map(|entry| entry.node) {
|
||||||
|
Some(Node::Arg(a)) => Some(&a.attrs[..]),
|
||||||
Some(Node::Local(l)) => Some(&l.attrs[..]),
|
Some(Node::Local(l)) => Some(&l.attrs[..]),
|
||||||
Some(Node::Item(i)) => Some(&i.attrs[..]),
|
Some(Node::Item(i)) => Some(&i.attrs[..]),
|
||||||
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
|
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
|
||||||
|
@ -995,6 +997,7 @@ impl<'hir> Map<'hir> {
|
||||||
pub fn span(&self, hir_id: HirId) -> Span {
|
pub fn span(&self, hir_id: HirId) -> Span {
|
||||||
self.read(hir_id); // reveals span from node
|
self.read(hir_id); // reveals span from node
|
||||||
match self.find_entry(hir_id).map(|entry| entry.node) {
|
match self.find_entry(hir_id).map(|entry| entry.node) {
|
||||||
|
Some(Node::Arg(arg)) => arg.span,
|
||||||
Some(Node::Item(item)) => item.span,
|
Some(Node::Item(item)) => item.span,
|
||||||
Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
|
Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
|
||||||
Some(Node::TraitItem(trait_method)) => trait_method.span,
|
Some(Node::TraitItem(trait_method)) => trait_method.span,
|
||||||
|
@ -1197,6 +1200,7 @@ impl<'hir> print::PpAnn for Map<'hir> {
|
||||||
impl<'a> print::State<'a> {
|
impl<'a> print::State<'a> {
|
||||||
pub fn print_node(&mut self, node: Node<'_>) {
|
pub fn print_node(&mut self, node: Node<'_>) {
|
||||||
match node {
|
match node {
|
||||||
|
Node::Arg(a) => self.print_arg(&a),
|
||||||
Node::Item(a) => self.print_item(&a),
|
Node::Item(a) => self.print_item(&a),
|
||||||
Node::ForeignItem(a) => self.print_foreign_item(&a),
|
Node::ForeignItem(a) => self.print_foreign_item(&a),
|
||||||
Node::TraitItem(a) => self.print_trait_item(a),
|
Node::TraitItem(a) => self.print_trait_item(a),
|
||||||
|
@ -1338,6 +1342,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
|
||||||
Some(Node::Pat(_)) => {
|
Some(Node::Pat(_)) => {
|
||||||
format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
|
format!("pat {}{}", map.hir_to_pretty_string(id), id_str)
|
||||||
}
|
}
|
||||||
|
Some(Node::Arg(_)) => {
|
||||||
|
format!("arg {}{}", map.hir_to_pretty_string(id), id_str)
|
||||||
|
}
|
||||||
Some(Node::Arm(_)) => {
|
Some(Node::Arm(_)) => {
|
||||||
format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
|
format!("arm {}{}", map.hir_to_pretty_string(id), id_str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2010,8 +2010,10 @@ pub struct InlineAsm {
|
||||||
/// Represents an argument in a function header.
|
/// Represents an argument in a function header.
|
||||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||||
pub struct Arg {
|
pub struct Arg {
|
||||||
pub pat: P<Pat>,
|
pub attrs: HirVec<Attribute>,
|
||||||
pub hir_id: HirId,
|
pub hir_id: HirId,
|
||||||
|
pub pat: P<Pat>,
|
||||||
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the header (not the body) of a function declaration.
|
/// Represents the header (not the body) of a function declaration.
|
||||||
|
@ -2701,6 +2703,7 @@ impl CodegenFnAttrs {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum Node<'hir> {
|
pub enum Node<'hir> {
|
||||||
|
Arg(&'hir Arg),
|
||||||
Item(&'hir Item),
|
Item(&'hir Item),
|
||||||
ForeignItem(&'hir ForeignItem),
|
ForeignItem(&'hir ForeignItem),
|
||||||
TraitItem(&'hir TraitItem),
|
TraitItem(&'hir TraitItem),
|
||||||
|
|
|
@ -1767,6 +1767,11 @@ impl<'a> State<'a> {
|
||||||
self.ann.post(self, AnnNode::Pat(pat))
|
self.ann.post(self, AnnNode::Pat(pat))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_arg(&mut self, arg: &hir::Arg) {
|
||||||
|
self.print_outer_attributes(&arg.attrs);
|
||||||
|
self.print_pat(&arg.pat);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_arm(&mut self, arm: &hir::Arm) {
|
pub fn print_arm(&mut self, arm: &hir::Arm) {
|
||||||
// I have no idea why this check is necessary, but here it
|
// I have no idea why this check is necessary, but here it
|
||||||
// is :(
|
// is :(
|
||||||
|
|
|
@ -966,6 +966,13 @@ for LateContextAndPass<'a, 'tcx, T> {
|
||||||
self.context.tables = old_tables;
|
self.context.tables = old_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
|
||||||
|
self.with_lint_attrs(arg.hir_id, &arg.attrs, |cx| {
|
||||||
|
lint_callback!(cx, check_arg, arg);
|
||||||
|
hir_visit::walk_arg(cx, arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_body(&mut self, body: &'tcx hir::Body) {
|
fn visit_body(&mut self, body: &'tcx hir::Body) {
|
||||||
lint_callback!(self, check_body, body);
|
lint_callback!(self, check_body, body);
|
||||||
hir_visit::walk_body(self, body);
|
hir_visit::walk_body(self, body);
|
||||||
|
@ -1156,6 +1163,13 @@ for LateContextAndPass<'a, 'tcx, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
|
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
|
||||||
|
fn visit_arg(&mut self, arg: &'a ast::Arg) {
|
||||||
|
self.with_lint_attrs(arg.id, &arg.attrs, |cx| {
|
||||||
|
run_early_pass!(cx, check_arg, arg);
|
||||||
|
ast_visit::walk_arg(cx, arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, it: &'a ast::Item) {
|
fn visit_item(&mut self, it: &'a ast::Item) {
|
||||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||||
run_early_pass!(cx, check_item, it);
|
run_early_pass!(cx, check_item, it);
|
||||||
|
|
|
@ -206,6 +206,7 @@ macro_rules! declare_lint_pass {
|
||||||
macro_rules! late_lint_methods {
|
macro_rules! late_lint_methods {
|
||||||
($macro:path, $args:tt, [$hir:tt]) => (
|
($macro:path, $args:tt, [$hir:tt]) => (
|
||||||
$macro!($args, [$hir], [
|
$macro!($args, [$hir], [
|
||||||
|
fn check_arg(a: &$hir hir::Arg);
|
||||||
fn check_body(a: &$hir hir::Body);
|
fn check_body(a: &$hir hir::Body);
|
||||||
fn check_body_post(a: &$hir hir::Body);
|
fn check_body_post(a: &$hir hir::Body);
|
||||||
fn check_name(a: Span, b: ast::Name);
|
fn check_name(a: Span, b: ast::Name);
|
||||||
|
@ -358,6 +359,7 @@ macro_rules! declare_combined_late_lint_pass {
|
||||||
macro_rules! early_lint_methods {
|
macro_rules! early_lint_methods {
|
||||||
($macro:path, $args:tt) => (
|
($macro:path, $args:tt) => (
|
||||||
$macro!($args, [
|
$macro!($args, [
|
||||||
|
fn check_arg(a: &ast::Arg);
|
||||||
fn check_ident(a: ast::Ident);
|
fn check_ident(a: ast::Ident);
|
||||||
fn check_crate(a: &ast::Crate);
|
fn check_crate(a: &ast::Crate);
|
||||||
fn check_crate_post(a: &ast::Crate);
|
fn check_crate_post(a: &ast::Crate);
|
||||||
|
@ -495,8 +497,6 @@ pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync +
|
||||||
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
|
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
|
||||||
+ sync::Sync + 'static>;
|
+ sync::Sync + 'static>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Identifies a lint known to the compiler.
|
/// Identifies a lint known to the compiler.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct LintId {
|
pub struct LintId {
|
||||||
|
@ -812,6 +812,12 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
|
||||||
intravisit::NestedVisitorMap::All(&self.tcx.hir())
|
intravisit::NestedVisitorMap::All(&self.tcx.hir())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_arg(&mut self, arg: &'tcx hir::Arg) {
|
||||||
|
self.with_lint_attrs(arg.hir_id, &arg.attrs, |builder| {
|
||||||
|
intravisit::walk_arg(builder, arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, it: &'tcx hir::Item) {
|
fn visit_item(&mut self, it: &'tcx hir::Item) {
|
||||||
self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
|
self.with_lint_attrs(it.hir_id, &it.attrs, |builder| {
|
||||||
intravisit::walk_item(builder, it);
|
intravisit::walk_item(builder, it);
|
||||||
|
|
|
@ -121,7 +121,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
|
||||||
self_arg = None;
|
self_arg = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
|
ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&arg), self_arg)
|
||||||
});
|
});
|
||||||
|
|
||||||
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
||||||
|
@ -511,7 +511,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// the main entry point for building MIR for a function
|
/// the main entry point for building MIR for a function
|
||||||
|
|
||||||
struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Pat>, Option<ImplicitSelfKind>);
|
struct ArgInfo<'tcx>(Ty<'tcx>, Option<Span>, Option<&'tcx hir::Arg>, Option<ImplicitSelfKind>);
|
||||||
|
|
||||||
fn construct_fn<'a, 'tcx, A>(
|
fn construct_fn<'a, 'tcx, A>(
|
||||||
hir: Cx<'a, 'tcx>,
|
hir: Cx<'a, 'tcx>,
|
||||||
|
@ -782,13 +782,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
-> BlockAnd<()>
|
-> BlockAnd<()>
|
||||||
{
|
{
|
||||||
// Allocate locals for the function arguments
|
// Allocate locals for the function arguments
|
||||||
for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
|
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
|
||||||
// If this is a simple binding pattern, give the local a name for
|
// If this is a simple binding pattern, give the local a name for
|
||||||
// debuginfo and so that error reporting knows that this is a user
|
// debuginfo and so that error reporting knows that this is a user
|
||||||
// variable. For any other pattern the pattern introduces new
|
// variable. For any other pattern the pattern introduces new
|
||||||
// variables which will be named instead.
|
// variables which will be named instead.
|
||||||
let (name, span) = if let Some(pat) = pattern {
|
let (name, span) = if let Some(arg) = arg_opt {
|
||||||
(pat.simple_ident().map(|ident| ident.name), pat.span)
|
(arg.pat.simple_ident().map(|ident| ident.name), arg.pat.span)
|
||||||
} else {
|
} else {
|
||||||
(None, self.fn_span)
|
(None, self.fn_span)
|
||||||
};
|
};
|
||||||
|
@ -813,18 +813,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Function arguments always get the first Local indices after the return place
|
// Function arguments always get the first Local indices after the return place
|
||||||
let local = Local::new(index + 1);
|
let local = Local::new(index + 1);
|
||||||
let place = Place::from(local);
|
let place = Place::from(local);
|
||||||
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
|
let &ArgInfo(ty, opt_ty_info, arg_opt, ref self_binding) = arg_info;
|
||||||
|
|
||||||
// Make sure we drop (parts of) the argument even when not matched on.
|
// Make sure we drop (parts of) the argument even when not matched on.
|
||||||
self.schedule_drop(
|
self.schedule_drop(
|
||||||
pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
|
arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span),
|
||||||
argument_scope, local, ty, DropKind::Value,
|
argument_scope, local, ty, DropKind::Value,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(pattern) = pattern {
|
if let Some(arg) = arg_opt {
|
||||||
let pattern = self.hir.pattern_from_hir(pattern);
|
let pattern = self.hir.pattern_from_hir(&arg.pat);
|
||||||
|
let original_source_scope = self.source_scope;
|
||||||
let span = pattern.span;
|
let span = pattern.span;
|
||||||
|
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
|
||||||
match *pattern.kind {
|
match *pattern.kind {
|
||||||
// Don't introduce extra copies for simple bindings
|
// Don't introduce extra copies for simple bindings
|
||||||
PatternKind::Binding {
|
PatternKind::Binding {
|
||||||
|
@ -835,6 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
self.local_decls[local].mutability = mutability;
|
self.local_decls[local].mutability = mutability;
|
||||||
|
self.local_decls[local].source_info.scope = self.source_scope;
|
||||||
self.local_decls[local].is_user_variable =
|
self.local_decls[local].is_user_variable =
|
||||||
if let Some(kind) = self_binding {
|
if let Some(kind) = self_binding {
|
||||||
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
|
Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind)))
|
||||||
|
@ -860,6 +862,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
unpack!(block = self.place_into_pattern(block, pattern, &place, false));
|
unpack!(block = self.place_into_pattern(block, pattern, &place, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.source_scope = original_source_scope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,6 +875,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
self.into(&Place::RETURN_PLACE, block, body)
|
self.into(&Place::RETURN_PLACE, block, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_correct_source_scope_for_arg(
|
||||||
|
&mut self,
|
||||||
|
arg_hir_id: hir::HirId,
|
||||||
|
original_source_scope: SourceScope,
|
||||||
|
pattern_span: Span
|
||||||
|
) {
|
||||||
|
let tcx = self.hir.tcx();
|
||||||
|
let current_root = tcx.maybe_lint_level_root_bounded(
|
||||||
|
arg_hir_id,
|
||||||
|
self.hir.root_lint_level
|
||||||
|
);
|
||||||
|
let parent_root = tcx.maybe_lint_level_root_bounded(
|
||||||
|
self.source_scope_local_data[original_source_scope].lint_root,
|
||||||
|
self.hir.root_lint_level,
|
||||||
|
);
|
||||||
|
if current_root != parent_root {
|
||||||
|
self.source_scope = self.new_source_scope(
|
||||||
|
pattern_span,
|
||||||
|
LintLevel::Explicit(current_root),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
||||||
match self.unit_temp {
|
match self.unit_temp {
|
||||||
Some(ref tmp) => tmp.clone(),
|
Some(ref tmp) => tmp.clone(),
|
||||||
|
|
|
@ -94,6 +94,11 @@ impl<'k> StatCollector<'k> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
||||||
|
fn visit_arg(&mut self, arg: &'v hir::Arg) {
|
||||||
|
self.record("Arg", Id::Node(arg.hir_id), arg);
|
||||||
|
hir_visit::walk_arg(self, arg)
|
||||||
|
}
|
||||||
|
|
||||||
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
|
fn nested_visit_map<'this>(&'this mut self) -> hir_visit::NestedVisitorMap<'this, 'v> {
|
||||||
panic!("visit_nested_xxx must be manually implemented in this visitor")
|
panic!("visit_nested_xxx must be manually implemented in this visitor")
|
||||||
}
|
}
|
||||||
|
|
|
@ -555,21 +555,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
if let PatKind::Binding(..) = inner.node {
|
if let PatKind::Binding(..) = inner.node {
|
||||||
let parent_id = tcx.hir().get_parent_node(pat.hir_id);
|
let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id);
|
||||||
let parent = tcx.hir().get(parent_id);
|
let binding_parent = tcx.hir().get(binding_parent_id);
|
||||||
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
|
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
|
||||||
match parent {
|
match binding_parent {
|
||||||
hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
|
hir::Node::Arg(hir::Arg { span, .. }) => {
|
||||||
hir::Node::ForeignItem(hir::ForeignItem {
|
|
||||||
node: hir::ForeignItemKind::Fn(..), ..
|
|
||||||
}) |
|
|
||||||
hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
|
|
||||||
hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
|
|
||||||
// this pat is likely an argument
|
|
||||||
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
|
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
|
||||||
// FIXME: turn into structured suggestion, will need a span that also
|
err.span_suggestion(
|
||||||
// includes the the arg's type.
|
*span,
|
||||||
err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
|
&format!("did you mean `{}`", snippet),
|
||||||
|
format!(" &{}", expected),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::Node::Arm(_) |
|
hir::Node::Arm(_) |
|
||||||
|
|
|
@ -235,40 +235,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
expr: &hir::Expr,
|
expr: &hir::Expr,
|
||||||
) -> Option<(Span, &'static str, String)> {
|
) -> Option<(Span, &'static str, String)> {
|
||||||
if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node {
|
let path = match expr.node {
|
||||||
if let hir::def::Res::Local(id) = path.res {
|
hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => path,
|
||||||
let parent = self.tcx.hir().get_parent_node(id);
|
_ => return None
|
||||||
if let Some(Node::Expr(hir::Expr {
|
};
|
||||||
hir_id,
|
|
||||||
node: hir::ExprKind::Closure(_, decl, ..),
|
let local_id = match path.res {
|
||||||
..
|
hir::def::Res::Local(id) => id,
|
||||||
})) = self.tcx.hir().find(parent) {
|
_ => return None
|
||||||
let parent = self.tcx.hir().get_parent_node(*hir_id);
|
};
|
||||||
if let (Some(Node::Expr(hir::Expr {
|
|
||||||
node: hir::ExprKind::MethodCall(path, span, expr),
|
let local_parent = self.tcx.hir().get_parent_node(local_id);
|
||||||
..
|
let arg_hir_id = match self.tcx.hir().find(local_parent) {
|
||||||
})), 1) = (self.tcx.hir().find(parent), decl.inputs.len()) {
|
Some(Node::Arg(hir::Arg { hir_id, .. })) => hir_id,
|
||||||
let self_ty = self.tables.borrow().node_type(expr[0].hir_id);
|
_ => return None
|
||||||
let self_ty = format!("{:?}", self_ty);
|
};
|
||||||
let name = path.ident.as_str();
|
|
||||||
let is_as_ref_able = (
|
let arg_parent = self.tcx.hir().get_parent_node(*arg_hir_id);
|
||||||
self_ty.starts_with("&std::option::Option") ||
|
let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(arg_parent) {
|
||||||
self_ty.starts_with("&std::result::Result") ||
|
Some(Node::Expr(
|
||||||
self_ty.starts_with("std::option::Option") ||
|
hir::Expr { hir_id, node: hir::ExprKind::Closure(_, decl, ..), .. }
|
||||||
self_ty.starts_with("std::result::Result")
|
)) => (hir_id, decl),
|
||||||
) && (name == "map" || name == "and_then");
|
_ => return None
|
||||||
match (is_as_ref_able, self.sess().source_map().span_to_snippet(*span)) {
|
};
|
||||||
(true, Ok(src)) => {
|
|
||||||
return Some((*span, "consider using `as_ref` instead",
|
let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id);
|
||||||
format!("as_ref().{}", src)));
|
let hir = self.tcx.hir().find(expr_parent);
|
||||||
},
|
let closure_params_len = closure_fn_decl.inputs.len();
|
||||||
_ => ()
|
let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
|
||||||
}
|
(Some(Node::Expr(
|
||||||
}
|
hir::Expr { node: hir::ExprKind::MethodCall(path, span, expr), .. }
|
||||||
}
|
)), 1) => (path, span, expr),
|
||||||
}
|
_ => return None
|
||||||
|
};
|
||||||
|
|
||||||
|
let self_ty = self.tables.borrow().node_type(method_expr[0].hir_id);
|
||||||
|
let self_ty = format!("{:?}", self_ty);
|
||||||
|
let name = method_path.ident.as_str();
|
||||||
|
let is_as_ref_able = (
|
||||||
|
self_ty.starts_with("&std::option::Option") ||
|
||||||
|
self_ty.starts_with("&std::result::Result") ||
|
||||||
|
self_ty.starts_with("std::option::Option") ||
|
||||||
|
self_ty.starts_with("std::result::Result")
|
||||||
|
) && (name == "map" || name == "and_then");
|
||||||
|
match (is_as_ref_able, self.sess().source_map().span_to_snippet(*method_span)) {
|
||||||
|
(true, Ok(src)) => {
|
||||||
|
let suggestion = format!("as_ref().{}", src);
|
||||||
|
Some((*method_span, "consider using `as_ref` instead", suggestion))
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn is_hir_id_from_struct_pattern_shorthand_field(
|
crate fn is_hir_id_from_struct_pattern_shorthand_field(
|
||||||
|
|
|
@ -1796,6 +1796,7 @@ pub struct Arg {
|
||||||
pub ty: P<Ty>,
|
pub ty: P<Ty>,
|
||||||
pub pat: P<Pat>,
|
pub pat: P<Pat>,
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alternative representation for `Arg`s describing `self` parameter of methods.
|
/// Alternative representation for `Arg`s describing `self` parameter of methods.
|
||||||
|
@ -1854,6 +1855,7 @@ impl Arg {
|
||||||
node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
|
||||||
span,
|
span,
|
||||||
}),
|
}),
|
||||||
|
span,
|
||||||
ty,
|
ty,
|
||||||
id: DUMMY_NODE_ID,
|
id: DUMMY_NODE_ID,
|
||||||
};
|
};
|
||||||
|
|
|
@ -966,6 +966,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
attrs: ThinVec::default(),
|
attrs: ThinVec::default(),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
pat: arg_pat,
|
pat: arg_pat,
|
||||||
|
span,
|
||||||
ty,
|
ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -558,10 +558,11 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) {
|
pub fn noop_visit_arg<T: MutVisitor>(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) {
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
visit_thin_attrs(attrs, vis);
|
visit_thin_attrs(attrs, vis);
|
||||||
vis.visit_pat(pat);
|
vis.visit_pat(pat);
|
||||||
|
vis.visit_span(span);
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ crate fn dummy_arg(ident: Ident) -> Arg {
|
||||||
span: ident.span,
|
span: ident.span,
|
||||||
id: ast::DUMMY_NODE_ID
|
id: ast::DUMMY_NODE_ID
|
||||||
};
|
};
|
||||||
Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, ty: P(ty) }
|
Arg { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat, span: ident.span, ty: P(ty) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
|
@ -1515,6 +1515,7 @@ impl<'a> Parser<'a> {
|
||||||
where
|
where
|
||||||
F: Fn(&token::Token) -> bool
|
F: Fn(&token::Token) -> bool
|
||||||
{
|
{
|
||||||
|
let lo = self.token.span;
|
||||||
let attrs = self.parse_arg_attributes()?;
|
let attrs = self.parse_arg_attributes()?;
|
||||||
if let Some(mut arg) = self.parse_self_arg()? {
|
if let Some(mut arg) = self.parse_self_arg()? {
|
||||||
arg.attrs = attrs.into();
|
arg.attrs = attrs.into();
|
||||||
|
@ -1578,11 +1579,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, ty })
|
let span = lo.to(self.token.span);
|
||||||
|
|
||||||
|
Ok(Arg { attrs: attrs.into(), id: ast::DUMMY_NODE_ID, pat, span, ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses an argument in a lambda header (e.g., `|arg, arg|`).
|
/// Parses an argument in a lambda header (e.g., `|arg, arg|`).
|
||||||
fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
|
fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
|
||||||
|
let lo = self.token.span;
|
||||||
let attrs = self.parse_arg_attributes()?;
|
let attrs = self.parse_arg_attributes()?;
|
||||||
let pat = self.parse_pat(Some("argument name"))?;
|
let pat = self.parse_pat(Some("argument name"))?;
|
||||||
let t = if self.eat(&token::Colon) {
|
let t = if self.eat(&token::Colon) {
|
||||||
|
@ -1594,10 +1598,12 @@ impl<'a> Parser<'a> {
|
||||||
span: self.prev_span,
|
span: self.prev_span,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
let span = lo.to(self.token.span);
|
||||||
Ok(Arg {
|
Ok(Arg {
|
||||||
attrs: attrs.into(),
|
attrs: attrs.into(),
|
||||||
ty: t,
|
ty: t,
|
||||||
pat,
|
pat,
|
||||||
|
span,
|
||||||
id: ast::DUMMY_NODE_ID
|
id: ast::DUMMY_NODE_ID
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ pub trait Visitor<'ast>: Sized {
|
||||||
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
|
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
|
||||||
fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
|
fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
|
||||||
fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
|
fn visit_stmt(&mut self, s: &'ast Stmt) { walk_stmt(self, s) }
|
||||||
|
fn visit_arg(&mut self, arg: &'ast Arg) { walk_arg(self, arg) }
|
||||||
fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
|
fn visit_arm(&mut self, a: &'ast Arm) { walk_arm(self, a) }
|
||||||
fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
|
fn visit_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) }
|
||||||
fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
|
fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) }
|
||||||
|
@ -547,12 +548,10 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
|
pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
|
||||||
for argument in &function_declaration.inputs {
|
for arg in &function_declaration.inputs {
|
||||||
walk_list!(visitor, visit_attribute, argument.attrs.iter());
|
visitor.visit_arg(arg);
|
||||||
visitor.visit_pat(&argument.pat);
|
|
||||||
visitor.visit_ty(&argument.ty);
|
|
||||||
}
|
}
|
||||||
visitor.visit_fn_ret_ty(&function_declaration.output)
|
visitor.visit_fn_ret_ty(&function_declaration.output);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
|
pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
|
||||||
|
@ -822,6 +821,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||||
visitor.visit_expr_post(expression)
|
visitor.visit_expr_post(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_arg<'a, V: Visitor<'a>>(visitor: &mut V, arg: &'a Arg) {
|
||||||
|
walk_list!(visitor, visit_attribute, arg.attrs.iter());
|
||||||
|
visitor.visit_pat(&arg.pat);
|
||||||
|
visitor.visit_ty(&arg.ty);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
|
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
|
||||||
walk_list!(visitor, visit_pat, &arm.pats);
|
walk_list!(visitor, visit_pat, &arm.pats);
|
||||||
if let Some(ref e) = &arm.guard {
|
if let Some(ref e) = &arm.guard {
|
||||||
|
|
|
@ -1,12 +1,70 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
// Exercise the unused_mut attribute in some positive and negative cases
|
// Exercise the unused_mut attribute in some positive and negative cases
|
||||||
|
|
||||||
#![allow(unused_assignments)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![deny(unused_mut)]
|
#![deny(unused_mut)]
|
||||||
|
#![feature(async_await, async_closure, param_attrs)]
|
||||||
|
|
||||||
|
async fn baz_async(
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
) {}
|
||||||
|
fn baz(
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
#[allow(unused_mut)] (mut c, d): (i32, i32)
|
||||||
|
) {}
|
||||||
|
|
||||||
|
struct RefStruct {}
|
||||||
|
impl RefStruct {
|
||||||
|
async fn baz_async(
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
) {}
|
||||||
|
fn baz(
|
||||||
|
&self,
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
#[allow(unused_mut)] (mut c, d): (i32, i32)
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait RefTrait {
|
||||||
|
fn baz(
|
||||||
|
&self,
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
#[allow(unused_mut)] (mut c, d): (i32, i32)
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
impl RefTrait for () {
|
||||||
|
fn baz(
|
||||||
|
&self,
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
#[allow(unused_mut)] (mut c, d): (i32, i32)
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let _ = async move |
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
| {};
|
||||||
|
let _ = |
|
||||||
|
mut a: i32,
|
||||||
|
//~^ ERROR: variable does not need to be mutable
|
||||||
|
#[allow(unused_mut)] mut b: i32,
|
||||||
|
#[allow(unused_mut)] (mut c, d): (i32, i32)
|
||||||
|
| {};
|
||||||
|
|
||||||
// negative cases
|
// negative cases
|
||||||
let mut a = 3; //~ ERROR: variable does not need to be mutable
|
let mut a = 3; //~ ERROR: variable does not need to be mutable
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,83 @@
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:46:14
|
--> $DIR/lint-unused-mut-variables.rs:9:5
|
||||||
|
|
|
|
||||||
LL | let x = |mut y: isize| 10;
|
LL | mut a: i32,
|
||||||
| ----^
|
| ----^
|
||||||
| |
|
| |
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/lint-unused-mut-variables.rs:6:9
|
--> $DIR/lint-unused-mut-variables.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![deny(unused_mut)]
|
LL | #![deny(unused_mut)]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:11:9
|
--> $DIR/lint-unused-mut-variables.rs:14:5
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:23:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:29:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:39:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:48:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:57:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:62:9
|
||||||
|
|
|
||||||
|
LL | mut a: i32,
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:104:14
|
||||||
|
|
|
||||||
|
LL | let x = |mut y: isize| 10;
|
||||||
|
| ----^
|
||||||
|
| |
|
||||||
|
| help: remove this `mut`
|
||||||
|
|
||||||
|
error: variable does not need to be mutable
|
||||||
|
--> $DIR/lint-unused-mut-variables.rs:69:9
|
||||||
|
|
|
|
||||||
LL | let mut a = 3;
|
LL | let mut a = 3;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -21,7 +85,7 @@ LL | let mut a = 3;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:13:9
|
--> $DIR/lint-unused-mut-variables.rs:71:9
|
||||||
|
|
|
|
||||||
LL | let mut a = 2;
|
LL | let mut a = 2;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -29,7 +93,7 @@ LL | let mut a = 2;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:15:9
|
--> $DIR/lint-unused-mut-variables.rs:73:9
|
||||||
|
|
|
|
||||||
LL | let mut b = 3;
|
LL | let mut b = 3;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -37,7 +101,7 @@ LL | let mut b = 3;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:17:9
|
--> $DIR/lint-unused-mut-variables.rs:75:9
|
||||||
|
|
|
|
||||||
LL | let mut a = vec![3];
|
LL | let mut a = vec![3];
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -45,7 +109,7 @@ LL | let mut a = vec![3];
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:19:10
|
--> $DIR/lint-unused-mut-variables.rs:77:10
|
||||||
|
|
|
|
||||||
LL | let (mut a, b) = (1, 2);
|
LL | let (mut a, b) = (1, 2);
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -53,7 +117,7 @@ LL | let (mut a, b) = (1, 2);
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:21:9
|
--> $DIR/lint-unused-mut-variables.rs:79:9
|
||||||
|
|
|
|
||||||
LL | let mut a;
|
LL | let mut a;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -61,7 +125,7 @@ LL | let mut a;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:25:9
|
--> $DIR/lint-unused-mut-variables.rs:83:9
|
||||||
|
|
|
|
||||||
LL | let mut b;
|
LL | let mut b;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -69,7 +133,7 @@ LL | let mut b;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:34:9
|
--> $DIR/lint-unused-mut-variables.rs:92:9
|
||||||
|
|
|
|
||||||
LL | mut x => {}
|
LL | mut x => {}
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -77,7 +141,7 @@ LL | mut x => {}
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:38:8
|
--> $DIR/lint-unused-mut-variables.rs:96:8
|
||||||
|
|
|
|
||||||
LL | (mut x, 1) |
|
LL | (mut x, 1) |
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -85,7 +149,7 @@ LL | (mut x, 1) |
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:51:9
|
--> $DIR/lint-unused-mut-variables.rs:109:9
|
||||||
|
|
|
|
||||||
LL | let mut a = &mut 5;
|
LL | let mut a = &mut 5;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -93,7 +157,7 @@ LL | let mut a = &mut 5;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:56:9
|
--> $DIR/lint-unused-mut-variables.rs:114:9
|
||||||
|
|
|
|
||||||
LL | let mut b = (&mut a,);
|
LL | let mut b = (&mut a,);
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -101,7 +165,7 @@ LL | let mut b = (&mut a,);
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:59:9
|
--> $DIR/lint-unused-mut-variables.rs:117:9
|
||||||
|
|
|
|
||||||
LL | let mut x = &mut 1;
|
LL | let mut x = &mut 1;
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -109,7 +173,7 @@ LL | let mut x = &mut 1;
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:71:9
|
--> $DIR/lint-unused-mut-variables.rs:129:9
|
||||||
|
|
|
|
||||||
LL | let mut v : &mut Vec<()> = &mut vec![];
|
LL | let mut v : &mut Vec<()> = &mut vec![];
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -117,7 +181,7 @@ LL | let mut v : &mut Vec<()> = &mut vec![];
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:48:13
|
--> $DIR/lint-unused-mut-variables.rs:106:13
|
||||||
|
|
|
|
||||||
LL | fn what(mut foo: isize) {}
|
LL | fn what(mut foo: isize) {}
|
||||||
| ----^^^
|
| ----^^^
|
||||||
|
@ -125,7 +189,7 @@ LL | fn what(mut foo: isize) {}
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:66:20
|
--> $DIR/lint-unused-mut-variables.rs:124:20
|
||||||
|
|
|
|
||||||
LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
|
LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
|
||||||
| ----^^^
|
| ----^^^
|
||||||
|
@ -133,7 +197,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
||||||
error: variable does not need to be mutable
|
error: variable does not need to be mutable
|
||||||
--> $DIR/lint-unused-mut-variables.rs:138:9
|
--> $DIR/lint-unused-mut-variables.rs:196:9
|
||||||
|
|
|
|
||||||
LL | let mut b = vec![2];
|
LL | let mut b = vec![2];
|
||||||
| ----^
|
| ----^
|
||||||
|
@ -141,10 +205,10 @@ LL | let mut b = vec![2];
|
||||||
| help: remove this `mut`
|
| help: remove this `mut`
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/lint-unused-mut-variables.rs:134:8
|
--> $DIR/lint-unused-mut-variables.rs:192:8
|
||||||
|
|
|
|
||||||
LL | #[deny(unused_mut)]
|
LL | #[deny(unused_mut)]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 17 previous errors
|
error: aborting due to 25 previous errors
|
||||||
|
|
||||||
|
|
64
src/test/ui/lint/lint-unused-variables.rs
Normal file
64
src/test/ui/lint/lint-unused-variables.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
// compile-flags: --cfg something
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
#![feature(async_await, async_closure, param_attrs)]
|
||||||
|
#![deny(unused_variables)]
|
||||||
|
|
||||||
|
async fn foo_async(
|
||||||
|
a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[allow(unused_variables)] b: i32,
|
||||||
|
) {}
|
||||||
|
fn foo(
|
||||||
|
#[allow(unused_variables)] a: i32,
|
||||||
|
b: i32,
|
||||||
|
//~^ ERROR unused variable: `b`
|
||||||
|
) {}
|
||||||
|
|
||||||
|
struct RefStruct {}
|
||||||
|
impl RefStruct {
|
||||||
|
async fn bar_async(
|
||||||
|
&self,
|
||||||
|
a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[allow(unused_variables)] b: i32,
|
||||||
|
) {}
|
||||||
|
fn bar(
|
||||||
|
&self,
|
||||||
|
#[allow(unused_variables)] a: i32,
|
||||||
|
b: i32,
|
||||||
|
//~^ ERROR unused variable: `b`
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
trait RefTrait {
|
||||||
|
fn bar(
|
||||||
|
&self,
|
||||||
|
#[allow(unused_variables)] a: i32,
|
||||||
|
b: i32,
|
||||||
|
//~^ ERROR unused variable: `b`
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
impl RefTrait for RefStruct {
|
||||||
|
fn bar(
|
||||||
|
&self,
|
||||||
|
#[allow(unused_variables)] a: i32,
|
||||||
|
b: i32,
|
||||||
|
//~^ ERROR unused variable: `b`
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _: fn(_, _) = foo;
|
||||||
|
let a = async move |
|
||||||
|
a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[allow(unused_variables)] b: i32,
|
||||||
|
| {};
|
||||||
|
let b = |
|
||||||
|
#[allow(unused_variables)] a: i32,
|
||||||
|
b: i32,
|
||||||
|
//~^ ERROR unused variable: `b`
|
||||||
|
| {};
|
||||||
|
let _ = a(1, 2);
|
||||||
|
let _ = b(1, 2);
|
||||||
|
}
|
56
src/test/ui/lint/lint-unused-variables.stderr
Normal file
56
src/test/ui/lint/lint-unused-variables.stderr
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
error: unused variable: `a`
|
||||||
|
--> $DIR/lint-unused-variables.rs:8:5
|
||||||
|
|
|
||||||
|
LL | a: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
|
||||||
|
note: lint level defined here
|
||||||
|
--> $DIR/lint-unused-variables.rs:5:9
|
||||||
|
|
|
||||||
|
LL | #![deny(unused_variables)]
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/lint-unused-variables.rs:14:5
|
||||||
|
|
|
||||||
|
LL | b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: unused variable: `a`
|
||||||
|
--> $DIR/lint-unused-variables.rs:53:9
|
||||||
|
|
|
||||||
|
LL | a: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/lint-unused-variables.rs:59:9
|
||||||
|
|
|
||||||
|
LL | b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/lint-unused-variables.rs:37:9
|
||||||
|
|
|
||||||
|
LL | b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: unused variable: `a`
|
||||||
|
--> $DIR/lint-unused-variables.rs:22:9
|
||||||
|
|
|
||||||
|
LL | a: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/lint-unused-variables.rs:29:9
|
||||||
|
|
|
||||||
|
LL | b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/lint-unused-variables.rs:45:9
|
||||||
|
|
|
||||||
|
LL | b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
|
@ -2,11 +2,13 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/issue-38371.rs:4:8
|
--> $DIR/issue-38371.rs:4:8
|
||||||
|
|
|
|
||||||
LL | fn foo(&foo: Foo) {
|
LL | fn foo(&foo: Foo) {
|
||||||
| ^^^^ expected struct `Foo`, found reference
|
| ^^^^------
|
||||||
|
| |
|
||||||
|
| expected struct `Foo`, found reference
|
||||||
|
| help: did you mean `foo`: `&Foo`
|
||||||
|
|
|
|
||||||
= note: expected type `Foo`
|
= note: expected type `Foo`
|
||||||
found type `&_`
|
found type `&_`
|
||||||
= help: did you mean `foo: &Foo`?
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-38371.rs:18:9
|
--> $DIR/issue-38371.rs:18:9
|
||||||
|
|
|
@ -1,189 +1,66 @@
|
||||||
|
// check-pass
|
||||||
// compile-flags: --cfg something
|
// compile-flags: --cfg something
|
||||||
// build-pass (FIXME(62277): could be check-pass?)
|
|
||||||
|
|
||||||
|
#![deny(unused_mut)]
|
||||||
#![feature(param_attrs)]
|
#![feature(param_attrs)]
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn ffi(
|
fn ffi(
|
||||||
#[allow(C)] a: i32,
|
#[allow(unused_mut)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||||
#[deny(C)] d: i32,
|
#[deny(unused_mut)] d: i32,
|
||||||
#[forbid(C)] #[warn(C)] ...
|
#[forbid(unused_mut)] #[warn(unused_mut)] ...
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type FnType = fn(
|
type FnType = fn(
|
||||||
#[allow(C)] a: i32,
|
#[allow(unused_mut)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||||
#[deny(C)] d: i32,
|
#[deny(unused_mut)] d: i32,
|
||||||
#[forbid(C)] #[warn(C)] e: i32
|
#[forbid(unused_mut)] #[warn(unused_mut)] e: i32
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn foo(
|
pub fn foo(
|
||||||
#[allow(C)] a: i32,
|
#[allow(unused_mut)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))] c: i32,
|
#[cfg_attr(something, cfg(nothing))] c: i32,
|
||||||
#[deny(C)] d: i32,
|
#[deny(unused_mut)] d: i32,
|
||||||
#[forbid(C)] #[warn(C)] e: i32
|
#[forbid(unused_mut)] #[warn(unused_mut)] _e: i32
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// self, &self and &mut self
|
// self
|
||||||
|
|
||||||
struct SelfStruct {}
|
struct SelfStruct {}
|
||||||
impl SelfStruct {
|
impl SelfStruct {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[allow(C)] self,
|
#[allow(unused_mut)] self,
|
||||||
#[cfg(something)] a: i32,
|
#[cfg(something)] a: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
#[cfg_attr(something, cfg(nothing))]
|
||||||
#[deny(C)] b: i32,
|
#[deny(unused_mut)] b: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RefStruct {}
|
struct RefStruct {}
|
||||||
impl RefStruct {
|
impl RefStruct {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[allow(C)] &self,
|
#[allow(unused_mut)] &self,
|
||||||
#[cfg(something)] a: i32,
|
#[cfg(something)] a: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
#[cfg_attr(something, cfg(nothing))]
|
||||||
#[deny(C)] b: i32,
|
#[deny(unused_mut)] b: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
trait RefTrait {
|
trait RefTrait {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[forbid(C)] &self,
|
#[forbid(unused_mut)] &self,
|
||||||
#[warn(C)] a: i32
|
#[warn(unused_mut)] a: i32
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
impl RefTrait for RefStruct {
|
impl RefTrait for RefStruct {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[forbid(C)] &self,
|
#[forbid(unused_mut)] &self,
|
||||||
#[warn(C)] a: i32
|
#[warn(unused_mut)] a: i32
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MutStruct {}
|
|
||||||
impl MutStruct {
|
|
||||||
fn foo(
|
|
||||||
#[allow(C)] &mut self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
trait MutTrait {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] &mut self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
impl MutTrait for MutStruct {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] &mut self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// self: Self, self: &Self and self: &mut Self
|
|
||||||
|
|
||||||
struct NamedSelfSelfStruct {}
|
|
||||||
impl NamedSelfSelfStruct {
|
|
||||||
fn foo(
|
|
||||||
#[allow(C)] self: Self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NamedSelfRefStruct {}
|
|
||||||
impl NamedSelfRefStruct {
|
|
||||||
fn foo(
|
|
||||||
#[allow(C)] self: &Self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
trait NamedSelfRefTrait {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] self: &Self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
impl NamedSelfRefTrait for NamedSelfRefStruct {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] self: &Self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NamedSelfMutStruct {}
|
|
||||||
impl NamedSelfMutStruct {
|
|
||||||
fn foo(
|
|
||||||
#[allow(C)] self: &mut Self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
trait NamedSelfMutTrait {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] self: &mut Self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
impl NamedSelfMutTrait for NamedSelfMutStruct {
|
|
||||||
fn foo(
|
|
||||||
#[forbid(C)] self: &mut Self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// &'a self and &'a mut self
|
|
||||||
|
|
||||||
struct NamedLifetimeRefStruct {}
|
|
||||||
impl NamedLifetimeRefStruct {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[allow(C)] self: &'a Self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
trait NamedLifetimeRefTrait {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[forbid(C)] &'a self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
impl NamedLifetimeRefTrait for NamedLifetimeRefStruct {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[forbid(C)] &'a self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NamedLifetimeMutStruct {}
|
|
||||||
impl NamedLifetimeMutStruct {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[allow(C)] self: &'a mut Self,
|
|
||||||
#[cfg(something)] a: i32,
|
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
|
||||||
#[deny(C)] b: i32,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
trait NamedLifetimeMutTrait {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[forbid(C)] &'a mut self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
impl NamedLifetimeMutTrait for NamedLifetimeMutStruct {
|
|
||||||
fn foo<'a>(
|
|
||||||
#[forbid(C)] &'a mut self,
|
|
||||||
#[warn(C)] a: i32
|
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,22 +69,22 @@ impl NamedLifetimeMutTrait for NamedLifetimeMutStruct {
|
||||||
struct BoxSelfStruct {}
|
struct BoxSelfStruct {}
|
||||||
impl BoxSelfStruct {
|
impl BoxSelfStruct {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[allow(C)] self: Box<Self>,
|
#[allow(unused_mut)] self: Box<Self>,
|
||||||
#[cfg(something)] a: i32,
|
#[cfg(something)] a: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
#[cfg_attr(something, cfg(nothing))]
|
||||||
#[deny(C)] b: i32,
|
#[deny(unused_mut)] b: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
trait BoxSelfTrait {
|
trait BoxSelfTrait {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[forbid(C)] self: Box<Self>,
|
#[forbid(unused_mut)] self: Box<Self>,
|
||||||
#[warn(C)] a: i32
|
#[warn(unused_mut)] a: i32
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
impl BoxSelfTrait for BoxSelfStruct {
|
impl BoxSelfTrait for BoxSelfStruct {
|
||||||
fn foo(
|
fn foo(
|
||||||
#[forbid(C)] self: Box<Self>,
|
#[forbid(unused_mut)] self: Box<Self>,
|
||||||
#[warn(C)] a: i32
|
#[warn(unused_mut)] a: i32
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,10 +93,10 @@ fn main() {
|
||||||
let _: fn(_, _, _, _) = foo;
|
let _: fn(_, _, _, _) = foo;
|
||||||
let _: FnType = |_, _, _, _| {};
|
let _: FnType = |_, _, _, _| {};
|
||||||
let c = |
|
let c = |
|
||||||
#[allow(C)] a: u32,
|
#[allow(unused_mut)] a: u32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
#[cfg_attr(something, cfg(nothing))]
|
#[cfg_attr(something, cfg(nothing))]
|
||||||
#[deny(C)] c: i32,
|
#[deny(unused_mut)] c: i32,
|
||||||
| {};
|
| {};
|
||||||
let _ = c(1, 2);
|
let _ = c(1, 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// compile-flags: --cfg something
|
// compile-flags: --cfg something
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
#![feature(param_attrs)]
|
#![feature(async_await, async_closure, param_attrs)]
|
||||||
#![deny(unused_variables)]
|
#![deny(unused_variables)]
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -19,24 +20,35 @@ type FnType = fn(
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async fn foo_async(
|
||||||
|
#[cfg(something)] a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[cfg(nothing)] b: i32,
|
||||||
|
) {}
|
||||||
fn foo(
|
fn foo(
|
||||||
#[cfg(nothing)] a: i32,
|
#[cfg(nothing)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
//~^ ERROR unused variable: `b` [unused_variables]
|
//~^ ERROR unused variable: `b`
|
||||||
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
//~^ ERROR unused variable: `c` [unused_variables]
|
//~^ ERROR unused variable: `c`
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
struct RefStruct {}
|
struct RefStruct {}
|
||||||
impl RefStruct {
|
impl RefStruct {
|
||||||
|
async fn bar_async(
|
||||||
|
&self,
|
||||||
|
#[cfg(something)] a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[cfg(nothing)] b: i32,
|
||||||
|
) {}
|
||||||
fn bar(
|
fn bar(
|
||||||
&self,
|
&self,
|
||||||
#[cfg(nothing)] a: i32,
|
#[cfg(nothing)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
//~^ ERROR unused variable: `b` [unused_variables]
|
//~^ ERROR unused variable: `b`
|
||||||
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
//~^ ERROR unused variable: `c` [unused_variables]
|
//~^ ERROR unused variable: `c`
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
@ -45,9 +57,9 @@ trait RefTrait {
|
||||||
&self,
|
&self,
|
||||||
#[cfg(nothing)] a: i32,
|
#[cfg(nothing)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
//~^ ERROR unused variable: `b` [unused_variables]
|
//~^ ERROR unused variable: `b`
|
||||||
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
//~^ ERROR unused variable: `c` [unused_variables]
|
//~^ ERROR unused variable: `c`
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
@ -56,9 +68,9 @@ impl RefTrait for RefStruct {
|
||||||
&self,
|
&self,
|
||||||
#[cfg(nothing)] a: i32,
|
#[cfg(nothing)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
//~^ ERROR unused variable: `b` [unused_variables]
|
//~^ ERROR unused variable: `b`
|
||||||
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
//~^ ERROR unused variable: `c` [unused_variables]
|
//~^ ERROR unused variable: `c`
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
@ -67,13 +79,19 @@ fn main() {
|
||||||
let _: unsafe extern "C" fn(_, ...) = ffi;
|
let _: unsafe extern "C" fn(_, ...) = ffi;
|
||||||
let _: fn(_, _) = foo;
|
let _: fn(_, _) = foo;
|
||||||
let _: FnType = |_, _| {};
|
let _: FnType = |_, _| {};
|
||||||
|
let a = async move |
|
||||||
|
#[cfg(something)] a: i32,
|
||||||
|
//~^ ERROR unused variable: `a`
|
||||||
|
#[cfg(nothing)] b: i32,
|
||||||
|
| {};
|
||||||
let c = |
|
let c = |
|
||||||
#[cfg(nothing)] a: i32,
|
#[cfg(nothing)] a: i32,
|
||||||
#[cfg(something)] b: i32,
|
#[cfg(something)] b: i32,
|
||||||
//~^ ERROR unused variable: `b` [unused_variables]
|
//~^ ERROR unused variable: `b`
|
||||||
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
#[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
//~^ ERROR unused variable: `c` [unused_variables]
|
//~^ ERROR unused variable: `c`
|
||||||
#[cfg_attr(something, cfg(nothing))] d: i32,
|
#[cfg_attr(something, cfg(nothing))] d: i32,
|
||||||
| {};
|
| {};
|
||||||
|
let _ = a(1);
|
||||||
let _ = c(1, 2);
|
let _ = c(1, 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +1,86 @@
|
||||||
error: unused variable: `b`
|
error: unused variable: `a`
|
||||||
--> $DIR/param-attrs-cfg.rs:24:23
|
--> $DIR/param-attrs-cfg.rs:24:23
|
||||||
|
|
|
|
||||||
LL | #[cfg(something)] b: i32,
|
LL | #[cfg(something)] a: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_b`
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/param-attrs-cfg.rs:4:9
|
--> $DIR/param-attrs-cfg.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![deny(unused_variables)]
|
LL | #![deny(unused_variables)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/param-attrs-cfg.rs:30:23
|
||||||
|
|
|
||||||
|
LL | #[cfg(something)] b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
error: unused variable: `c`
|
error: unused variable: `c`
|
||||||
--> $DIR/param-attrs-cfg.rs:26:40
|
--> $DIR/param-attrs-cfg.rs:32:40
|
||||||
|
|
|
|
||||||
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_c`
|
| ^ help: consider prefixing with an underscore: `_c`
|
||||||
|
|
||||||
|
error: unused variable: `a`
|
||||||
|
--> $DIR/param-attrs-cfg.rs:83:27
|
||||||
|
|
|
||||||
|
LL | #[cfg(something)] a: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
||||||
error: unused variable: `b`
|
error: unused variable: `b`
|
||||||
--> $DIR/param-attrs-cfg.rs:72:27
|
--> $DIR/param-attrs-cfg.rs:89:27
|
||||||
|
|
|
|
||||||
LL | #[cfg(something)] b: i32,
|
LL | #[cfg(something)] b: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_b`
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
error: unused variable: `c`
|
error: unused variable: `c`
|
||||||
--> $DIR/param-attrs-cfg.rs:74:44
|
--> $DIR/param-attrs-cfg.rs:91:44
|
||||||
|
|
|
|
||||||
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_c`
|
| ^ help: consider prefixing with an underscore: `_c`
|
||||||
|
|
||||||
error: unused variable: `b`
|
error: unused variable: `b`
|
||||||
--> $DIR/param-attrs-cfg.rs:47:27
|
--> $DIR/param-attrs-cfg.rs:59:27
|
||||||
|
|
|
|
||||||
LL | #[cfg(something)] b: i32,
|
LL | #[cfg(something)] b: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_b`
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
error: unused variable: `c`
|
error: unused variable: `c`
|
||||||
--> $DIR/param-attrs-cfg.rs:49:44
|
--> $DIR/param-attrs-cfg.rs:61:44
|
||||||
|
|
|
||||||
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_c`
|
||||||
|
|
||||||
|
error: unused variable: `a`
|
||||||
|
--> $DIR/param-attrs-cfg.rs:41:27
|
||||||
|
|
|
||||||
|
LL | #[cfg(something)] a: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_a`
|
||||||
|
|
||||||
|
error: unused variable: `b`
|
||||||
|
--> $DIR/param-attrs-cfg.rs:48:27
|
||||||
|
|
|
||||||
|
LL | #[cfg(something)] b: i32,
|
||||||
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
|
error: unused variable: `c`
|
||||||
|
--> $DIR/param-attrs-cfg.rs:50:44
|
||||||
|
|
|
|
||||||
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_c`
|
| ^ help: consider prefixing with an underscore: `_c`
|
||||||
|
|
||||||
error: unused variable: `b`
|
error: unused variable: `b`
|
||||||
--> $DIR/param-attrs-cfg.rs:36:27
|
--> $DIR/param-attrs-cfg.rs:70:27
|
||||||
|
|
|
|
||||||
LL | #[cfg(something)] b: i32,
|
LL | #[cfg(something)] b: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_b`
|
| ^ help: consider prefixing with an underscore: `_b`
|
||||||
|
|
||||||
error: unused variable: `c`
|
error: unused variable: `c`
|
||||||
--> $DIR/param-attrs-cfg.rs:38:44
|
--> $DIR/param-attrs-cfg.rs:72:44
|
||||||
|
|
|
|
||||||
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
||||||
| ^ help: consider prefixing with an underscore: `_c`
|
| ^ help: consider prefixing with an underscore: `_c`
|
||||||
|
|
||||||
error: unused variable: `b`
|
error: aborting due to 13 previous errors
|
||||||
--> $DIR/param-attrs-cfg.rs:58:27
|
|
||||||
|
|
|
||||||
LL | #[cfg(something)] b: i32,
|
|
||||||
| ^ help: consider prefixing with an underscore: `_b`
|
|
||||||
|
|
||||||
error: unused variable: `c`
|
|
||||||
--> $DIR/param-attrs-cfg.rs:60:44
|
|
||||||
|
|
|
||||||
LL | #[cfg_attr(nothing, cfg(nothing))] c: i32,
|
|
||||||
| ^ help: consider prefixing with an underscore: `_c`
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
// gate-test-param_attrs
|
// gate-test-param_attrs
|
||||||
|
|
||||||
|
#![deny(unused_variables)]
|
||||||
|
|
||||||
fn foo(
|
fn foo(
|
||||||
/// Foo
|
/// Foo
|
||||||
//~^ ERROR documentation comments cannot be applied to function parameters
|
//~^ ERROR documentation comments cannot be applied to function parameters
|
||||||
//~| NOTE doc comments are not allowed here
|
//~| NOTE doc comments are not allowed here
|
||||||
//~| ERROR attributes on function parameters are unstable
|
//~| ERROR attributes on function parameters are unstable
|
||||||
//~| NOTE https://github.com/rust-lang/rust/issues/60406
|
//~| NOTE https://github.com/rust-lang/rust/issues/60406
|
||||||
#[allow(C)] a: u8
|
#[allow(unused_variables)] a: u8
|
||||||
//~^ ERROR attributes on function parameters are unstable
|
//~^ ERROR attributes on function parameters are unstable
|
||||||
//~| NOTE https://github.com/rust-lang/rust/issues/60406
|
//~| NOTE https://github.com/rust-lang/rust/issues/60406
|
||||||
) {}
|
) {}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error: documentation comments cannot be applied to function parameters
|
error: documentation comments cannot be applied to function parameters
|
||||||
--> $DIR/param-attrs-feature-gate.rs:4:5
|
--> $DIR/param-attrs-feature-gate.rs:6:5
|
||||||
|
|
|
|
||||||
LL | /// Foo
|
LL | /// Foo
|
||||||
| ^^^^^^^ doc comments are not allowed here
|
| ^^^^^^^ doc comments are not allowed here
|
||||||
|
|
||||||
error[E0658]: attributes on function parameters are unstable
|
error[E0658]: attributes on function parameters are unstable
|
||||||
--> $DIR/param-attrs-feature-gate.rs:4:5
|
--> $DIR/param-attrs-feature-gate.rs:6:5
|
||||||
|
|
|
|
||||||
LL | /// Foo
|
LL | /// Foo
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -14,10 +14,10 @@ LL | /// Foo
|
||||||
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
|
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: attributes on function parameters are unstable
|
error[E0658]: attributes on function parameters are unstable
|
||||||
--> $DIR/param-attrs-feature-gate.rs:9:5
|
--> $DIR/param-attrs-feature-gate.rs:11:5
|
||||||
|
|
|
|
||||||
LL | #[allow(C)] a: u8
|
LL | #[allow(unused_variables)] a: u8
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: for more information, see https://github.com/rust-lang/rust/issues/60406
|
= note: for more information, see https://github.com/rust-lang/rust/issues/60406
|
||||||
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
|
= help: add `#![feature(param_attrs)]` to the crate attributes to enable
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue