From c8619ae7916459bec1b7e5583d75c69b10f06df9 Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Sun, 25 Aug 2019 00:09:12 +0200 Subject: [PATCH 1/9] Document platform-specific behavior of the iterator returned by std::fs::read_dir --- src/libstd/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 5f76875bd66c4..90d911a6f9ac0 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1956,7 +1956,8 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// # Platform-specific behavior /// /// This function currently corresponds to the `opendir` function on Unix -/// and the `FindFirstFile` function on Windows. +/// and the `FindFirstFile` function on Windows. Advancing the iterator +/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: ../io/index.html#platform-specific-behavior From ab73b325b0e1288656f69ee24acb822fe91bc6a0 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 5 Sep 2019 20:51:22 +0200 Subject: [PATCH 2/9] save-analysis: Nest typeck tables when processing functions/methods Fixes an issue where we did not nest tables correctly when resolving associated types in formal argument/return type positions --- src/librustc_save_analysis/dump_visitor.rs | 80 ++++++++++------------ 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 12c5ce12a0e8b..135f13499436c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -283,36 +283,32 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ) { debug!("process_method: {}:{}", id, ident); - if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) { - let sig_str = crate::make_signature(&sig.decl, &generics); - if body.is_some() { - self.nest_tables( - id, - |v| v.process_formals(&sig.decl.inputs, &method_data.qualname), - ); - } + let hir_id = self.tcx.hir().node_to_hir_id(id); + self.nest_tables(id, |v| { + if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) { + v.process_formals(&sig.decl.inputs, &method_data.qualname); + v.process_generic_params(&generics, &method_data.qualname, id); - self.process_generic_params(&generics, &method_data.qualname, id); + method_data.value = crate::make_signature(&sig.decl, &generics); + method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt); - method_data.value = sig_str; - method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt); - let hir_id = self.tcx.hir().node_to_hir_id(id); - self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data); - } + v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data); + } - // walk arg and return types - for arg in &sig.decl.inputs { - self.visit_ty(&arg.ty); - } + // walk arg and return types + for arg in &sig.decl.inputs { + v.visit_ty(&arg.ty); + } - if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output { - self.visit_ty(ret_ty); - } + if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output { + v.visit_ty(ret_ty); + } - // walk the fn body - if let Some(body) = body { - self.nest_tables(id, |v| v.visit_block(body)); - } + // walk the fn body + if let Some(body) = body { + v.visit_block(body); + } + }); } fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) { @@ -377,26 +373,26 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ty_params: &'l ast::Generics, body: &'l ast::Block, ) { - if let Some(fn_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(fn_data, DefData, item.span); - self.nest_tables( - item.id, - |v| v.process_formals(&decl.inputs, &fn_data.qualname), - ); - self.process_generic_params(ty_params, &fn_data.qualname, item.id); - let hir_id = self.tcx.hir().node_to_hir_id(item.id); - self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data); - } + let hir_id = self.tcx.hir().node_to_hir_id(item.id); + self.nest_tables(item.id, |v| { + if let Some(fn_data) = v.save_ctxt.get_item_data(item) { + down_cast_data!(fn_data, DefData, item.span); + v.process_formals(&decl.inputs, &fn_data.qualname); + v.process_generic_params(ty_params, &fn_data.qualname, item.id); - for arg in &decl.inputs { - self.visit_ty(&arg.ty); - } + v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data); + } - if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { - self.visit_ty(&ret_ty); - } + for arg in &decl.inputs { + v.visit_ty(&arg.ty) + } - self.nest_tables(item.id, |v| v.visit_block(&body)); + if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { + v.visit_ty(&ret_ty); + } + + v.visit_block(&body); + }); } fn process_static_or_const_item( From b456c820ffe6f19d133f196d3e935071f326094e Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 8 Sep 2019 21:19:47 +0200 Subject: [PATCH 3/9] Always validate HIR ID for TypeckTables Performance shouldn't be impacted (see [1] for a perf run) and this should allow us to catch more bugs, e.g. [2] and [3]. [1]: https://github.com/rust-lang/rust/pull/64262 [2]: https://github.com/rust-lang/rust/pull/64250 [3]: https://github.com/rust-lang/rust/issues/57298 --- src/librustc/ty/context.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 8e8472a5aacc9..7366037c5eb96 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -205,26 +205,24 @@ pub struct LocalTableInContext<'a, V> { fn validate_hir_id_for_typeck_tables(local_id_root: Option, hir_id: hir::HirId, mut_access: bool) { - if cfg!(debug_assertions) { - if let Some(local_id_root) = local_id_root { - if hir_id.owner != local_id_root.index { - ty::tls::with(|tcx| { - bug!("node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", - tcx.hir().node_to_string(hir_id), - DefId::local(hir_id.owner), - local_id_root) - }); - } - } else { - // We use "Null Object" TypeckTables in some of the analysis passes. - // These are just expected to be empty and their `local_id_root` is - // `None`. Therefore we cannot verify whether a given `HirId` would - // be a valid key for the given table. Instead we make sure that - // nobody tries to write to such a Null Object table. - if mut_access { - bug!("access to invalid TypeckTables") - } + if let Some(local_id_root) = local_id_root { + if hir_id.owner != local_id_root.index { + ty::tls::with(|tcx| { + bug!("node {} with HirId::owner {:?} cannot be placed in \ + TypeckTables with local_id_root {:?}", + tcx.hir().node_to_string(hir_id), + DefId::local(hir_id.owner), + local_id_root) + }); + } + } else { + // We use "Null Object" TypeckTables in some of the analysis passes. + // These are just expected to be empty and their `local_id_root` is + // `None`. Therefore we cannot verify whether a given `HirId` would + // be a valid key for the given table. Instead we make sure that + // nobody tries to write to such a Null Object table. + if mut_access { + bug!("access to invalid TypeckTables") } } } From 6117faa809334136f81c90b6645ae760d50b48cd Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 8 Sep 2019 21:48:08 +0200 Subject: [PATCH 4/9] save-analysis: Add a related test case --- src/test/ui/save-analysis/issue-63663.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/ui/save-analysis/issue-63663.rs diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs new file mode 100644 index 0000000000000..ccbe13f1a1b71 --- /dev/null +++ b/src/test/ui/save-analysis/issue-63663.rs @@ -0,0 +1,23 @@ +// check-pass +// compile-flags: -Zsave-analysis + +// Check that this doesn't ICE when processing associated const in formal +// argument and return type of functions defined inside function/method scope. + +pub trait Trait { + type Assoc; +} + +pub struct A; + +pub fn func() { + fn _inner1(_: U::Assoc) {} + fn _inner2() -> U::Assoc { unimplemented!() } + + impl A { + fn _inner1(self, _: U::Assoc) {} + fn _inner2(self) -> U::Assoc { unimplemented!() } + } +} + +fn main() {} From b4151dd3211f4a9e8f980994a094f4b85149cd46 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 13 Sep 2019 15:36:38 +0200 Subject: [PATCH 5/9] save-analysis: Use process_bounds when processing opaque impl item type ...since the code is literally the same and does the same thing. --- src/librustc_save_analysis/dump_visitor.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 135f13499436c..28d8e3a4296ad 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1109,11 +1109,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. - for bound in bounds.iter() { - if let ast::GenericBound::Trait(trait_ref, _) = bound { - self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) - } - } + self.process_bounds(&bounds); } ast::ImplItemKind::Macro(_) => {} } From 0fafd615e5f56a98a0c1c21c88fc6352540926b2 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 13 Sep 2019 15:41:10 +0200 Subject: [PATCH 6/9] save-analysis: Visit bounds in opaque types --- src/librustc_save_analysis/dump_visitor.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 28d8e3a4296ad..fb1003fd7055d 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1356,10 +1356,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ty); self.process_generic_params(ty_params, &qualname, item.id); } - OpaqueTy(ref _bounds, ref ty_params) => { + OpaqueTy(ref bounds, ref ty_params) => { let qualname = format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))); - // FIXME do something with _bounds + let value = String::new(); if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); @@ -1385,6 +1385,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { ); } + self.process_bounds(bounds); self.process_generic_params(ty_params, &qualname, item.id); } Mac(_) => (), From 30e39e871fa9064f310d05a295a6c197d9b0da78 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 14 Sep 2019 20:53:42 +0200 Subject: [PATCH 7/9] save-analysis: Deduplicate lookup_{d,r}ef_id functions --- src/librustc_save_analysis/dump_visitor.rs | 11 ++++------- src/librustc_save_analysis/lib.rs | 8 ++++---- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index fb1003fd7055d..c43e07a8c7480 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -130,6 +130,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.save_ctxt.span_from_span(span) } + fn lookup_def_id(&self, ref_id: NodeId) -> Option { + self.save_ctxt.lookup_def_id(ref_id) + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -223,13 +227,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } } - fn lookup_def_id(&self, ref_id: NodeId) -> Option { - match self.save_ctxt.get_path_res(ref_id) { - Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => None, - def => Some(def.def_id()), - } - } - fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) { for arg in formals { self.visit_pat(&arg.pat); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4bc098db68611..055ccf6c2c4f8 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -312,7 +312,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let impl_id = self.next_impl_id(); let span = self.span_from_span(sub_span); - let type_data = self.lookup_ref_id(typ.id); + let type_data = self.lookup_def_id(typ.id); type_data.map(|type_data| { Data::RelationData(Relation { kind: RelationKind::Impl { @@ -322,7 +322,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { from: id_from_def_id(type_data), to: trait_ref .as_ref() - .and_then(|t| self.lookup_ref_id(t.ref_id)) + .and_then(|t| self.lookup_def_id(t.ref_id)) .map(id_from_def_id) .unwrap_or_else(|| null_id()), }, @@ -495,7 +495,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option { - self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { + self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; if generated_code(span) { return None; @@ -870,7 +870,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { }) } - fn lookup_ref_id(&self, ref_id: NodeId) -> Option { + fn lookup_def_id(&self, ref_id: NodeId) -> Option { match self.get_path_res(ref_id) { Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None, def => Some(def.def_id()), From a946b8d6e1ff39f22e3f9f1c46ba81898901d907 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 15 Sep 2019 00:42:18 +0200 Subject: [PATCH 8/9] save-analysis: Process bounds in impl trait only in argument position --- src/librustc_save_analysis/dump_visitor.rs | 19 ++++++++++++++++++- src/test/ui/save-analysis/issue-63663.rs | 11 ++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index c43e07a8c7480..55f6b91e71431 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -385,7 +385,12 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { - v.visit_ty(&ret_ty); + if let ast::TyKind::ImplTrait(..) = ret_ty.node { + // FIXME: Opaque type desugaring prevents us from easily + // processing trait bounds. See `visit_ty` for more details. + } else { + v.visit_ty(&ret_ty); + } } v.visit_block(&body); @@ -1439,6 +1444,18 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(element); self.nest_tables(length.id, |v| v.visit_expr(&length.value)); } + ast::TyKind::ImplTrait(id, ref bounds) => { + // FIXME: As of writing, the opaque type lowering introduces + // another DefPath scope/segment (used to declare the resulting + // opaque type item). + // However, the synthetic scope does *not* have associated + // typeck tables, which means we can't nest it and we fire an + // assertion when resolving the qualified type paths in trait + // bounds... + // This will panic if called on return type `impl Trait`, which + // we guard against in `process_fn`. + self.nest_tables(id, |v| v.process_bounds(bounds)); + } _ => visit::walk_ty(self, t), } } diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs index ccbe13f1a1b71..92e85884f664d 100644 --- a/src/test/ui/save-analysis/issue-63663.rs +++ b/src/test/ui/save-analysis/issue-63663.rs @@ -1,15 +1,20 @@ // check-pass // compile-flags: -Zsave-analysis -// Check that this doesn't ICE when processing associated const in formal -// argument and return type of functions defined inside function/method scope. - pub trait Trait { type Assoc; } pub struct A; +trait Generic {} +impl Generic for () {} + +// Don't ICE when resolving type paths in return type `impl Trait` +fn assoc_in_opaque_type_bounds() -> impl Generic {} + +// Check that this doesn't ICE when processing associated const in formal +// argument and return type of functions defined inside function/method scope. pub fn func() { fn _inner1(_: U::Assoc) {} fn _inner2() -> U::Assoc { unimplemented!() } From 1d33f06de80ce6b473460cdf87566d57f53a0b4e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 14 Sep 2019 18:41:46 -0400 Subject: [PATCH 9/9] Don't mark expression with attributes as not needing parentheses This is not perfectly correct as `#[attr] (5)` will still not lint, but it does seem good enough, in particular as the parentheses in that case are not unambiguously incorrect. --- src/librustc_lint/unused.rs | 3 +- .../ui/lint/issue-54538-unused-parens-lint.rs | 6 +++- .../issue-54538-unused-parens-lint.stderr | 36 +++++++++---------- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 561bf202dfeff..20c05800889cf 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -370,7 +370,8 @@ impl UnusedParens { right_pos: Option) { match value.node { ast::ExprKind::Paren(ref inner) => { - if !Self::is_expr_parens_necessary(inner, followed_by_block) { + if !Self::is_expr_parens_necessary(inner, followed_by_block) && + value.attrs.is_empty() { let expr_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index 1d8cce5228116..7dcbdd0863cbd 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(box_patterns, stmt_expr_attributes)] #![feature(or_patterns)] //~^ WARN the feature `or_patterns` is incomplete @@ -17,6 +17,10 @@ fn lint_on_top_level() { let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern } +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 7d5e286416fe2..675dd4f07def6 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -49,109 +49,109 @@ LL | let _ = |(a): u8| 0; | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:41:12 + --> $DIR/issue-54538-unused-parens-lint.rs:45:12 | LL | if let (0 | 1) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:42:13 + --> $DIR/issue-54538-unused-parens-lint.rs:46:13 | LL | if let ((0 | 1),) = (0,) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:43:13 + --> $DIR/issue-54538-unused-parens-lint.rs:47:13 | LL | if let [(0 | 1)] = [0] {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:44:16 + --> $DIR/issue-54538-unused-parens-lint.rs:48:16 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:46:15 + --> $DIR/issue-54538-unused-parens-lint.rs:50:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:48:20 + --> $DIR/issue-54538-unused-parens-lint.rs:52:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:58:9 + --> $DIR/issue-54538-unused-parens-lint.rs:62:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:59:9 + --> $DIR/issue-54538-unused-parens-lint.rs:63:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:60:9 + --> $DIR/issue-54538-unused-parens-lint.rs:64:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:61:9 + --> $DIR/issue-54538-unused-parens-lint.rs:65:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:67:9 + --> $DIR/issue-54538-unused-parens-lint.rs:71:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:68:10 + --> $DIR/issue-54538-unused-parens-lint.rs:72:10 | LL | &(_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:79:9 + --> $DIR/issue-54538-unused-parens-lint.rs:83:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:80:9 + --> $DIR/issue-54538-unused-parens-lint.rs:84:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:81:9 + --> $DIR/issue-54538-unused-parens-lint.rs:85:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + --> $DIR/issue-54538-unused-parens-lint.rs:86:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:88:9 + --> $DIR/issue-54538-unused-parens-lint.rs:92:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:89:10 + --> $DIR/issue-54538-unused-parens-lint.rs:93:10 | LL | &(_) => {} | ^^^ help: remove these parentheses