mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-17 09:23:05 +00:00
Rollup merge of #70081 - lcnr:issue68387, r=varkor
add `unused_braces` lint Add the lint `unused_braces` which is warn by default. `unused_parens` is also extended and now checks anon consts. closes #68387 r? @varkor
This commit is contained in:
commit
8993358e77
@ -39,7 +39,7 @@ where
|
||||
alive: Range<usize>,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIter<T, { N }>
|
||||
impl<T, const N: usize> IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -99,7 +99,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, { N }>
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -146,7 +146,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, { N }>
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -182,7 +182,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Drop for IntoIter<T, { N }>
|
||||
impl<T, const N: usize> Drop for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -195,7 +195,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, { N }>
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -210,17 +210,17 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
|
||||
|
||||
// The iterator indeed reports the correct length. The number of "alive"
|
||||
// elements (that will still be yielded) is the length of the range `alive`.
|
||||
// This range is decremented in length in either `next` or `next_back`. It is
|
||||
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, { N }>
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
@ -249,7 +249,7 @@ where
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, { N }>
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N>
|
||||
where
|
||||
[T; N]: LengthAtMost32,
|
||||
{
|
||||
|
@ -104,6 +104,11 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
||||
run_early_pass!(self, check_pat_post, p);
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
|
||||
run_early_pass!(self, check_anon_const, c);
|
||||
ast_visit::walk_anon_const(self, c);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
self.with_lint_attrs(e.id, &e.attrs, |cx| {
|
||||
run_early_pass!(cx, check_expr, e);
|
||||
|
@ -104,6 +104,7 @@ macro_rules! early_lint_passes {
|
||||
$args,
|
||||
[
|
||||
UnusedParens: UnusedParens,
|
||||
UnusedBraces: UnusedBraces,
|
||||
UnusedImportBraces: UnusedImportBraces,
|
||||
UnsafeCode: UnsafeCode,
|
||||
AnonymousParameters: AnonymousParameters,
|
||||
@ -275,6 +276,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
|
||||
UNUSED_FEATURES,
|
||||
UNUSED_LABELS,
|
||||
UNUSED_PARENS,
|
||||
UNUSED_BRACES,
|
||||
REDUNDANT_SEMICOLONS
|
||||
);
|
||||
|
||||
|
@ -170,6 +170,7 @@ macro_rules! early_lint_methods {
|
||||
fn check_stmt(a: &ast::Stmt);
|
||||
fn check_arm(a: &ast::Arm);
|
||||
fn check_pat(a: &ast::Pat);
|
||||
fn check_anon_const(a: &ast::AnonConst);
|
||||
fn check_pat_post(a: &ast::Pat);
|
||||
fn check_expr(a: &ast::Expr);
|
||||
fn check_expr_post(a: &ast::Expr);
|
||||
|
@ -1,5 +1,7 @@
|
||||
use crate::Lint;
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast::ast;
|
||||
use rustc_ast::ast::{ExprKind, StmtKind};
|
||||
use rustc_ast::attr;
|
||||
use rustc_ast::util::parser;
|
||||
use rustc_ast_pretty::pprust;
|
||||
@ -315,16 +317,58 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub(super) UNUSED_PARENS,
|
||||
Warn,
|
||||
"`if`, `match`, `while` and `return` do not need parentheses"
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum UnusedDelimsCtx {
|
||||
FunctionArg,
|
||||
MethodArg,
|
||||
AssignedValue,
|
||||
IfCond,
|
||||
WhileCond,
|
||||
ForIterExpr,
|
||||
MatchScrutineeExpr,
|
||||
ReturnValue,
|
||||
BlockRetValue,
|
||||
LetScrutineeExpr,
|
||||
ArrayLenExpr,
|
||||
AnonConst,
|
||||
}
|
||||
|
||||
declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
|
||||
impl From<UnusedDelimsCtx> for &'static str {
|
||||
fn from(ctx: UnusedDelimsCtx) -> &'static str {
|
||||
match ctx {
|
||||
UnusedDelimsCtx::FunctionArg => "function argument",
|
||||
UnusedDelimsCtx::MethodArg => "method argument",
|
||||
UnusedDelimsCtx::AssignedValue => "assigned value",
|
||||
UnusedDelimsCtx::IfCond => "`if` condition",
|
||||
UnusedDelimsCtx::WhileCond => "`while` condition",
|
||||
UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
|
||||
UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression",
|
||||
UnusedDelimsCtx::ReturnValue => "`return` value",
|
||||
UnusedDelimsCtx::BlockRetValue => "block return value",
|
||||
UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
|
||||
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UnusedParens {
|
||||
fn is_expr_parens_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
|
||||
/// Used by both `UnusedParens` and `UnusedBraces` to prevent code duplication.
|
||||
trait UnusedDelimLint {
|
||||
const DELIM_STR: &'static str;
|
||||
|
||||
// this cannot be a constant is it refers to a static.
|
||||
fn lint(&self) -> &'static Lint;
|
||||
|
||||
fn check_unused_delims_expr(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
value: &ast::Expr,
|
||||
ctx: UnusedDelimsCtx,
|
||||
followed_by_block: bool,
|
||||
left_pos: Option<BytePos>,
|
||||
right_pos: Option<BytePos>,
|
||||
);
|
||||
|
||||
fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
|
||||
followed_by_block
|
||||
&& match inner.kind {
|
||||
ast::ExprKind::Ret(_) | ast::ExprKind::Break(..) => true,
|
||||
@ -332,42 +376,160 @@ impl UnusedParens {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unused_parens_expr(
|
||||
fn emit_unused_delims_expr(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
value: &ast::Expr,
|
||||
msg: &str,
|
||||
followed_by_block: bool,
|
||||
ctx: UnusedDelimsCtx,
|
||||
left_pos: Option<BytePos>,
|
||||
right_pos: Option<BytePos>,
|
||||
) {
|
||||
match value.kind {
|
||||
ast::ExprKind::Paren(ref inner) => {
|
||||
if !Self::is_expr_parens_necessary(inner, followed_by_block)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
{
|
||||
let expr_text =
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
|
||||
snippet
|
||||
} else {
|
||||
pprust::expr_to_string(value)
|
||||
};
|
||||
let keep_space = (
|
||||
left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
|
||||
right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
|
||||
let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
|
||||
snippet
|
||||
} else {
|
||||
pprust::expr_to_string(value)
|
||||
};
|
||||
let keep_space = (
|
||||
left_pos.map(|s| s >= value.span.lo()).unwrap_or(false),
|
||||
right_pos.map(|s| s <= value.span.hi()).unwrap_or(false),
|
||||
);
|
||||
self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
|
||||
}
|
||||
|
||||
fn emit_unused_delims(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
span: Span,
|
||||
pattern: &str,
|
||||
msg: &str,
|
||||
keep_space: (bool, bool),
|
||||
) {
|
||||
cx.struct_span_lint(self.lint(), span, |lint| {
|
||||
let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
|
||||
let mut err = lint.build(&span_msg);
|
||||
let mut ate_left_paren = false;
|
||||
let mut ate_right_paren = false;
|
||||
let parens_removed = pattern.trim_matches(|c| match c {
|
||||
'(' | '{' => {
|
||||
if ate_left_paren {
|
||||
false
|
||||
} else {
|
||||
ate_left_paren = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
')' | '}' => {
|
||||
if ate_right_paren {
|
||||
false
|
||||
} else {
|
||||
ate_right_paren = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let replace = {
|
||||
let mut replace = if keep_space.0 {
|
||||
let mut s = String::from(" ");
|
||||
s.push_str(parens_removed);
|
||||
s
|
||||
} else {
|
||||
String::from(parens_removed)
|
||||
};
|
||||
|
||||
if keep_space.1 {
|
||||
replace.push(' ');
|
||||
}
|
||||
replace
|
||||
};
|
||||
|
||||
let suggestion = format!("remove these {}", Self::DELIM_STR);
|
||||
|
||||
err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable);
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
use rustc_ast::ast::ExprKind::*;
|
||||
let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
|
||||
If(ref cond, ref block, ..) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(2);
|
||||
let right = block.span.lo();
|
||||
(cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
|
||||
}
|
||||
|
||||
While(ref cond, ref block, ..) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||
let right = block.span.lo();
|
||||
(cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right))
|
||||
}
|
||||
|
||||
ForLoop(_, ref cond, ref block, ..) => {
|
||||
(cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
|
||||
}
|
||||
|
||||
Match(ref head, _) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||
(head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
|
||||
}
|
||||
|
||||
Ret(Some(ref value)) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(3);
|
||||
(value, UnusedDelimsCtx::ReturnValue, false, Some(left), None)
|
||||
}
|
||||
|
||||
Assign(_, ref value, _) | AssignOp(.., ref value) => {
|
||||
(value, UnusedDelimsCtx::AssignedValue, false, None, None)
|
||||
}
|
||||
// either function/method call, or something this lint doesn't care about
|
||||
ref call_or_other => {
|
||||
let (args_to_check, ctx) = match *call_or_other {
|
||||
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
|
||||
// first "argument" is self (which sometimes needs delims)
|
||||
MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg),
|
||||
// actual catch-all arm
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
// Don't lint if this is a nested macro expansion: otherwise, the lint could
|
||||
// trigger in situations that macro authors shouldn't have to care about, e.g.,
|
||||
// when a parenthesized token tree matched in one macro expansion is matched as
|
||||
// an expression in another and used as a fn/method argument (Issue #47775)
|
||||
if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
|
||||
return;
|
||||
}
|
||||
for arg in args_to_check {
|
||||
self.check_unused_delims_expr(cx, arg, ctx, false, None, None);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.check_unused_delims_expr(cx, &value, ctx, followed_by_block, left_pos, right_pos);
|
||||
}
|
||||
|
||||
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
|
||||
match s.kind {
|
||||
StmtKind::Local(ref local) => {
|
||||
if let Some(ref value) = local.init {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
&value,
|
||||
UnusedDelimsCtx::AssignedValue,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
Self::remove_outer_parens(cx, value.span, &expr_text, msg, keep_space);
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Let(_, ref expr) => {
|
||||
// FIXME(#60336): Properly handle `let true = (false && true)`
|
||||
// actually needing the parenthesis.
|
||||
self.check_unused_parens_expr(
|
||||
StmtKind::Expr(ref expr) => {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
expr,
|
||||
"`let` head expression",
|
||||
followed_by_block,
|
||||
&expr,
|
||||
UnusedDelimsCtx::BlockRetValue,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
@ -376,6 +538,73 @@ impl UnusedParens {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
use ast::ItemKind::*;
|
||||
|
||||
if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
expr,
|
||||
UnusedDelimsCtx::AssignedValue,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub(super) UNUSED_PARENS,
|
||||
Warn,
|
||||
"`if`, `match`, `while` and `return` do not need parentheses"
|
||||
}
|
||||
|
||||
declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
|
||||
|
||||
impl UnusedDelimLint for UnusedParens {
|
||||
const DELIM_STR: &'static str = "parentheses";
|
||||
|
||||
fn lint(&self) -> &'static Lint {
|
||||
UNUSED_PARENS
|
||||
}
|
||||
|
||||
fn check_unused_delims_expr(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
value: &ast::Expr,
|
||||
ctx: UnusedDelimsCtx,
|
||||
followed_by_block: bool,
|
||||
left_pos: Option<BytePos>,
|
||||
right_pos: Option<BytePos>,
|
||||
) {
|
||||
match value.kind {
|
||||
ast::ExprKind::Paren(ref inner) => {
|
||||
if !Self::is_expr_delims_necessary(inner, followed_by_block)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
{
|
||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Let(_, ref expr) => {
|
||||
// FIXME(#60336): Properly handle `let true = (false && true)`
|
||||
// actually needing the parenthesis.
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
expr,
|
||||
UnusedDelimsCtx::LetScrutineeExpr,
|
||||
followed_by_block,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UnusedParens {
|
||||
fn check_unused_parens_pat(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
@ -406,132 +635,18 @@ impl UnusedParens {
|
||||
} else {
|
||||
pprust::pat_to_string(value)
|
||||
};
|
||||
Self::remove_outer_parens(cx, value.span, &pattern_text, "pattern", (false, false));
|
||||
self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false));
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_outer_parens(
|
||||
cx: &EarlyContext<'_>,
|
||||
span: Span,
|
||||
pattern: &str,
|
||||
msg: &str,
|
||||
keep_space: (bool, bool),
|
||||
) {
|
||||
cx.struct_span_lint(UNUSED_PARENS, span, |lint| {
|
||||
let span_msg = format!("unnecessary parentheses around {}", msg);
|
||||
let mut err = lint.build(&span_msg);
|
||||
let mut ate_left_paren = false;
|
||||
let mut ate_right_paren = false;
|
||||
let parens_removed = pattern.trim_matches(|c| match c {
|
||||
'(' => {
|
||||
if ate_left_paren {
|
||||
false
|
||||
} else {
|
||||
ate_left_paren = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
')' => {
|
||||
if ate_right_paren {
|
||||
false
|
||||
} else {
|
||||
ate_right_paren = true;
|
||||
true
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
|
||||
let replace = {
|
||||
let mut replace = if keep_space.0 {
|
||||
let mut s = String::from(" ");
|
||||
s.push_str(parens_removed);
|
||||
s
|
||||
} else {
|
||||
String::from(parens_removed)
|
||||
};
|
||||
|
||||
if keep_space.1 {
|
||||
replace.push(' ');
|
||||
}
|
||||
replace
|
||||
};
|
||||
|
||||
err.span_suggestion_short(
|
||||
span,
|
||||
"remove these parentheses",
|
||||
replace,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for UnusedParens {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
use rustc_ast::ast::ExprKind::*;
|
||||
let (value, msg, followed_by_block, left_pos, right_pos) = match e.kind {
|
||||
Let(ref pat, ..) => {
|
||||
self.check_unused_parens_pat(cx, pat, false, false);
|
||||
return;
|
||||
}
|
||||
if let ExprKind::Let(ref pat, ..) | ExprKind::ForLoop(ref pat, ..) = e.kind {
|
||||
self.check_unused_parens_pat(cx, pat, false, false);
|
||||
}
|
||||
|
||||
If(ref cond, ref block, ..) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(2);
|
||||
let right = block.span.lo();
|
||||
(cond, "`if` condition", true, Some(left), Some(right))
|
||||
}
|
||||
|
||||
While(ref cond, ref block, ..) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||
let right = block.span.lo();
|
||||
(cond, "`while` condition", true, Some(left), Some(right))
|
||||
}
|
||||
|
||||
ForLoop(ref pat, ref cond, ref block, ..) => {
|
||||
self.check_unused_parens_pat(cx, pat, false, false);
|
||||
(cond, "`for` head expression", true, None, Some(block.span.lo()))
|
||||
}
|
||||
|
||||
Match(ref head, _) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(5);
|
||||
(head, "`match` head expression", true, Some(left), None)
|
||||
}
|
||||
|
||||
Ret(Some(ref value)) => {
|
||||
let left = e.span.lo() + rustc_span::BytePos(3);
|
||||
(value, "`return` value", false, Some(left), None)
|
||||
}
|
||||
|
||||
Assign(_, ref value, _) => (value, "assigned value", false, None, None),
|
||||
AssignOp(.., ref value) => (value, "assigned value", false, None, None),
|
||||
// either function/method call, or something this lint doesn't care about
|
||||
ref call_or_other => {
|
||||
let (args_to_check, call_kind) = match *call_or_other {
|
||||
Call(_, ref args) => (&args[..], "function"),
|
||||
// first "argument" is self (which sometimes needs parens)
|
||||
MethodCall(_, ref args) => (&args[1..], "method"),
|
||||
// actual catch-all arm
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
// Don't lint if this is a nested macro expansion: otherwise, the lint could
|
||||
// trigger in situations that macro authors shouldn't have to care about, e.g.,
|
||||
// when a parenthesized token tree matched in one macro expansion is matched as
|
||||
// an expression in another and used as a fn/method argument (Issue #47775)
|
||||
if e.span.ctxt().outer_expn_data().call_site.from_expansion() {
|
||||
return;
|
||||
}
|
||||
let msg = format!("{} argument", call_kind);
|
||||
for arg in args_to_check {
|
||||
self.check_unused_parens_expr(cx, arg, &msg, false, None, None);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.check_unused_parens_expr(cx, &value, msg, followed_by_block, left_pos, right_pos);
|
||||
<Self as UnusedDelimLint>::check_expr(self, cx, e)
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) {
|
||||
@ -556,22 +671,16 @@ impl EarlyLintPass for UnusedParens {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
|
||||
self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
|
||||
}
|
||||
|
||||
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
|
||||
use ast::StmtKind::*;
|
||||
|
||||
match s.kind {
|
||||
Local(ref local) => {
|
||||
self.check_unused_parens_pat(cx, &local.pat, false, false);
|
||||
|
||||
if let Some(ref value) = local.init {
|
||||
self.check_unused_parens_expr(cx, &value, "assigned value", false, None, None);
|
||||
}
|
||||
}
|
||||
Expr(ref expr) => {
|
||||
self.check_unused_parens_expr(cx, &expr, "block return value", false, None, None);
|
||||
}
|
||||
_ => {}
|
||||
if let StmtKind::Local(ref local) = s.kind {
|
||||
self.check_unused_parens_pat(cx, &local.pat, false, false);
|
||||
}
|
||||
|
||||
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
|
||||
}
|
||||
|
||||
fn check_param(&mut self, cx: &EarlyContext<'_>, param: &ast::Param) {
|
||||
@ -587,6 +696,16 @@ impl EarlyLintPass for UnusedParens {
|
||||
match &r.kind {
|
||||
&ast::TyKind::TraitObject(..) => {}
|
||||
&ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {}
|
||||
&ast::TyKind::Array(_, ref len) => {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
&len.value,
|
||||
UnusedDelimsCtx::ArrayLenExpr,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
let pattern_text =
|
||||
if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) {
|
||||
@ -595,21 +714,136 @@ impl EarlyLintPass for UnusedParens {
|
||||
pprust::ty_to_string(ty)
|
||||
};
|
||||
|
||||
Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false));
|
||||
self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
use ast::ItemKind::*;
|
||||
<Self as UnusedDelimLint>::check_item(self, cx, item)
|
||||
}
|
||||
}
|
||||
|
||||
if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind {
|
||||
self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None);
|
||||
declare_lint! {
|
||||
pub(super) UNUSED_BRACES,
|
||||
Warn,
|
||||
"unnecessary braces around an expression"
|
||||
}
|
||||
|
||||
declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
|
||||
|
||||
impl UnusedDelimLint for UnusedBraces {
|
||||
const DELIM_STR: &'static str = "braces";
|
||||
|
||||
fn lint(&self) -> &'static Lint {
|
||||
UNUSED_BRACES
|
||||
}
|
||||
|
||||
fn check_unused_delims_expr(
|
||||
&self,
|
||||
cx: &EarlyContext<'_>,
|
||||
value: &ast::Expr,
|
||||
ctx: UnusedDelimsCtx,
|
||||
followed_by_block: bool,
|
||||
left_pos: Option<BytePos>,
|
||||
right_pos: Option<BytePos>,
|
||||
) {
|
||||
match value.kind {
|
||||
ast::ExprKind::Block(ref inner, None)
|
||||
if inner.rules == ast::BlockCheckMode::Default =>
|
||||
{
|
||||
// emit a warning under the following conditions:
|
||||
//
|
||||
// - the block does not have a label
|
||||
// - the block is not `unsafe`
|
||||
// - the block contains exactly one expression (do not lint `{ expr; }`)
|
||||
// - `followed_by_block` is true and the internal expr may contain a `{`
|
||||
// - the block is not multiline (do not lint multiline match arms)
|
||||
// ```
|
||||
// match expr {
|
||||
// Pattern => {
|
||||
// somewhat_long_expression
|
||||
// }
|
||||
// // ...
|
||||
// }
|
||||
// ```
|
||||
// - the block has no attribute and was not created inside a macro
|
||||
// - if the block is an `anon_const`, the inner expr must be a literal
|
||||
// (do not lint `struct A<const N: usize>; let _: A<{ 2 + 3 }>;`)
|
||||
//
|
||||
// FIXME(const_generics): handle paths when #67075 is fixed.
|
||||
if let [stmt] = inner.stmts.as_slice() {
|
||||
if let ast::StmtKind::Expr(ref expr) = stmt.kind {
|
||||
if !Self::is_expr_delims_necessary(expr, followed_by_block)
|
||||
&& (ctx != UnusedDelimsCtx::AnonConst
|
||||
|| matches!(expr.kind, ast::ExprKind::Lit(_)))
|
||||
// array length expressions are checked during `check_anon_const` and `check_ty`,
|
||||
// once as `ArrayLenExpr` and once as `AnonConst`.
|
||||
//
|
||||
// As we do not want to lint this twice, we do not emit an error for
|
||||
// `ArrayLenExpr` if `AnonConst` would do the same.
|
||||
&& (ctx != UnusedDelimsCtx::ArrayLenExpr
|
||||
|| !matches!(expr.kind, ast::ExprKind::Lit(_)))
|
||||
&& !cx.sess().source_map().is_multiline(value.span)
|
||||
&& value.attrs.is_empty()
|
||||
&& !value.span.from_expansion()
|
||||
{
|
||||
self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Let(_, ref expr) => {
|
||||
// FIXME(#60336): Properly handle `let true = (false && true)`
|
||||
// actually needing the parenthesis.
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
expr,
|
||||
UnusedDelimsCtx::LetScrutineeExpr,
|
||||
followed_by_block,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for UnusedBraces {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
|
||||
<Self as UnusedDelimLint>::check_expr(self, cx, e)
|
||||
}
|
||||
|
||||
fn check_anon_const(&mut self, cx: &EarlyContext<'_>, c: &ast::AnonConst) {
|
||||
self.check_unused_delims_expr(cx, &c.value, UnusedDelimsCtx::AnonConst, false, None, None);
|
||||
}
|
||||
|
||||
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
|
||||
<Self as UnusedDelimLint>::check_stmt(self, cx, s)
|
||||
}
|
||||
|
||||
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
|
||||
if let &ast::TyKind::Paren(ref r) = &ty.kind {
|
||||
if let ast::TyKind::Array(_, ref len) = r.kind {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
&len.value,
|
||||
UnusedDelimsCtx::ArrayLenExpr,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
<Self as UnusedDelimLint>::check_item(self, cx, item)
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
UNUSED_IMPORT_BRACES,
|
||||
Allow,
|
||||
|
@ -356,9 +356,11 @@ fn add_query_description_impl(
|
||||
quote! { #t }
|
||||
})
|
||||
.unwrap_or(quote! { _ });
|
||||
// expr is a `Block`, meaning that `{ #expr }` gets expanded
|
||||
// to `{ { stmts... } }`, which triggers the `unused_braces` lint.
|
||||
quote! {
|
||||
#[inline]
|
||||
#[allow(unused_variables)]
|
||||
#[allow(unused_variables, unused_braces)]
|
||||
fn cache_on_disk(
|
||||
#tcx: TyCtxt<'tcx>,
|
||||
#key: Self::Key,
|
||||
|
@ -2808,7 +2808,7 @@ impl<'a> Resolver<'a> {
|
||||
ast::Path {
|
||||
span,
|
||||
segments: iter::once(Ident::with_dummy_span(kw::PathRoot))
|
||||
.chain({ path_str.split("::").skip(1).map(Ident::from_str) })
|
||||
.chain(path_str.split("::").skip(1).map(Ident::from_str))
|
||||
.map(|i| self.new_ast_path_segment(i))
|
||||
.collect(),
|
||||
}
|
||||
|
@ -115,8 +115,7 @@ impl RawHandle {
|
||||
) -> io::Result<Option<usize>> {
|
||||
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
|
||||
let mut amt = 0;
|
||||
let res =
|
||||
cvt({ c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped) });
|
||||
let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
|
||||
match res {
|
||||
Ok(_) => Ok(Some(amt as usize)),
|
||||
Err(e) => {
|
||||
@ -139,7 +138,7 @@ impl RawHandle {
|
||||
unsafe {
|
||||
let mut bytes = 0;
|
||||
let wait = if wait { c::TRUE } else { c::FALSE };
|
||||
let res = cvt({ c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait) });
|
||||
let res = cvt(c::GetOverlappedResult(self.raw(), overlapped, &mut bytes, wait));
|
||||
match res {
|
||||
Ok(_) => Ok(bytes as usize),
|
||||
Err(e) => {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
struct FakeArray<T, const N: usize>(T);
|
||||
|
||||
impl<T, const N: usize> FakeArray<T, { N }> {
|
||||
impl<T, const N: usize> FakeArray<T, N> {
|
||||
fn len(&self) -> usize {
|
||||
N
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ fn test_big_vec() {}
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn test_big_vec()
|
||||
{
|
||||
assert_eq!(size_of::<[u8; (1 << 32)]>(), (1 << 32));
|
||||
assert_eq!(size_of::<[u8; 1 << 32]>(), (1 << 32));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
|
||||
fn force<F>(f: F) -> isize where F: FnOnce() -> isize { return f(); }
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(unused_variables)]
|
||||
// Test that destructors for rvalue temporaries run either at end of
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
#![allow(dead_code)]
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
|
@ -7,13 +7,13 @@ trait HasSize {
|
||||
const SIZE: usize;
|
||||
}
|
||||
|
||||
impl<const X: usize> HasSize for ArrayHolder<{ X }> {
|
||||
impl<const X: usize> HasSize for ArrayHolder<X> {
|
||||
const SIZE: usize = X;
|
||||
}
|
||||
|
||||
struct ArrayHolder<const X: usize>([u32; X]);
|
||||
|
||||
impl<const X: usize> ArrayHolder<{ X }> {
|
||||
impl<const X: usize> ArrayHolder<X> {
|
||||
pub const fn new() -> Self {
|
||||
ArrayHolder([0; Self::SIZE])
|
||||
//~^ ERROR: mismatched types
|
||||
|
@ -13,4 +13,4 @@ trait Foo<const X: usize> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo<{3}> for () {}
|
||||
impl Foo<3> for () {}
|
||||
|
13
src/test/ui/const-generics/unused_braces.rs
Normal file
13
src/test/ui/const-generics/unused_braces.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
#![warn(unused_braces)]
|
||||
|
||||
#![feature(const_generics)]
|
||||
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
|
||||
struct A<const N: usize>;
|
||||
|
||||
fn main() {
|
||||
let _: A<7>; // ok
|
||||
let _: A<{ 7 }>; //~ WARN unnecessary braces
|
||||
let _: A<{ 3 + 5 }>; // ok
|
||||
}
|
20
src/test/ui/const-generics/unused_braces.stderr
Normal file
20
src/test/ui/const-generics/unused_braces.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
|
||||
--> $DIR/unused_braces.rs:4:12
|
||||
|
|
||||
LL | #![feature(const_generics)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: unnecessary braces around const expression
|
||||
--> $DIR/unused_braces.rs:11:14
|
||||
|
|
||||
LL | let _: A<{ 7 }>;
|
||||
| ^^^^^ help: remove these braces
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_braces.rs:2:9
|
||||
|
|
||||
LL | #![warn(unused_braces)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_unsafe)]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
fn test_generic<T, F>(expected: Box<T>, eq: F) where T: Clone, F: FnOnce(Box<T>, Box<T>) -> bool {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
fn test_generic<T, F>(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool {
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
|
||||
fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool {
|
||||
let actual: T = { expected.clone() };
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); }
|
||||
|
@ -1,10 +1,7 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
||||
|
||||
|
||||
// Tests for standalone blocks as expressions
|
||||
|
||||
fn test_basic() { let rs: bool = { true }; assert!((rs)); }
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
|
||||
fn test_int() {
|
||||
fn f() -> isize { 10 }
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
|
||||
fn foo(i: isize) -> isize { i + 1 }
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// run-pass
|
||||
// Test a rather underspecified example:
|
||||
|
||||
#![allow(unused_braces)]
|
||||
|
||||
pub fn main() {
|
||||
let f = {|i| i};
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
#![allow(unused_unsafe)]
|
||||
#![allow(unreachable_code)]
|
||||
// ignore-emscripten no threads support
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_parens)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Note: This test was used to demonstrate #5873 (now #23898).
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
fn main() {
|
||||
let v1 = { 1 + {2} * {3} };
|
||||
let v2 = 1 + {2} * {3} ;
|
||||
|
@ -48,11 +48,11 @@ fn main() {
|
||||
if (true) {} //~ ERROR unnecessary parentheses around `if` condition
|
||||
while (true) {} //~ ERROR unnecessary parentheses around `while` condition
|
||||
//~^ WARN denote infinite loops with
|
||||
match (true) { //~ ERROR unnecessary parentheses around `match` head expression
|
||||
match (true) { //~ ERROR unnecessary parentheses around `match` scrutinee expression
|
||||
_ => {}
|
||||
}
|
||||
if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` head expression
|
||||
while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` head expression
|
||||
if let 1 = (1) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression
|
||||
while let 1 = (2) {} //~ ERROR unnecessary parentheses around `let` scrutinee expression
|
||||
let v = X { y: false };
|
||||
// struct lits needs parens, so these shouldn't warn.
|
||||
if (v == X { y: true }) {}
|
||||
|
@ -72,19 +72,19 @@ LL | while (true) {}
|
||||
|
|
||||
= note: `#[warn(while_true)]` on by default
|
||||
|
||||
error: unnecessary parentheses around `match` head expression
|
||||
error: unnecessary parentheses around `match` scrutinee expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:51:11
|
||||
|
|
||||
LL | match (true) {
|
||||
| ^^^^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `let` head expression
|
||||
error: unnecessary parentheses around `let` scrutinee expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:54:16
|
||||
|
|
||||
LL | if let 1 = (1) {}
|
||||
| ^^^ help: remove these parentheses
|
||||
|
||||
error: unnecessary parentheses around `let` head expression
|
||||
error: unnecessary parentheses around `let` scrutinee expression
|
||||
--> $DIR/lint-unnecessary-parens.rs:55:19
|
||||
|
|
||||
LL | while let 1 = (2) {}
|
||||
|
31
src/test/ui/lint/unused_braces.rs
Normal file
31
src/test/ui/lint/unused_braces.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// check-pass
|
||||
#![warn(unused_braces, unused_parens)]
|
||||
|
||||
fn main() {
|
||||
let _ = (7);
|
||||
//~^WARN unnecessary parentheses
|
||||
|
||||
let _ = { 7 };
|
||||
//~^ WARN unnecessary braces
|
||||
|
||||
if let 7 = { 7 } {
|
||||
//~^ WARN unnecessary braces
|
||||
}
|
||||
|
||||
let _: [u8; { 3 }];
|
||||
//~^ WARN unnecessary braces
|
||||
|
||||
// do not emit error for multiline blocks.
|
||||
let _ = {
|
||||
7
|
||||
};
|
||||
|
||||
// do not emit error for unsafe blocks.
|
||||
let _ = unsafe { 7 };
|
||||
|
||||
// do not emit error, as the `{` would then
|
||||
// be parsed as part of the `return`.
|
||||
if { return } {
|
||||
|
||||
}
|
||||
}
|
36
src/test/ui/lint/unused_braces.stderr
Normal file
36
src/test/ui/lint/unused_braces.stderr
Normal file
@ -0,0 +1,36 @@
|
||||
warning: unnecessary parentheses around assigned value
|
||||
--> $DIR/unused_braces.rs:5:13
|
||||
|
|
||||
LL | let _ = (7);
|
||||
| ^^^ help: remove these parentheses
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_braces.rs:2:24
|
||||
|
|
||||
LL | #![warn(unused_braces, unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: unnecessary braces around assigned value
|
||||
--> $DIR/unused_braces.rs:8:13
|
||||
|
|
||||
LL | let _ = { 7 };
|
||||
| ^^^^^ help: remove these braces
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_braces.rs:2:9
|
||||
|
|
||||
LL | #![warn(unused_braces, unused_parens)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: unnecessary braces around `let` scrutinee expression
|
||||
--> $DIR/unused_braces.rs:11:16
|
||||
|
|
||||
LL | if let 7 = { 7 } {
|
||||
| ^^^^^ help: remove these braces
|
||||
|
||||
warning: unnecessary braces around const expression
|
||||
--> $DIR/unused_braces.rs:15:17
|
||||
|
|
||||
LL | let _: [u8; { 3 }];
|
||||
| ^^^^^ help: remove these braces
|
||||
|
22
src/test/ui/lint/unused_parens_borrow.rs
Normal file
22
src/test/ui/lint/unused_parens_borrow.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// check-pass
|
||||
#![warn(unused_braces)]
|
||||
|
||||
// changing `&{ expr }` to `&expr` changes the semantic of the program
|
||||
// so we should not warn this case
|
||||
|
||||
#[repr(packed)]
|
||||
struct A {
|
||||
a: u8,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A {
|
||||
a: 42,
|
||||
b: 1729,
|
||||
};
|
||||
|
||||
let _ = &{ a.b };
|
||||
let _ = { a.b };
|
||||
//~^ WARN unnecessary braces
|
||||
}
|
12
src/test/ui/lint/unused_parens_borrow.stderr
Normal file
12
src/test/ui/lint/unused_parens_borrow.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
warning: unnecessary braces around assigned value
|
||||
--> $DIR/unused_parens_borrow.rs:20:13
|
||||
|
|
||||
LL | let _ = { a.b };
|
||||
| ^^^^^^^ help: remove these braces
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused_parens_borrow.rs:2:9
|
||||
|
|
||||
LL | #![warn(unused_braces)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -46,14 +46,14 @@ LL | while(true && false) {
|
||||
| ^^^^^^^^^^^^^^^ help: remove these parentheses
|
||||
|
||||
"}
|
||||
{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
|
||||
{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:44:18
|
||||
|
|
||||
LL | for _ in (0 .. 3){
|
||||
| ^^^^^^^^ help: remove these parentheses
|
||||
|
||||
"}
|
||||
{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
|
||||
{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
|
||||
--> $DIR/unused_parens_remove_json_suggestion.rs:49:14
|
||||
|
|
||||
LL | for _ in (0 .. 3) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces)]
|
||||
#![allow(unused_comparisons)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unused_mut)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// run-pass
|
||||
// Test inclusive range syntax.
|
||||
|
||||
#![feature(range_is_empty)]
|
||||
#![allow(unused_braces)]
|
||||
#![allow(unused_comparisons)]
|
||||
|
||||
use std::ops::RangeToInclusive;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -18,16 +18,16 @@ trait MyTrait<'a, const C: usize> {
|
||||
const MY_CONST: usize;
|
||||
}
|
||||
|
||||
impl<'a, const C: usize> MyTrait<'a, { C }> for MyStruct<{ C }> {
|
||||
impl<'a, const C: usize> MyTrait<'a, C> for MyStruct<C> {
|
||||
type MyItem = u8;
|
||||
const MY_CONST: usize = C;
|
||||
}
|
||||
|
||||
impl<'a, I, const C: usize> UnwrapItemsExt<'a, { C }> for I {
|
||||
type Iter = impl MyTrait<'a, { C }>;
|
||||
impl<'a, I, const C: usize> UnwrapItemsExt<'a, C> for I {
|
||||
type Iter = impl MyTrait<'a, C>;
|
||||
|
||||
fn unwrap_items(self) -> Self::Iter {
|
||||
MyStruct::<{ C }> {}
|
||||
MyStruct::<C> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_braces, unused_parens)]
|
||||
#![feature(unsized_tuple_coercion, unsized_locals)]
|
||||
|
||||
struct A<X: ?Sized>(X);
|
||||
@ -30,7 +30,6 @@ fn main() {
|
||||
*foo()
|
||||
});
|
||||
udrop::<[u8]>({*foo()});
|
||||
#[allow(unused_parens)]
|
||||
udrop::<[u8]>((*foo()));
|
||||
udrop::<[u8]>((*tfoo()).1);
|
||||
*afoo() + 42;
|
||||
|
@ -5,7 +5,7 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(unreachable_code)]
|
||||
#![allow(unused_parens)]
|
||||
#![allow(unused_braces, unused_parens)]
|
||||
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_braces)]
|
||||
#![allow(unused_assignments)]
|
||||
|
||||
// Make sure that the constructor args are codegened for zero-sized tuple structs
|
||||
|
Loading…
Reference in New Issue
Block a user