From af96b1df1da916561547dd30b3187b30308d6843 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 3 Jul 2019 21:45:17 -0400 Subject: [PATCH 01/11] Document that ManuallyDrop::drop should not called more than once Double dropping is unsound (e.g. https://github.com/rust-lang/rust/issues/60977). This commit documents the fact that `ManuallyDrop::drop` should not be called multiple times on the same instance, as it might not be immediately obvious that this counts as a use of uninitialized data. --- src/libcore/mem/manually_drop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 3ad1223e331ec..5d43090250803 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -118,7 +118,8 @@ impl ManuallyDrop { /// /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the - /// uninitialized data is not actually used. + /// uninitialized data is not actually used, and that this function is called at most once + /// for a given instance of ManuallyDrop /// /// [`ManuallyDrop::into_inner`]: #method.into_inner #[stable(feature = "manually_drop", since = "1.20.0")] From 626ae7585c555010bee23d7e63b28147b63c0c19 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 3 Jul 2019 22:16:48 -0400 Subject: [PATCH 02/11] Improve formatting of 'ManuallyDrop' Co-Authored-By: Mazdak Farrokhzad --- src/libcore/mem/manually_drop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 5d43090250803..d6907000ffc4a 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -119,7 +119,7 @@ impl ManuallyDrop { /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the /// uninitialized data is not actually used, and that this function is called at most once - /// for a given instance of ManuallyDrop + /// for a given instance of `ManuallyDrop`. /// /// [`ManuallyDrop::into_inner`]: #method.into_inner #[stable(feature = "manually_drop", since = "1.20.0")] From eeb1bd18dc172c2ba80c116d711214c2cdac3e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Jul 2019 15:59:38 -0700 Subject: [PATCH 03/11] Avoid ICE when suggestion span is at Eof --- src/librustc_errors/lib.rs | 3 +- src/test/ui/parser/issue-62973.rs | 8 ++++ src/test/ui/parser/issue-62973.stderr | 61 +++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-62973.rs create mode 100644 src/test/ui/parser/issue-62973.stderr diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3269b85d0dd13..67fae1f676923 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -229,7 +229,8 @@ impl CodeSuggestion { } } if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { - buf.push_str(&cur_line[..cur_lo.col.to_usize()]); + let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize()); + buf.push_str(&cur_line[..end]); } } buf.push_str(&part.snippet); diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issue-62973.rs new file mode 100644 index 0000000000000..c04608e055030 --- /dev/null +++ b/src/test/ui/parser/issue-62973.rs @@ -0,0 +1,8 @@ +// ignore-tidy-end-whitespace +// error-pattern: aborting due to 6 previous errors + +fn main() {} + +fn p() { match s { v, E { [) {) } + + diff --git a/src/test/ui/parser/issue-62973.stderr b/src/test/ui/parser/issue-62973.stderr new file mode 100644 index 0000000000000..141076bf6b638 --- /dev/null +++ b/src/test/ui/parser/issue-62973.stderr @@ -0,0 +1,61 @@ +error: this file contains an un-closed delimiter + --> $DIR/issue-62973.rs:8:2 + | +LL | fn p() { match s { v, E { [) {) } + | - - un-closed delimiter + | | + | un-closed delimiter +LL | +LL | + | ^ + +error: expected one of `,` or `}`, found `{` + --> $DIR/issue-62973.rs:6:25 + | +LL | fn p() { match s { v, E { [) {) } + | - ^ expected one of `,` or `}` here + | | + | while parsing this struct + +error: struct literals are not allowed here + --> $DIR/issue-62973.rs:6:16 + | +LL | fn p() { match s { v, E { [) {) } + | ________________^ +LL | | +LL | | + | |_^ +help: surround the struct literal with parentheses + | +LL | fn p() { match (s { v, E { [) {) } +LL | +LL | ) + | + +error: expected one of `.`, `?`, `{`, or an operator, found `}` + --> $DIR/issue-62973.rs:8:1 + | +LL | fn p() { match s { v, E { [) {) } + | ----- while parsing this match expression +LL | +LL | + | ^ expected one of `.`, `?`, `{`, or an operator here + +error: incorrect close delimiter: `)` + --> $DIR/issue-62973.rs:6:28 + | +LL | fn p() { match s { v, E { [) {) } + | -^ incorrect close delimiter + | | + | un-closed delimiter + +error: incorrect close delimiter: `)` + --> $DIR/issue-62973.rs:6:31 + | +LL | fn p() { match s { v, E { [) {) } + | -^ incorrect close delimiter + | | + | un-closed delimiter + +error: aborting due to 6 previous errors + From 6263eb438def79c393e372eac1237b4d4f97772f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Jul 2019 16:26:33 -0700 Subject: [PATCH 04/11] ignore-tidy-trailing-newlines --- src/test/ui/parser/issue-62973.rs | 2 +- src/tools/tidy/src/style.rs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/test/ui/parser/issue-62973.rs b/src/test/ui/parser/issue-62973.rs index c04608e055030..18bc51e7ba7cd 100644 --- a/src/test/ui/parser/issue-62973.rs +++ b/src/test/ui/parser/issue-62973.rs @@ -1,4 +1,4 @@ -// ignore-tidy-end-whitespace +// ignore-tidy-trailing-newlines // error-pattern: aborting due to 6 previous errors fn main() {} diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 4a159d926b7cc..6a0d530e2362a 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -152,6 +152,8 @@ pub fn check(path: &Path, bad: &mut bool) { let mut skip_file_length = contains_ignore_directive(can_contain, &contents, "filelength"); let mut skip_end_whitespace = contains_ignore_directive(can_contain, &contents, "end-whitespace"); + let mut skip_trailing_newlines = + contains_ignore_directive(can_contain, &contents, "trailing-newlines"); let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright"); let mut leading_new_lines = false; let mut trailing_new_lines = 0; @@ -214,10 +216,17 @@ pub fn check(path: &Path, bad: &mut bool) { if leading_new_lines { tidy_error!(bad, "{}: leading newline", file.display()); } + let mut err = |msg: &str| { + tidy_error!(bad, "{}: {}", file.display(), msg); + }; match trailing_new_lines { - 0 => tidy_error!(bad, "{}: missing trailing newline", file.display()), + 0 => suppressible_tidy_err!(err, skip_trailing_newlines, "missing trailing newline"), 1 => {} - n => tidy_error!(bad, "{}: too many trailing newlines ({})", file.display(), n), + n => suppressible_tidy_err!( + err, + skip_trailing_newlines, + &format!("too many trailing newlines ({})", n) + ), }; if lines > LINES { let mut err = |_| { @@ -247,6 +256,9 @@ pub fn check(path: &Path, bad: &mut bool) { if let Directive::Ignore(false) = skip_end_whitespace { tidy_error!(bad, "{}: ignoring trailing whitespace unnecessarily", file.display()); } + if let Directive::Ignore(false) = skip_trailing_newlines { + tidy_error!(bad, "{}: ignoring trailing newlines unnecessarily", file.display()); + } if let Directive::Ignore(false) = skip_copyright { tidy_error!(bad, "{}: ignoring copyright unnecessarily", file.display()); } From 53fc7fbc9606ba8b29e674ab08c3ccf1ebfd128d Mon Sep 17 00:00:00 2001 From: Caio Date: Fri, 26 Jul 2019 19:52:37 -0300 Subject: [PATCH 05/11] Lint attributes on function arguments --- src/librustc/hir/intravisit.rs | 15 +- src/librustc/hir/lowering.rs | 43 ++++- src/librustc/hir/map/collector.rs | 8 + src/librustc/hir/map/mod.rs | 7 + src/librustc/hir/mod.rs | 5 +- src/librustc/hir/print.rs | 5 + src/librustc/lint/context.rs | 14 ++ src/librustc/lint/mod.rs | 10 +- src/librustc_mir/build/mod.rs | 47 ++++- src/librustc_passes/hir_stats.rs | 5 + src/librustc_typeck/check/_match.rs | 25 ++- src/librustc_typeck/check/demand.rs | 82 ++++---- src/libsyntax/ast.rs | 2 + src/libsyntax/ext/build.rs | 1 + src/libsyntax/mut_visit.rs | 3 +- src/libsyntax/parse/diagnostics.rs | 2 +- src/libsyntax/parse/parser.rs | 8 +- src/libsyntax/visit.rs | 15 +- src/test/ui/lint/lint-unused-mut-variables.rs | 64 ++++++- .../ui/lint/lint-unused-mut-variables.stderr | 112 ++++++++--- src/test/ui/lint/lint-unused-variables.rs | 64 +++++++ src/test/ui/lint/lint-unused-variables.stderr | 56 ++++++ .../ui/mismatched_types/issue-38371.stderr | 6 +- .../param-attrs-allowed.rs | 179 +++--------------- .../rfc-2565-param-attrs/param-attrs-cfg.rs | 40 ++-- .../param-attrs-cfg.stderr | 46 +++-- .../param-attrs-feature-gate.rs | 4 +- .../param-attrs-feature-gate.stderr | 10 +- 28 files changed, 586 insertions(+), 292 deletions(-) create mode 100644 src/test/ui/lint/lint-unused-variables.rs create mode 100644 src/test/ui/lint/lint-unused-variables.stderr diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2d82314f86ac2..3781d7df1764c 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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 /// `visit_nested_item` for details. 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) { - for argument in &body.arguments { - visitor.visit_id(argument.hir_id); - visitor.visit_pat(&argument.pat); - } + walk_list!(visitor, visit_arg, &body.arguments); 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) } +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) { visitor.visit_vis(&item.vis); visitor.visit_ident(item.ident); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 288fd2714e251..e1fc61b82546e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2461,8 +2461,10 @@ impl<'a> LoweringContext<'a> { fn lower_arg(&mut self, arg: &Arg) -> hir::Arg { hir::Arg { + attrs: self.lower_attrs(&arg.attrs), hir_id: self.lower_node_id(arg.id), 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 // 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 = hir::Arg { + attrs: argument.attrs, hir_id: argument.hir_id, pat: new_argument_pat, + span: argument.span, }; + if is_simple_argument { // If this is the simple case, then we only insert one statement that is // `let = ;`. We re-use the original argument's pattern so that // `HirId`s are densely assigned. let expr = this.expr_ident(desugared_span, ident, new_argument_id); 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); } else { // 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); let move_expr = this.expr_ident(desugared_span, ident, new_argument_id); 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 = __argN;` statement. We re-use the original // argument's pattern so that `HirId`s are densely assigned. let pattern_expr = this.expr_ident(desugared_span, ident, move_id); let pattern_stmt = this.stmt_let_pat( - desugared_span, Some(P(pattern_expr)), argument.pat, - hir::LocalSource::AsyncFn); + stmt_attrs, + desugared_span, + Some(P(pattern_expr)), + argument.pat, + hir::LocalSource::AsyncFn + ); statements.push(move_stmt); statements.push(pattern_stmt); @@ -4910,6 +4931,7 @@ impl<'a> LoweringContext<'a> { // `let mut __next` let next_let = self.stmt_let_pat( + ThinVec::new(), desugared_span, None, next_pat, @@ -4919,6 +4941,7 @@ impl<'a> LoweringContext<'a> { // `let = __next` let pat = self.lower_pat(pat); let pat_let = self.stmt_let_pat( + ThinVec::new(), head_sp, Some(next_expr), pat, @@ -5413,19 +5436,20 @@ impl<'a> LoweringContext<'a> { fn stmt_let_pat( &mut self, + attrs: ThinVec, span: Span, init: Option>, pat: P, source: hir::LocalSource, ) -> hir::Stmt { let local = hir::Local { - pat, - ty: None, - init, + attrs, hir_id: self.next_id(), - span, + init, + pat, source, - attrs: ThinVec::new() + span, + ty: None, }; self.stmt(span, hir::StmtKind::Local(P(local))) } @@ -5831,6 +5855,7 @@ impl<'a> LoweringContext<'a> { hir::BindingAnnotation::Mutable, ); let pinned_let = self.stmt_let_pat( + ThinVec::new(), span, Some(expr), pinned_pat, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 12ea772c1fb31..b6807f7d3bbd2 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -363,6 +363,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { 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) { debug!("visit_item: {:?}", i); debug_assert_eq!(i.hir_id.owner, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 43b1dbb6216d7..5a28d9e7b7db6 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -360,6 +360,7 @@ impl<'hir> Map<'hir> { Node::Pat(_) | Node::Binding(_) | Node::Local(_) | + Node::Arg(_) | Node::Arm(_) | Node::Lifetime(_) | Node::Visibility(_) | @@ -932,6 +933,7 @@ impl<'hir> Map<'hir> { pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { self.read(id); // reveals attributes on the 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::Item(i)) => Some(&i.attrs[..]), Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), @@ -995,6 +997,7 @@ impl<'hir> Map<'hir> { pub fn span(&self, hir_id: HirId) -> Span { self.read(hir_id); // reveals span from 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::ForeignItem(foreign_item)) => foreign_item.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> { pub fn print_node(&mut self, node: Node<'_>) { match node { + Node::Arg(a) => self.print_arg(&a), Node::Item(a) => self.print_item(&a), Node::ForeignItem(a) => self.print_foreign_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(_)) => { 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(_)) => { format!("arm {}{}", map.hir_to_pretty_string(id), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e7b37d40b4b2f..821585da4ebb2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2010,8 +2010,10 @@ pub struct InlineAsm { /// Represents an argument in a function header. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arg { - pub pat: P, + pub attrs: HirVec, pub hir_id: HirId, + pub pat: P, + pub span: Span, } /// Represents the header (not the body) of a function declaration. @@ -2701,6 +2703,7 @@ impl CodegenFnAttrs { #[derive(Copy, Clone, Debug)] pub enum Node<'hir> { + Arg(&'hir Arg), Item(&'hir Item), ForeignItem(&'hir ForeignItem), TraitItem(&'hir TraitItem), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 3e571baaa4e51..9f6be0a9290e6 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1767,6 +1767,11 @@ impl<'a> State<'a> { 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) { // I have no idea why this check is necessary, but here it // is :( diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 2930f7690dd8e..597ea8e8e5fb7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -966,6 +966,13 @@ for LateContextAndPass<'a, 'tcx, T> { 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) { lint_callback!(self, check_body, 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> { + 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) { self.with_lint_attrs(it.id, &it.attrs, |cx| { run_early_pass!(cx, check_item, it); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index dddbc31ccd4ea..8ddf4603490a1 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -206,6 +206,7 @@ macro_rules! declare_lint_pass { macro_rules! late_lint_methods { ($macro:path, $args:tt, [$hir:tt]) => ( $macro!($args, [$hir], [ + fn check_arg(a: &$hir hir::Arg); fn check_body(a: &$hir hir::Body); fn check_body_post(a: &$hir hir::Body); 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:path, $args:tt) => ( $macro!($args, [ + fn check_arg(a: &ast::Arg); fn check_ident(a: ast::Ident); fn check_crate(a: &ast::Crate); fn check_crate_post(a: &ast::Crate); @@ -495,8 +497,6 @@ pub type EarlyLintPassObject = Box LateLintPass<'a, 'tcx> + sync::Send + sync::Sync + 'static>; - - /// Identifies a lint known to the compiler. #[derive(Clone, Copy, Debug)] pub struct LintId { @@ -812,6 +812,12 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { 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) { self.with_lint_attrs(it.hir_id, &it.attrs, |builder| { intravisit::walk_item(builder, it); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8948d1c4b3663..4e970aee42cf4 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -121,7 +121,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { 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); @@ -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 -struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Pat>, Option); +struct ArgInfo<'tcx>(Ty<'tcx>, Option, Option<&'tcx hir::Arg>, Option); fn construct_fn<'a, 'tcx, A>( hir: Cx<'a, 'tcx>, @@ -782,13 +782,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { -> BlockAnd<()> { // 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 // debuginfo and so that error reporting knows that this is a user // variable. For any other pattern the pattern introduces new // variables which will be named instead. - let (name, span) = if let Some(pat) = pattern { - (pat.simple_ident().map(|ident| ident.name), pat.span) + let (name, span) = if let Some(arg) = arg_opt { + (arg.pat.simple_ident().map(|ident| ident.name), arg.pat.span) } else { (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 let local = Local::new(index + 1); 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. 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, ); - if let Some(pattern) = pattern { - let pattern = self.hir.pattern_from_hir(pattern); + if let Some(arg) = arg_opt { + let pattern = self.hir.pattern_from_hir(&arg.pat); + let original_source_scope = self.source_scope; let span = pattern.span; - + self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span); match *pattern.kind { // Don't introduce extra copies for simple bindings PatternKind::Binding { @@ -835,6 +836,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .. } => { self.local_decls[local].mutability = mutability; + self.local_decls[local].source_info.scope = self.source_scope; self.local_decls[local].is_user_variable = if let Some(kind) = self_binding { 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)); } } + self.source_scope = original_source_scope; } } @@ -872,6 +875,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 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> { match self.unit_temp { Some(ref tmp) => tmp.clone(), diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index e7f6abc410a32..8fba3256ec429 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -94,6 +94,11 @@ impl<'k> StatCollector<'k> { } 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> { panic!("visit_nested_xxx must be manually implemented in this visitor") } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index de42a6a35c89a..c8983fef2de57 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -551,21 +551,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; if let PatKind::Binding(..) = inner.node { - let parent_id = tcx.hir().get_parent_node(pat.hir_id); - let parent = tcx.hir().get(parent_id); - debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent); - match parent { - hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) | - 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 + let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); + let binding_parent = tcx.hir().get(binding_parent_id); + debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent); + match binding_parent { + hir::Node::Arg(hir::Arg { 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 - // includes the the arg's type. - err.help(&format!("did you mean `{}: &{}`?", snippet, expected)); + err.span_suggestion( + *span, + &format!("did you mean `{}`", snippet), + format!(" &{}", expected), + Applicability::MachineApplicable, + ); } } hir::Node::Arm(_) | diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 14c38ae053d23..3229d49841e79 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -235,40 +235,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, expr: &hir::Expr, ) -> Option<(Span, &'static str, String)> { - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.node { - if let hir::def::Res::Local(id) = path.res { - let parent = self.tcx.hir().get_parent_node(id); - if let Some(Node::Expr(hir::Expr { - hir_id, - node: hir::ExprKind::Closure(_, decl, ..), - .. - })) = self.tcx.hir().find(parent) { - let parent = self.tcx.hir().get_parent_node(*hir_id); - if let (Some(Node::Expr(hir::Expr { - node: hir::ExprKind::MethodCall(path, span, expr), - .. - })), 1) = (self.tcx.hir().find(parent), decl.inputs.len()) { - let self_ty = self.tables.borrow().node_type(expr[0].hir_id); - let self_ty = format!("{:?}", self_ty); - let name = 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(*span)) { - (true, Ok(src)) => { - return Some((*span, "consider using `as_ref` instead", - format!("as_ref().{}", src))); - }, - _ => () - } - } - } - } + let path = match expr.node { + hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => path, + _ => return None + }; + + let local_id = match path.res { + hir::def::Res::Local(id) => id, + _ => return None + }; + + let local_parent = self.tcx.hir().get_parent_node(local_id); + let arg_hir_id = match self.tcx.hir().find(local_parent) { + Some(Node::Arg(hir::Arg { hir_id, .. })) => hir_id, + _ => return None + }; + + let arg_parent = self.tcx.hir().get_parent_node(*arg_hir_id); + let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(arg_parent) { + Some(Node::Expr( + hir::Expr { hir_id, node: hir::ExprKind::Closure(_, decl, ..), .. } + )) => (hir_id, decl), + _ => return None + }; + + let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id); + 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( diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b9b43c89346c7..471a657c82ae0 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1776,6 +1776,7 @@ pub struct Arg { pub ty: P, pub pat: P, pub id: NodeId, + pub span: Span, } /// Alternative representation for `Arg`s describing `self` parameter of methods. @@ -1834,6 +1835,7 @@ impl Arg { node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), span, }), + span, ty, id: DUMMY_NODE_ID, }; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index baf1031de1e7c..e1f8310ee8d03 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -966,6 +966,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { attrs: ThinVec::default(), id: ast::DUMMY_NODE_ID, pat: arg_pat, + span, ty, } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index dc656222fbc10..23dfad32911ed 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -558,10 +558,11 @@ pub fn noop_visit_meta_item(mi: &mut MetaItem, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arg(Arg { attrs, id, pat, ty }: &mut Arg, vis: &mut T) { +pub fn noop_visit_arg(Arg { attrs, id, pat, span, ty }: &mut Arg, vis: &mut T) { vis.visit_id(id); visit_thin_attrs(attrs, vis); vis.visit_pat(pat); + vis.visit_span(span); vis.visit_ty(ty); } diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index f4fc87506f357..39cb5042fbc11 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -30,7 +30,7 @@ crate fn dummy_arg(ident: Ident) -> Arg { span: ident.span, 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 { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index da38869463737..ed4cb405fe74b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1502,6 +1502,7 @@ impl<'a> Parser<'a> { where F: Fn(&token::Token) -> bool { + let lo = self.token.span; let attrs = self.parse_arg_attributes()?; if let Some(mut arg) = self.parse_self_arg()? { arg.attrs = attrs.into(); @@ -1565,11 +1566,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|`). fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { + let lo = self.token.span; let attrs = self.parse_arg_attributes()?; let pat = self.parse_pat(Some("argument name"))?; let t = if self.eat(&token::Colon) { @@ -1581,10 +1585,12 @@ impl<'a> Parser<'a> { span: self.prev_span, }) }; + let span = lo.to(self.token.span); Ok(Arg { attrs: attrs.into(), ty: t, pat, + span, id: ast::DUMMY_NODE_ID }) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9ec9550f93ab9..5fc8bdb608e47 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -66,6 +66,7 @@ pub trait Visitor<'ast>: Sized { 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_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_pat(&mut self, p: &'ast Pat) { walk_pat(self, p) } fn visit_anon_const(&mut self, c: &'ast AnonConst) { walk_anon_const(self, c) } @@ -549,12 +550,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) { - for argument in &function_declaration.inputs { - walk_list!(visitor, visit_attribute, argument.attrs.iter()); - visitor.visit_pat(&argument.pat); - visitor.visit_ty(&argument.ty); + for arg in &function_declaration.inputs { + visitor.visit_arg(arg); } - 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) @@ -824,6 +823,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { 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) { walk_list!(visitor, visit_pat, &arm.pats); if let Some(ref e) = &arm.guard { diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 78609a6e24b5e..2957f93111051 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -1,12 +1,70 @@ +// edition:2018 + // Exercise the unused_mut attribute in some positive and negative cases -#![allow(unused_assignments)] -#![allow(unused_variables)] -#![allow(dead_code)] #![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() { + 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 let mut a = 3; //~ ERROR: variable does not need to be mutable diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 1a175c9683ec7..92c2b68652dc2 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -1,19 +1,83 @@ 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; - | ----^ - | | - | help: remove this `mut` +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` | 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)] | ^^^^^^^^^^ 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; | ----^ @@ -21,7 +85,7 @@ LL | let mut a = 3; | help: remove this `mut` 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; | ----^ @@ -29,7 +93,7 @@ LL | let mut a = 2; | help: remove this `mut` 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; | ----^ @@ -37,7 +101,7 @@ LL | let mut b = 3; | help: remove this `mut` 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]; | ----^ @@ -45,7 +109,7 @@ LL | let mut a = vec![3]; | help: remove this `mut` 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); | ----^ @@ -53,7 +117,7 @@ LL | let (mut a, b) = (1, 2); | help: remove this `mut` 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; | ----^ @@ -61,7 +125,7 @@ LL | let mut a; | help: remove this `mut` 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; | ----^ @@ -69,7 +133,7 @@ LL | let mut b; | help: remove this `mut` 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 => {} | ----^ @@ -77,7 +141,7 @@ LL | mut x => {} | help: remove this `mut` 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) | | ----^ @@ -85,7 +149,7 @@ LL | (mut x, 1) | | help: remove this `mut` 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; | ----^ @@ -93,7 +157,7 @@ LL | let mut a = &mut 5; | help: remove this `mut` 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,); | ----^ @@ -101,7 +165,7 @@ LL | let mut b = (&mut a,); | help: remove this `mut` 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; | ----^ @@ -109,7 +173,7 @@ LL | let mut x = &mut 1; | help: remove this `mut` 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![]; | ----^ @@ -117,7 +181,7 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | help: remove this `mut` 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) {} | ----^^^ @@ -125,7 +189,7 @@ LL | fn what(mut foo: isize) {} | help: remove this `mut` 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] { | ----^^^ @@ -133,7 +197,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` 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]; | ----^ @@ -141,10 +205,10 @@ LL | let mut b = vec![2]; | help: remove this `mut` | 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)] | ^^^^^^^^^^ -error: aborting due to 17 previous errors +error: aborting due to 25 previous errors diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs new file mode 100644 index 0000000000000..a1660d2351123 --- /dev/null +++ b/src/test/ui/lint/lint-unused-variables.rs @@ -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); +} diff --git a/src/test/ui/lint/lint-unused-variables.stderr b/src/test/ui/lint/lint-unused-variables.stderr new file mode 100644 index 0000000000000..7ed5669e33c24 --- /dev/null +++ b/src/test/ui/lint/lint-unused-variables.stderr @@ -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 + diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr index a9347926bda0a..79a0807c33721 100644 --- a/src/test/ui/mismatched_types/issue-38371.stderr +++ b/src/test/ui/mismatched_types/issue-38371.stderr @@ -2,11 +2,13 @@ error[E0308]: mismatched types --> $DIR/issue-38371.rs:4:8 | 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` found type `&_` - = help: did you mean `foo: &Foo`? error[E0308]: mismatched types --> $DIR/issue-38371.rs:18:9 diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs index e796e37bbaa45..5eeda66173ded 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-allowed.rs @@ -1,189 +1,66 @@ +// check-pass // compile-flags: --cfg something -// build-pass (FIXME(62277): could be check-pass?) +#![deny(unused_mut)] #![feature(param_attrs)] extern "C" { fn ffi( - #[allow(C)] a: i32, + #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(C)] d: i32, - #[forbid(C)] #[warn(C)] ... + #[deny(unused_mut)] d: i32, + #[forbid(unused_mut)] #[warn(unused_mut)] ... ); } type FnType = fn( - #[allow(C)] a: i32, + #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(C)] d: i32, - #[forbid(C)] #[warn(C)] e: i32 + #[deny(unused_mut)] d: i32, + #[forbid(unused_mut)] #[warn(unused_mut)] e: i32 ); pub fn foo( - #[allow(C)] a: i32, + #[allow(unused_mut)] a: i32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] c: i32, - #[deny(C)] d: i32, - #[forbid(C)] #[warn(C)] e: i32 + #[deny(unused_mut)] d: i32, + #[forbid(unused_mut)] #[warn(unused_mut)] _e: i32 ) {} -// self, &self and &mut self +// self struct SelfStruct {} impl SelfStruct { fn foo( - #[allow(C)] self, + #[allow(unused_mut)] self, #[cfg(something)] a: i32, #[cfg_attr(something, cfg(nothing))] - #[deny(C)] b: i32, + #[deny(unused_mut)] b: i32, ) {} } struct RefStruct {} impl RefStruct { fn foo( - #[allow(C)] &self, + #[allow(unused_mut)] &self, #[cfg(something)] a: i32, #[cfg_attr(something, cfg(nothing))] - #[deny(C)] b: i32, + #[deny(unused_mut)] b: i32, ) {} } trait RefTrait { fn foo( - #[forbid(C)] &self, - #[warn(C)] a: i32 + #[forbid(unused_mut)] &self, + #[warn(unused_mut)] a: i32 ) {} } impl RefTrait for RefStruct { fn foo( - #[forbid(C)] &self, - #[warn(C)] 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 + #[forbid(unused_mut)] &self, + #[warn(unused_mut)] a: i32 ) {} } @@ -192,22 +69,22 @@ impl NamedLifetimeMutTrait for NamedLifetimeMutStruct { struct BoxSelfStruct {} impl BoxSelfStruct { fn foo( - #[allow(C)] self: Box, + #[allow(unused_mut)] self: Box, #[cfg(something)] a: i32, #[cfg_attr(something, cfg(nothing))] - #[deny(C)] b: i32, + #[deny(unused_mut)] b: i32, ) {} } trait BoxSelfTrait { fn foo( - #[forbid(C)] self: Box, - #[warn(C)] a: i32 + #[forbid(unused_mut)] self: Box, + #[warn(unused_mut)] a: i32 ) {} } impl BoxSelfTrait for BoxSelfStruct { fn foo( - #[forbid(C)] self: Box, - #[warn(C)] a: i32 + #[forbid(unused_mut)] self: Box, + #[warn(unused_mut)] a: i32 ) {} } @@ -216,10 +93,10 @@ fn main() { let _: fn(_, _, _, _) = foo; let _: FnType = |_, _, _, _| {}; let c = | - #[allow(C)] a: u32, + #[allow(unused_mut)] a: u32, #[cfg(something)] b: i32, #[cfg_attr(something, cfg(nothing))] - #[deny(C)] c: i32, + #[deny(unused_mut)] c: i32, | {}; let _ = c(1, 2); } diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs index 977b5d9ce3495..069332ffa255f 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -1,6 +1,7 @@ // compile-flags: --cfg something +// edition:2018 -#![feature(param_attrs)] +#![feature(async_await, async_closure, param_attrs)] #![deny(unused_variables)] extern "C" { @@ -19,24 +20,35 @@ type FnType = fn( #[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( #[cfg(nothing)] a: i32, #[cfg(something)] b: i32, - //~^ ERROR unused variable: `b` [unused_variables] + //~^ ERROR unused variable: `b` #[cfg_attr(nothing, cfg(nothing))] c: i32, - //~^ ERROR unused variable: `c` [unused_variables] + //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} struct RefStruct {} impl RefStruct { + async fn bar_async( + &self, + #[cfg(something)] a: i32, + //~^ ERROR unused variable: `a` + #[cfg(nothing)] b: i32, + ) {} fn bar( &self, #[cfg(nothing)] a: i32, #[cfg(something)] b: i32, - //~^ ERROR unused variable: `b` [unused_variables] + //~^ ERROR unused variable: `b` #[cfg_attr(nothing, cfg(nothing))] c: i32, - //~^ ERROR unused variable: `c` [unused_variables] + //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} } @@ -45,9 +57,9 @@ trait RefTrait { &self, #[cfg(nothing)] a: i32, #[cfg(something)] b: i32, - //~^ ERROR unused variable: `b` [unused_variables] + //~^ ERROR unused variable: `b` #[cfg_attr(nothing, cfg(nothing))] c: i32, - //~^ ERROR unused variable: `c` [unused_variables] + //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} } @@ -56,9 +68,9 @@ impl RefTrait for RefStruct { &self, #[cfg(nothing)] a: i32, #[cfg(something)] b: i32, - //~^ ERROR unused variable: `b` [unused_variables] + //~^ ERROR unused variable: `b` #[cfg_attr(nothing, cfg(nothing))] c: i32, - //~^ ERROR unused variable: `c` [unused_variables] + //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, ) {} } @@ -67,13 +79,19 @@ fn main() { let _: unsafe extern "C" fn(_, ...) = ffi; let _: fn(_, _) = foo; let _: FnType = |_, _| {}; + let a = async move | + #[cfg(something)] a: i32, + //~^ ERROR unused variable: `a` + #[cfg(nothing)] b: i32, + | {}; let c = | #[cfg(nothing)] a: i32, #[cfg(something)] b: i32, - //~^ ERROR unused variable: `b` [unused_variables] + //~^ ERROR unused variable: `b` #[cfg_attr(nothing, cfg(nothing))] c: i32, - //~^ ERROR unused variable: `c` [unused_variables] + //~^ ERROR unused variable: `c` #[cfg_attr(something, cfg(nothing))] d: i32, | {}; + let _ = a(1); let _ = c(1, 2); } diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr index c97190324e5a2..3232e2a0411a2 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.stderr @@ -1,68 +1,86 @@ -error: unused variable: `b` +error: unused variable: `a` --> $DIR/param-attrs-cfg.rs:24:23 | -LL | #[cfg(something)] b: i32, - | ^ help: consider prefixing with an underscore: `_b` +LL | #[cfg(something)] a: i32, + | ^ help: consider prefixing with an underscore: `_a` | note: lint level defined here - --> $DIR/param-attrs-cfg.rs:4:9 + --> $DIR/param-attrs-cfg.rs:5:9 | 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` - --> $DIR/param-attrs-cfg.rs:26:40 + --> $DIR/param-attrs-cfg.rs:32:40 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ 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` - --> $DIR/param-attrs-cfg.rs:72:27 + --> $DIR/param-attrs-cfg.rs:89:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` 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, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:47:27 + --> $DIR/param-attrs-cfg.rs:59:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` 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:36:27 + --> $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:38:44 + --> $DIR/param-attrs-cfg.rs:50:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` error: unused variable: `b` - --> $DIR/param-attrs-cfg.rs:58:27 + --> $DIR/param-attrs-cfg.rs:70:27 | LL | #[cfg(something)] b: i32, | ^ help: consider prefixing with an underscore: `_b` error: unused variable: `c` - --> $DIR/param-attrs-cfg.rs:60:44 + --> $DIR/param-attrs-cfg.rs:72:44 | LL | #[cfg_attr(nothing, cfg(nothing))] c: i32, | ^ help: consider prefixing with an underscore: `_c` -error: aborting due to 10 previous errors +error: aborting due to 13 previous errors diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs index c5a6514efb0f0..a7f4855915b24 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.rs @@ -1,12 +1,14 @@ // gate-test-param_attrs +#![deny(unused_variables)] + fn foo( /// Foo //~^ ERROR documentation comments cannot be applied to function parameters //~| NOTE doc comments are not allowed here //~| ERROR attributes on function parameters are unstable //~| 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 //~| NOTE https://github.com/rust-lang/rust/issues/60406 ) {} diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr index 704c41f0fa641..0bb9d05dca0ac 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-feature-gate.stderr @@ -1,11 +1,11 @@ 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 | ^^^^^^^ doc comments are not allowed here 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 | ^^^^^^^ @@ -14,10 +14,10 @@ LL | /// Foo = help: add `#![feature(param_attrs)]` to the crate attributes to enable 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 = help: add `#![feature(param_attrs)]` to the crate attributes to enable From a93f4abe24019e2dbe1e8f9bffae01d91d5079e0 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 27 Jul 2019 18:42:47 -0400 Subject: [PATCH 06/11] Update wording --- src/libcore/mem/manually_drop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index d6907000ffc4a..bb35399323628 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -118,7 +118,8 @@ impl ManuallyDrop { /// /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the - /// uninitialized data is not actually used, and that this function is called at most once + /// uninitialized data is not actually used. + /// In particular, this function can only be called called at most once /// for a given instance of `ManuallyDrop`. /// /// [`ManuallyDrop::into_inner`]: #method.into_inner From 55c07b39ae89408c08de4781b2051cc4c7cc7b20 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sat, 27 Jul 2019 21:46:18 +0100 Subject: [PATCH 07/11] SystemTime docs: recommend Instant for elapsed time --- src/libstd/time.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index dc97f8c04a839..98371b9ba3d7e 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -396,6 +396,7 @@ impl SystemTime { /// This function may fail because measurements taken earlier are not /// guaranteed to always be before later measurements (due to anomalies such /// as the system clock being adjusted either forwards or backwards). + /// [`Instant`] can be used to measure elapsed time without this risk of failure. /// /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents /// the amount of time elapsed from the specified measurement to this one. @@ -406,6 +407,7 @@ impl SystemTime { /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok /// [`Duration`]: ../../std/time/struct.Duration.html /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Instant`]: ../../std/time/struct.Instant.html /// /// # Examples /// @@ -414,7 +416,7 @@ impl SystemTime { /// /// let sys_time = SystemTime::now(); /// let difference = sys_time.duration_since(sys_time) - /// .expect("SystemTime::duration_since failed"); + /// .expect("Clock may have gone backwards"); /// println!("{:?}", difference); /// ``` #[stable(feature = "time2", since = "1.8.0")] @@ -423,7 +425,8 @@ impl SystemTime { self.0.sub_time(&earlier.0).map_err(SystemTimeError) } - /// Returns the amount of time elapsed since this system time was created. + /// Returns the difference between the clock time when this + /// system time was created, and the current clock time. /// /// This function may fail as the underlying system clock is susceptible to /// drift and updates (e.g., the system clock could go backwards), so this @@ -431,12 +434,15 @@ impl SystemTime { /// returned where the duration represents the amount of time elapsed from /// this time measurement to the current time. /// + /// To measure elapsed time reliably, use [`Instant`] instead. + /// /// Returns an [`Err`] if `self` is later than the current system time, and /// the error contains how far from the current system time `self` is. /// /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok /// [`Duration`]: ../../std/time/struct.Duration.html /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Instant`]: ../../std/time/struct.Instant.html /// /// # Examples /// From 61729b3bf0e439ebe6cd785b3e6ae02ab24592c0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 28 Jul 2019 14:36:26 +0300 Subject: [PATCH 08/11] tidy: Cleanup the directory whitelist --- .../owning_ref/mod.rs | 12 ++++++----- .../owning_ref/tests.rs | 20 ++++++++++++++----- src/tools/tidy/src/lib.rs | 20 ++++--------------- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index a7af615fa5000..e9b33c13ff8a9 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -10,7 +10,7 @@ This allows moving and dropping of a `OwningRef` without needing to recreate the This can sometimes be useful because Rust borrowing rules normally prevent moving a type that has been moved from. For example, this kind of code gets rejected: -```rust,ignore +```compile_fail,E0515 fn return_owned_and_referenced<'a>() -> (Vec, &'a [u8]) { let v = vec![1, 2, 3, 4]; let s = &v[1..3]; @@ -43,7 +43,8 @@ and preventing mutable access to root containers, which in practice requires hea as provided by `Box`, `Rc`, etc. Also provided are typedefs for common owner type combinations, -which allow for less verbose type signatures. For example, `BoxRef` instead of `OwningRef, T>`. +which allow for less verbose type signatures. +For example, `BoxRef` instead of `OwningRef, T>`. The crate also provides the more advanced `OwningHandle` type, which allows more freedom in bundling a dependent handle object @@ -495,7 +496,8 @@ impl OwningRef { } } - /// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`. + /// Erases the concrete base type of the owner with a trait object + /// which implements `Send` and `Sync`. /// /// This allows mixing of owned references with different owner base types. pub fn erase_send_sync_owner<'a>(self) -> OwningRef @@ -507,7 +509,7 @@ impl OwningRef { } } - // TODO: wrap_owner + // UNIMPLEMENTED: wrap_owner // FIXME: Naming convention? /// A getter for the underlying owner. @@ -753,7 +755,7 @@ impl OwningRefMut { } } - // TODO: wrap_owner + // UNIMPLEMENTED: wrap_owner // FIXME: Naming convention? /// A getter for the underlying owner. diff --git a/src/librustc_data_structures/owning_ref/tests.rs b/src/librustc_data_structures/owning_ref/tests.rs index d368219cab3eb..5bff5e035b529 100644 --- a/src/librustc_data_structures/owning_ref/tests.rs +++ b/src/librustc_data_structures/owning_ref/tests.rs @@ -274,7 +274,9 @@ mod owning_handle { use std::cell::RefCell; let cell = Rc::new(RefCell::new(2)); let cell_ref = RcRef::new(cell); - let mut handle = OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + let mut handle = OwningHandle::new_with_fn(cell_ref, |x| { + unsafe { x.as_ref() }.unwrap().borrow_mut() + }); assert_eq!(*handle, 2); *handle = 3; assert_eq!(*handle, 3); @@ -319,8 +321,12 @@ mod owning_handle { let result = { let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); + let curr = OwningHandle::new_with_fn(curr, |x| { + unsafe { x.as_ref() }.unwrap().borrow_mut() + }); + let mut curr = OwningHandle::new_with_fn(curr, |x| { + unsafe { x.as_ref() }.unwrap().try_write().unwrap() + }); assert_eq!(*curr, "someString"); *curr = "someOtherString"; curr @@ -353,8 +359,12 @@ mod owning_handle { let result = { let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); let curr = RcRef::new(complex); - let curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); - let mut curr = OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); + let curr = OwningHandle::new_with_fn(curr, |x| { + unsafe { x.as_ref() }.unwrap().borrow_mut() + }); + let mut curr = OwningHandle::new_with_fn(curr, |x| { + unsafe { x.as_ref() }.unwrap().try_write().unwrap() + }); assert_eq!(*curr, "someString"); *curr = "someOtherString"; curr diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 3d40bdced63e0..eca8001a9d2a1 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -43,31 +43,19 @@ pub mod unstable_book; fn filter_dirs(path: &Path) -> bool { let skip = [ - "src/llvm", - "src/llvm-project", "src/llvm-emscripten", - "src/libbacktrace", - "src/librustc_data_structures/owning_ref", - "src/vendor", + "src/llvm-project", + "src/stdarch", "src/tools/cargo", - "src/tools/clang", - "src/tools/rls", "src/tools/clippy", + "src/tools/miri", + "src/tools/rls", "src/tools/rust-installer", "src/tools/rustfmt", - "src/tools/miri", - "src/tools/lld", - "src/tools/lldb", - "src/target", - "src/stdarch", - "src/rust-sgx", - "target", - "vendor", ]; skip.iter().any(|p| path.ends_with(p)) } - fn walk_many( paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&DirEntry, &str) ) { From 4b1d404d833929dffcc1ea8d704aa3d2c432ba11 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 23 Jul 2019 19:50:53 +0100 Subject: [PATCH 09/11] Better recursive async fn error message. Co-Authored-By: Mazdak Farrokhzad --- src/librustc_typeck/check/mod.rs | 40 +++++++++++----- src/librustc_typeck/error_codes.rs | 46 +++++++++++++++++++ .../recursive-async-impl-trait-type.stderr | 8 ++-- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 21cd4b694ae4c..09fe92415b91a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1325,19 +1325,35 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { check_packed(tcx, span, def_id); } -fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, span: Span) { +fn check_opaque<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + span: Span, + origin: &hir::ExistTyOrigin +) { if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) { - let mut err = struct_span_err!( - tcx.sess, span, E0720, - "opaque type expands to a recursive type", - ); - err.span_label(span, "expands to a recursive type"); - if let ty::Opaque(..) = partially_expanded_type.sty { - err.note("type resolves to itself"); + if let hir::ExistTyOrigin::AsyncFn = origin { + struct_span_err!( + tcx.sess, span, E0733, + "recursion in an `async fn` requires boxing", + ) + .span_label(span, "an `async fn` cannot invoke itself directly") + .note("a recursive `async fn` must be rewritten to return a boxed future.") + .emit(); } else { - err.note(&format!("expanded type is `{}`", partially_expanded_type)); + let mut err = struct_span_err!( + tcx.sess, span, E0720, + "opaque type expands to a recursive type", + ); + err.span_label(span, "expands to a recursive type"); + if let ty::Opaque(..) = partially_expanded_type.sty { + err.note("type resolves to itself"); + } else { + err.note(&format!("expanded type is `{}`", partially_expanded_type)); + } + err.emit(); } - err.emit(); } } @@ -1387,11 +1403,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item) { hir::ItemKind::Union(..) => { check_union(tcx, it.hir_id, it.span); } - hir::ItemKind::Existential(..) => { + hir::ItemKind::Existential(hir::ExistTy{origin, ..}) => { let def_id = tcx.hir().local_def_id(it.hir_id); let substs = InternalSubsts::identity_for_item(tcx, def_id); - check_opaque(tcx, def_id, substs, it.span); + check_opaque(tcx, def_id, substs, it.span, &origin); } hir::ItemKind::Ty(..) => { let def_id = tcx.hir().local_def_id(it.hir_id); diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 19d5e8b3e8447..8a6cb90310ab0 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4765,7 +4765,53 @@ assert_eq!(1, discriminant(&Enum::Struct{a: 7, b: 11})); ``` "##, +E0733: r##" +Recursion in an `async fn` requires boxing. For example, this will not compile: + +```edition2018,compile_fail,E0733 +#![feature(async_await)] +async fn foo(n: usize) { + if n > 0 { + foo(n - 1).await; + } +} +``` + +To achieve async recursion, the `async fn` needs to be desugared +such that the `Future` is explicit in the return type: + +```edition2018,compile_fail,E0720 +# #![feature(async_await)] +use std::future::Future; +fn foo_desugered(n: usize) -> impl Future { + async move { + if n > 0 { + foo_desugered(n - 1).await; + } + } +} +``` + +Finally, the future is wrapped in a pinned box: + +```edition2018 +# #![feature(async_await)] +use std::future::Future; +use std::pin::Pin; +fn foo_recursive(n: usize) -> Pin>> { + Box::pin(async move { + if n > 0 { + foo_recursive(n - 1).await; + } + }) } +``` + +The `Box<...>` ensures that the result is of known size, +and the pin is required to keep it in the same place in memory. +"##, + +} // (end of detailed error messages) register_diagnostics! { // E0035, merged into E0087/E0089 diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr index 69914b6a7910f..64f6eccd5479a 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr @@ -1,11 +1,11 @@ -error[E0720]: opaque type expands to a recursive type +error[E0733]: recursion in an `async fn` requires boxing --> $DIR/recursive-async-impl-trait-type.rs:7:40 | LL | async fn recursive_async_function() -> () { - | ^^ expands to a recursive type + | ^^ an `async fn` cannot invoke itself directly | - = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>` + = note: a recursive `async fn` must be rewritten to return a boxed future. error: aborting due to previous error -For more information about this error, try `rustc --explain E0720`. +For more information about this error, try `rustc --explain E0733`. From 6fd6972e8b2ba9743b2bfffdcda07b78d67516c2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 28 Jul 2019 10:17:19 -0700 Subject: [PATCH 10/11] Remove anonymous_parameters from unrelated test --- src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs b/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs index 4e85bcc4ba623..141f363694ab6 100644 --- a/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs +++ b/src/test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs @@ -9,7 +9,7 @@ pub trait LolInto: Sized { } pub trait LolFrom { - fn from(T) -> Self; + fn from(_: T) -> Self; } impl<'a, T: ?Sized, U> LolInto for &'a T where T: LolTo { From 3f4dbd390c9d8f56bcf9a37f94985ef10471b994 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 28 Jul 2019 20:24:52 +0200 Subject: [PATCH 11/11] Update minifier-rs version --- Cargo.lock | 6 +++--- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/html/render.rs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 312f05d6e730e..c08d7444d14ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "minifier" -version = "0.0.30" +version = "0.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3195,7 +3195,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4442,7 +4442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum minifier 0.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "4c909e78edf61f3aa0dd2086da168cdf304329044bbf248768ca3d20253ec8c0" +"checksum minifier 0.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "70bf0db2475f5e627787da77ca52fe33c294063f49f4134b8bc662eedb5e7332" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index ce0d82ec7b105..334dc74c6c8f7 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.5.3", default-features = false } -minifier = "0.0.30" +minifier = "0.0.33" rayon = { version = "0.2.0", package = "rustc-rayon" } tempfile = "3" parking_lot = "0.7" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 6270ed3785905..87c6a0b423578 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1322,13 +1322,13 @@ fn write_minify_replacer( { let tokens: Tokens<'_> = simple_minify(contents) .into_iter() - .filter(|f| { + .filter(|(f, next)| { // We keep backlines. - minifier::js::clean_token_except(f, &|c: &Token<'_>| { + minifier::js::clean_token_except(f, next, &|c: &Token<'_>| { c.get_char() != Some(ReservedChar::Backline) }) }) - .map(|f| { + .map(|(f, _)| { minifier::js::replace_token_with(f, &|t: &Token<'_>| { match *t { Token::Keyword(Keyword::Null) => Some(Token::Other("N")), @@ -1363,7 +1363,7 @@ fn write_minify_replacer( // shouldn't be aggregated. |tokens, pos| { pos < 2 || - !tokens[pos - 1].is_char(ReservedChar::OpenBracket) || + !tokens[pos - 1].eq_char(ReservedChar::OpenBracket) || tokens[pos - 2].get_other() != Some("searchIndex") } )