}
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
+ lint_callback!(self, enter_where_predicate, p);
ast_visit::walk_where_predicate(self, p);
+ lint_callback!(self, exit_where_predicate, p);
}
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
[
pub BuiltinCombinedEarlyLintPass,
[
- UnusedParens: UnusedParens,
+ UnusedParens: UnusedParens::new(),
UnusedBraces: UnusedBraces,
UnusedImportBraces: UnusedImportBraces,
UnsafeCode: UnsafeCode,
/// Counterpart to `enter_lint_attrs`.
fn exit_lint_attrs(a: &[ast::Attribute]);
+
+ fn enter_where_predicate(a: &ast::WherePredicate);
+ fn exit_where_predicate(a: &ast::WherePredicate);
]);
)
}
"`if`, `match`, `while` and `return` do not need parentheses"
}
-declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
+pub struct UnusedParens {
+ with_self_ty_parens: bool,
+}
+
+impl UnusedParens {
+ pub fn new() -> Self {
+ Self { with_self_ty_parens: false }
+ }
+}
+
+impl_lint_pass!(UnusedParens => [UNUSED_PARENS]);
impl UnusedDelimLint for UnusedParens {
const DELIM_STR: &'static str = "parentheses";
}
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
- if let ast::TyKind::Paren(r) = &ty.kind {
- match &r.kind {
- ast::TyKind::TraitObject(..) => {}
- ast::TyKind::BareFn(b) if b.generic_params.len() > 0 => {}
- ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
- ast::TyKind::Array(_, len) => {
- self.check_unused_delims_expr(
- cx,
- &len.value,
- UnusedDelimsCtx::ArrayLenExpr,
- false,
- None,
- None,
- );
- }
- _ => {
- let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
- Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
- } else {
- None
- };
- self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
+ match &ty.kind {
+ ast::TyKind::Array(_, len) => {
+ self.check_unused_delims_expr(
+ cx,
+ &len.value,
+ UnusedDelimsCtx::ArrayLenExpr,
+ false,
+ None,
+ None,
+ );
+ }
+ ast::TyKind::Paren(r) => {
+ match &r.kind {
+ ast::TyKind::TraitObject(..) => {}
+ ast::TyKind::BareFn(b)
+ if self.with_self_ty_parens && b.generic_params.len() > 0 => {}
+ ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
+ _ => {
+ let spans = if let Some(r) = r.span.find_ancestor_inside(ty.span) {
+ Some((ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi())))
+ } else {
+ None
+ };
+ self.emit_unused_delims(cx, ty.span, spans, "type", (false, false));
+ }
}
+ self.with_self_ty_parens = false;
}
+ _ => {}
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
<Self as UnusedDelimLint>::check_item(self, cx, item)
}
+
+ fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) {
+ use rustc_ast::{WhereBoundPredicate, WherePredicate};
+ if let WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bounded_ty,
+ bound_generic_params,
+ ..
+ }) = pred &&
+ let ast::TyKind::Paren(_) = &bounded_ty.kind &&
+ bound_generic_params.is_empty() {
+ self.with_self_ty_parens = true;
+ }
+ }
+
+ fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) {
+ assert!(!self.with_self_ty_parens);
+ }
}
declare_lint! {
static_assert!(align_of::<SimpleMessage>() >= TAG_MASK + 1);
static_assert!(align_of::<Custom>() >= TAG_MASK + 1);
-static_assert!(@usize_eq: (TAG_MASK & TAG_SIMPLE_MESSAGE), TAG_SIMPLE_MESSAGE);
-static_assert!(@usize_eq: (TAG_MASK & TAG_CUSTOM), TAG_CUSTOM);
-static_assert!(@usize_eq: (TAG_MASK & TAG_OS), TAG_OS);
-static_assert!(@usize_eq: (TAG_MASK & TAG_SIMPLE), TAG_SIMPLE);
+static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE_MESSAGE, TAG_SIMPLE_MESSAGE);
+static_assert!(@usize_eq: TAG_MASK & TAG_CUSTOM, TAG_CUSTOM);
+static_assert!(@usize_eq: TAG_MASK & TAG_OS, TAG_OS);
+static_assert!(@usize_eq: TAG_MASK & TAG_SIMPLE, TAG_SIMPLE);
// This is obviously true (`TAG_CUSTOM` is `0b01`), but in `Repr::new_custom` we
// offset a pointer by this value, and expect it to both be within the same
--- /dev/null
+#![warn(unused)]
+#![deny(warnings)]
+
+fn main() {
+ let _x: ([u32; 3]); //~ ERROR unnecessary parentheses around type
+ let _y: [u8; (3)]; //~ ERROR unnecessary parentheses around const expression
+ let _z: ([u8; (3)]);
+ //~^ ERROR unnecessary parentheses around const expression
+ //~| ERROR unnecessary parentheses around type
+
+}
--- /dev/null
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-array-lint.rs:5:13
+ |
+LL | let _x: ([u32; 3]);
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061-array-lint.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - let _x: ([u32; 3]);
+LL + let _x: [u32; 3];
+ |
+
+error: unnecessary parentheses around const expression
+ --> $DIR/issue-105061-array-lint.rs:6:18
+ |
+LL | let _y: [u8; (3)];
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _y: [u8; (3)];
+LL + let _y: [u8; 3];
+ |
+
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-array-lint.rs:7:13
+ |
+LL | let _z: ([u8; (3)]);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _z: ([u8; (3)]);
+LL + let _z: [u8; (3)];
+ |
+
+error: unnecessary parentheses around const expression
+ --> $DIR/issue-105061-array-lint.rs:7:19
+ |
+LL | let _z: ([u8; (3)]);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _z: ([u8; (3)]);
+LL + let _z: ([u8; 3]);
+ |
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait<'a> {}
+impl<'b> Trait<'b> for for<'a> fn(Inv<'a>) {}
+
+fn with_bound()
+where
+ for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, //~ ERROR unnecessary parentheses around type
+{}
+
+trait Hello<T> {}
+fn with_dyn_bound<T>()
+where
+ (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> //~ ERROR unnecessary parentheses around type
+{}
+
+fn main() {
+ with_bound();
+ with_dyn_bound();
+}
--- /dev/null
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-should-lint.rs:11:13
+ |
+LL | for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>,
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061-should-lint.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>,
+LL + for<'b> for<'a> fn(Inv<'a>): Trait<'b>,
+ |
+
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-should-lint.rs:17:16
+ |
+LL | (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T>
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T>
+LL + (dyn Hello<for<'b> fn(&'b ())>): Hello<T>
+ |
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait {}
+impl Trait for (for<'a> fn(Inv<'a>),) {}
+
+
+fn with_bound()
+where
+ ((for<'a> fn(Inv<'a>)),): Trait, //~ ERROR unnecessary parentheses around type
+{}
+
+fn main() {
+ with_bound();
+}
--- /dev/null
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061.rs:12:6
+ |
+LL | ((for<'a> fn(Inv<'a>)),): Trait,
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - ((for<'a> fn(Inv<'a>)),): Trait,
+LL + (for<'a> fn(Inv<'a>),): Trait,
+ |
+
+error: aborting due to previous error
+