Skip to content

Rollup of 7 pull requests #128186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 25, 2024
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
de560c3
Implement `ambiguous_negative_literals` lint
Urgau Feb 20, 2024
c5e1a12
Remove unary neg from `clippy::precedence` lint
Urgau Feb 20, 2024
c31ff97
centralize turning asm flags into human readable names
folkertdev Jul 24, 2024
4b7a87d
use an allow list for allowed asm options in naked functions
folkertdev Jul 24, 2024
2c7ae38
std: unsafe-wrap gcc::rust_eh_personality and impl
workingjubilee Jul 24, 2024
c9cd4a6
std: update comments on gcc personality fn
workingjubilee Jul 24, 2024
40d132f
Make sure that args are compatible in resolve_associated_item
compiler-errors Jul 25, 2024
d004edf
Don't ICE if HIR and middle types disagree in borrowck error reporting
compiler-errors Jul 25, 2024
34819b7
Don't add crashes for misuses of intrinsics
compiler-errors Jul 25, 2024
17b4fbc
In connect timeout, read readiness of socket for vxworks. Check pollh…
Jul 25, 2024
ae71900
Rollup merge of #121364 - Urgau:unary_precedence, r=compiler-errors
matthiaskrgr Jul 25, 2024
d1070df
Rollup merge of #127300 - biabbas:fix_connect_timeout, r=tgross35
matthiaskrgr Jul 25, 2024
e76bb3f
Rollup merge of #128138 - folkertdev:asm-option-allowlist, r=lcnr
matthiaskrgr Jul 25, 2024
606c9fc
Rollup merge of #128158 - workingjubilee:unsafe-wrap-personality-gcc,…
matthiaskrgr Jul 25, 2024
5a853d0
Rollup merge of #128171 - compiler-errors:arg-compat, r=oli-obk
matthiaskrgr Jul 25, 2024
4cf4196
Rollup merge of #128172 - compiler-errors:non-self-arg, r=chenyukang
matthiaskrgr Jul 25, 2024
c98d704
Rollup merge of #128173 - compiler-errors:misused-intrinsics, r=oli-obk
matthiaskrgr Jul 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -2264,6 +2264,42 @@ bitflags::bitflags! {
}
}

impl InlineAsmOptions {
pub fn human_readable_names(&self) -> Vec<&'static str> {
let mut options = vec![];

if self.contains(InlineAsmOptions::PURE) {
options.push("pure");
}
if self.contains(InlineAsmOptions::NOMEM) {
options.push("nomem");
}
if self.contains(InlineAsmOptions::READONLY) {
options.push("readonly");
}
if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
options.push("preserves_flags");
}
if self.contains(InlineAsmOptions::NORETURN) {
options.push("noreturn");
}
if self.contains(InlineAsmOptions::NOSTACK) {
options.push("nostack");
}
if self.contains(InlineAsmOptions::ATT_SYNTAX) {
options.push("att_syntax");
}
if self.contains(InlineAsmOptions::RAW) {
options.push("raw");
}
if self.contains(InlineAsmOptions::MAY_UNWIND) {
options.push("may_unwind");
}

options
}
}

impl std::fmt::Debug for InlineAsmOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
bitflags::parser::to_writer(self, f)
30 changes: 1 addition & 29 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
@@ -1505,35 +1505,7 @@ impl<'a> State<'a> {
AsmArg::Options(opts) => {
s.word("options");
s.popen();
let mut options = vec![];
if opts.contains(InlineAsmOptions::PURE) {
options.push("pure");
}
if opts.contains(InlineAsmOptions::NOMEM) {
options.push("nomem");
}
if opts.contains(InlineAsmOptions::READONLY) {
options.push("readonly");
}
if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
options.push("preserves_flags");
}
if opts.contains(InlineAsmOptions::NORETURN) {
options.push("noreturn");
}
if opts.contains(InlineAsmOptions::NOSTACK) {
options.push("nostack");
}
if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
options.push("att_syntax");
}
if opts.contains(InlineAsmOptions::RAW) {
options.push("raw");
}
if opts.contains(InlineAsmOptions::MAY_UNWIND) {
options.push("may_unwind");
}
s.commasep(Inconsistent, &options, |s, &opt| {
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
s.word(opt);
});
s.pclose();
34 changes: 26 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
// search for relevant arguments.
let mut arguments = Vec::new();
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
if let ty::Ref(argument_region, _, _) = argument.kind() {
if argument_region == return_region {
// Need to use the `rustc_middle::ty` types to compare against the
// `return_region`. Then use the `rustc_hir` type to get only
// the lifetime span.
if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
if let ty::Ref(argument_region, _, _) = argument.kind()
&& argument_region == return_region
{
// Need to use the `rustc_middle::ty` types to compare against the
// `return_region`. Then use the `rustc_hir` type to get only
// the lifetime span.
match &fn_decl.inputs[index].kind {
hir::TyKind::Ref(lifetime, _) => {
// With access to the lifetime, we can get
// the span of it.
arguments.push((*argument, lifetime.ident.span));
} else {
bug!("ty type is a ref but hir type is not");
}
// Resolve `self` whose self type is `&T`.
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
if let Res::SelfTyAlias { alias_to, .. } = path.res
&& let Some(alias_to) = alias_to.as_local()
&& let hir::Impl { self_ty, .. } = self
.infcx
.tcx
.hir_node_by_def_id(alias_to)
.expect_item()
.expect_impl()
&& let hir::TyKind::Ref(lifetime, _) = self_ty.kind
{
arguments.push((*argument, lifetime.ident.span));
}
}
_ => {
// Don't ICE though. It might be a type alias.
}
}
}
30 changes: 1 addition & 29 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1298,35 +1298,7 @@ impl<'a> State<'a> {
AsmArg::Options(opts) => {
s.word("options");
s.popen();
let mut options = vec![];
if opts.contains(ast::InlineAsmOptions::PURE) {
options.push("pure");
}
if opts.contains(ast::InlineAsmOptions::NOMEM) {
options.push("nomem");
}
if opts.contains(ast::InlineAsmOptions::READONLY) {
options.push("readonly");
}
if opts.contains(ast::InlineAsmOptions::PRESERVES_FLAGS) {
options.push("preserves_flags");
}
if opts.contains(ast::InlineAsmOptions::NORETURN) {
options.push("noreturn");
}
if opts.contains(ast::InlineAsmOptions::NOSTACK) {
options.push("nostack");
}
if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
options.push("att_syntax");
}
if opts.contains(ast::InlineAsmOptions::RAW) {
options.push("raw");
}
if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) {
options.push("may_unwind");
}
s.commasep(Inconsistent, &options, |s, &opt| {
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
s.word(opt);
});
s.pclose();
5 changes: 5 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
@@ -5,6 +5,11 @@ lint_ambiguous_glob_reexport = ambiguous glob re-exports
.label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here
.label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here

lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected
.example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
.negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal
.current_behavior = add parentheses around the literal and the method call to keep the current behavior

lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
.addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
.addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -73,6 +73,7 @@ mod noop_method_call;
mod opaque_hidden_inferred_bound;
mod pass_by_value;
mod passes;
mod precedence;
mod ptr_nulls;
mod redundant_semicolon;
mod reference_casting;
@@ -111,6 +112,7 @@ use nonstandard_style::*;
use noop_method_call::*;
use opaque_hidden_inferred_bound::*;
use pass_by_value::*;
use precedence::*;
use ptr_nulls::*;
use redundant_semicolon::*;
use reference_casting::*;
@@ -174,6 +176,7 @@ early_lint_methods!(
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
Expr2024: Expr2024,
Precedence: Precedence,
]
]
);
29 changes: 29 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -1499,6 +1499,35 @@ pub struct NonLocalDefinitionsCargoUpdateNote {
pub crate_name: Symbol,
}

// precedence.rs
#[derive(LintDiagnostic)]
#[diag(lint_ambiguous_negative_literals)]
#[note(lint_example)]
pub struct AmbiguousNegativeLiteralsDiag {
#[subdiagnostic]
pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
#[subdiagnostic]
pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
#[suggestion_part(code = "(")]
pub start_span: Span,
#[suggestion_part(code = ")")]
pub end_span: Span,
}

#[derive(Subdiagnostic)]
#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
#[suggestion_part(code = "(")]
pub start_span: Span,
#[suggestion_part(code = ")")]
pub end_span: Span,
}

// pass_by_value.rs
#[derive(LintDiagnostic)]
#[diag(lint_pass_by_value)]
70 changes: 70 additions & 0 deletions compiler/rustc_lint/src/precedence.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use rustc_ast::token::LitKind;
use rustc_ast::{Expr, ExprKind, MethodCall, UnOp};
use rustc_session::{declare_lint, declare_lint_pass};

use crate::lints::{
AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag,
AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
};
use crate::{EarlyContext, EarlyLintPass, LintContext};

declare_lint! {
/// The `ambiguous_negative_literals` lint checks for cases that are
/// confusing between a negative literal and a negation that's not part
/// of the literal.
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![allow(unused)]
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Method calls take precedence over unary precedence. Setting the
/// precedence explicitly makes the code clearer and avoid potential bugs.
pub AMBIGUOUS_NEGATIVE_LITERALS,
Deny,
"ambiguous negative literals operations",
report_in_external_macro
}

declare_lint_pass!(Precedence => [AMBIGUOUS_NEGATIVE_LITERALS]);

impl EarlyLintPass for Precedence {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind else {
return;
};

let mut arg = operand;
let mut at_least_one = false;
while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind {
at_least_one = true;
arg = receiver;
}

if at_least_one
&& let ExprKind::Lit(lit) = &arg.kind
&& let LitKind::Integer | LitKind::Float = &lit.kind
{
cx.emit_span_lint(
AMBIGUOUS_NEGATIVE_LITERALS,
expr.span,
AmbiguousNegativeLiteralsDiag {
negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
start_span: expr.span.shrink_to_lo(),
end_span: arg.span.shrink_to_hi(),
},
current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
start_span: operand.span.shrink_to_lo(),
end_span: operand.span.shrink_to_hi(),
},
},
);
}
}
}
21 changes: 9 additions & 12 deletions compiler/rustc_passes/src/naked_functions.rs
Original file line number Diff line number Diff line change
@@ -244,22 +244,19 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
}

let unsupported_options: Vec<&'static str> = [
(InlineAsmOptions::MAY_UNWIND, "`may_unwind`"),
(InlineAsmOptions::NOMEM, "`nomem`"),
(InlineAsmOptions::NOSTACK, "`nostack`"),
(InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
(InlineAsmOptions::PURE, "`pure`"),
(InlineAsmOptions::READONLY, "`readonly`"),
]
.iter()
.filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
.collect();
let supported_options =
InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
let unsupported_options = asm.options.difference(supported_options);

if !unsupported_options.is_empty() {
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
span,
unsupported_options: unsupported_options.join(", "),
unsupported_options: unsupported_options
.human_readable_names()
.into_iter()
.map(|name| format!("`{name}`"))
.collect::<Vec<_>>()
.join(", "),
});
}

15 changes: 13 additions & 2 deletions compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
@@ -191,11 +191,22 @@ fn resolve_associated_item<'tcx>(

// Any final impl is required to define all associated items.
if !leaf_def.item.defaultness(tcx).has_value() {
let guard = tcx.dcx().span_delayed_bug(
let guar = tcx.dcx().span_delayed_bug(
tcx.def_span(leaf_def.item.def_id),
"missing value for assoc item in impl",
);
return Err(guard);
return Err(guar);
}

// Make sure that we're projecting to an item that has compatible args.
// This may happen if we are resolving an instance before codegen, such
// as during inlining. This check is also done in projection.
if !tcx.check_args_compatible(leaf_def.item.def_id, args) {
let guar = tcx.dcx().span_delayed_bug(
tcx.def_span(leaf_def.item.def_id),
"missing value for assoc item in impl",
);
return Err(guar);
}

let args = tcx.erase_regions(args);
29 changes: 19 additions & 10 deletions library/std/src/sys/pal/unix/net.rs
Original file line number Diff line number Diff line change
@@ -214,16 +214,25 @@ impl Socket {
}
0 => {}
_ => {
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
// for POLLHUP rather than read readiness
if pollfd.revents & libc::POLLHUP != 0 {
let e = self.take_error()?.unwrap_or_else(|| {
io::const_io_error!(
io::ErrorKind::Uncategorized,
"no error set after POLLHUP",
)
});
return Err(e);
if cfg!(target_os = "vxworks") {
// VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the
// connnection actually succeeded and return ok only when the socket is
// ready and no errors were found.
if let Some(e) = self.take_error()? {
return Err(e);
}
} else {
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
// for POLLHUP or POLLERR rather than read readiness
if pollfd.revents & (libc::POLLHUP | libc::POLLERR) != 0 {
let e = self.take_error()?.unwrap_or_else(|| {
io::const_io_error!(
io::ErrorKind::Uncategorized,
"no error set after POLLHUP",
)
});
return Err(e);
}
}

return Ok(());
321 changes: 180 additions & 141 deletions library/std/src/sys/personality/gcc.rs

Large diffs are not rendered by default.

56 changes: 1 addition & 55 deletions src/tools/clippy/clippy_lints/src/precedence.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,17 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, MethodCall, UnOp};
use rustc_ast::token;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::source_map::Spanned;

const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [
"asin",
"asinh",
"atan",
"atanh",
"cbrt",
"fract",
"round",
"signum",
"sin",
"sinh",
"tan",
"tanh",
"to_degrees",
"to_radians",
];

declare_clippy_lint! {
/// ### What it does
/// Checks for operations where precedence may be unclear
/// and suggests to add parentheses. Currently it catches the following:
/// * mixed usage of arithmetic and bit shifting/combining operators without
/// parentheses
/// * a "negative" numeric literal (which is really a unary `-` followed by a
/// numeric literal)
/// followed by a method call
///
/// ### Why is this bad?
/// Not everyone knows the precedence of those operators by
@@ -41,7 +20,6 @@ declare_clippy_lint! {
///
/// ### Example
/// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
/// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1
#[clippy::version = "pre 1.29.0"]
pub PRECEDENCE,
complexity,
@@ -104,38 +82,6 @@ impl EarlyLintPass for Precedence {
(false, false) => (),
}
}

if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind {
let mut arg = operand;

let mut all_odd = true;
while let ExprKind::MethodCall(box MethodCall { seg, receiver, .. }) = &arg.kind {
let seg_str = seg.ident.name.as_str();
all_odd &= ALLOWED_ODD_FUNCTIONS
.iter()
.any(|odd_function| **odd_function == *seg_str);
arg = receiver;
}

if !all_odd
&& let ExprKind::Lit(lit) = &arg.kind
&& let token::LitKind::Integer | token::LitKind::Float = &lit.kind
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
PRECEDENCE,
expr.span,
"unary minus has lower precedence than method call",
"consider adding parentheses to clarify your intent",
format!(
"-({})",
snippet_with_applicability(cx, operand.span, "..", &mut applicability)
),
applicability,
);
}
}
}
}

34 changes: 0 additions & 34 deletions src/tools/clippy/tests/ui/precedence.fixed
Original file line number Diff line number Diff line change
@@ -20,40 +20,6 @@ fn main() {
1 ^ (1 - 1);
3 | (2 - 1);
3 & (5 - 2);
-(1i32.abs());
-(1f32.abs());

// These should not trigger an error
let _ = (-1i32).abs();
let _ = (-1f32).abs();
let _ = -(1i32).abs();
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());

// Odd functions should not trigger an error
let _ = -1f64.asin();
let _ = -1f64.asinh();
let _ = -1f64.atan();
let _ = -1f64.atanh();
let _ = -1f64.cbrt();
let _ = -1f64.fract();
let _ = -1f64.round();
let _ = -1f64.signum();
let _ = -1f64.sin();
let _ = -1f64.sinh();
let _ = -1f64.tan();
let _ = -1f64.tanh();
let _ = -1f64.to_degrees();
let _ = -1f64.to_radians();

// Chains containing any non-odd function should trigger (issue #5924)
let _ = -(1.0_f64.cos().cos());
let _ = -(1.0_f64.cos().sin());
let _ = -(1.0_f64.sin().cos());

// Chains of odd functions shouldn't trigger
let _ = -1f64.sin().sin();

let b = 3;
trip!(b * 8);
34 changes: 0 additions & 34 deletions src/tools/clippy/tests/ui/precedence.rs
Original file line number Diff line number Diff line change
@@ -20,40 +20,6 @@ fn main() {
1 ^ 1 - 1;
3 | 2 - 1;
3 & 5 - 2;
-1i32.abs();
-1f32.abs();

// These should not trigger an error
let _ = (-1i32).abs();
let _ = (-1f32).abs();
let _ = -(1i32).abs();
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());

// Odd functions should not trigger an error
let _ = -1f64.asin();
let _ = -1f64.asinh();
let _ = -1f64.atan();
let _ = -1f64.atanh();
let _ = -1f64.cbrt();
let _ = -1f64.fract();
let _ = -1f64.round();
let _ = -1f64.signum();
let _ = -1f64.sin();
let _ = -1f64.sinh();
let _ = -1f64.tan();
let _ = -1f64.tanh();
let _ = -1f64.to_degrees();
let _ = -1f64.to_radians();

// Chains containing any non-odd function should trigger (issue #5924)
let _ = -1.0_f64.cos().cos();
let _ = -1.0_f64.cos().sin();
let _ = -1.0_f64.sin().cos();

// Chains of odd functions shouldn't trigger
let _ = -1f64.sin().sin();

let b = 3;
trip!(b * 8);
32 changes: 1 addition & 31 deletions src/tools/clippy/tests/ui/precedence.stderr
Original file line number Diff line number Diff line change
@@ -43,35 +43,5 @@ error: operator precedence can trip the unwary
LL | 3 & 5 - 2;
| ^^^^^^^^^ help: consider parenthesizing your expression: `3 & (5 - 2)`

error: unary minus has lower precedence than method call
--> tests/ui/precedence.rs:23:5
|
LL | -1i32.abs();
| ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1i32.abs())`

error: unary minus has lower precedence than method call
--> tests/ui/precedence.rs:24:5
|
LL | -1f32.abs();
| ^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1f32.abs())`

error: unary minus has lower precedence than method call
--> tests/ui/precedence.rs:51:13
|
LL | let _ = -1.0_f64.cos().cos();
| ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().cos())`

error: unary minus has lower precedence than method call
--> tests/ui/precedence.rs:52:13
|
LL | let _ = -1.0_f64.cos().sin();
| ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.cos().sin())`

error: unary minus has lower precedence than method call
--> tests/ui/precedence.rs:53:13
|
LL | let _ = -1.0_f64.sin().cos();
| ^^^^^^^^^^^^^^^^^^^^ help: consider adding parentheses to clarify your intent: `-(1.0_f64.sin().cos())`

error: aborting due to 12 previous errors
error: aborting due to 7 previous errors

2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/unnecessary_cast.fixed
Original file line number Diff line number Diff line change
@@ -206,7 +206,7 @@ mod fixable {

fn issue_9563() {
let _: f64 = (-8.0_f64).exp();
#[allow(clippy::precedence)]
#[allow(ambiguous_negative_literals)]
let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
}

2 changes: 1 addition & 1 deletion src/tools/clippy/tests/ui/unnecessary_cast.rs
Original file line number Diff line number Diff line change
@@ -206,7 +206,7 @@ mod fixable {

fn issue_9563() {
let _: f64 = (-8.0 as f64).exp();
#[allow(clippy::precedence)]
#[allow(ambiguous_negative_literals)]
let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
}

11 changes: 0 additions & 11 deletions tests/crashes/101962.rs

This file was deleted.

14 changes: 0 additions & 14 deletions tests/crashes/111699.rs

This file was deleted.

25 changes: 0 additions & 25 deletions tests/crashes/120792.rs

This file was deleted.

22 changes: 0 additions & 22 deletions tests/crashes/120793-2.rs

This file was deleted.

21 changes: 0 additions & 21 deletions tests/crashes/120793.rs

This file was deleted.

20 changes: 0 additions & 20 deletions tests/crashes/121063.rs

This file was deleted.

12 changes: 0 additions & 12 deletions tests/crashes/121816.rs

This file was deleted.

20 changes: 0 additions & 20 deletions tests/crashes/121957-1.rs

This file was deleted.

20 changes: 0 additions & 20 deletions tests/crashes/121957-2.rs

This file was deleted.

22 changes: 0 additions & 22 deletions tests/crashes/97501.rs

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/asm/naked-functions.rs
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ unsafe extern "C" fn invalid_options() {
unsafe extern "C" fn invalid_options_continued() {
asm!("", options(readonly, nostack), options(pure));
//~^ ERROR asm with the `pure` option must have at least one output
//~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
//~| ERROR asm options unsupported in naked functions: `pure`, `readonly`, `nostack`
//~| ERROR asm in naked functions must use `noreturn` option
}

2 changes: 1 addition & 1 deletion tests/ui/asm/naked-functions.stderr
Original file line number Diff line number Diff line change
@@ -212,7 +212,7 @@ error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_fl
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
error[E0787]: asm options unsupported in naked functions: `pure`, `readonly`, `nostack`
--> $DIR/naked-functions.rs:112:5
|
LL | asm!("", options(readonly, nostack), options(pure));
19 changes: 19 additions & 0 deletions tests/ui/borrowck/ice-on-non-ref-sig-ty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Don't ICE when trying to annotate signature and we see `&()`

fn f<'a, T>(_: &'static &'a (), x: &'a T) -> &'static T {
x
}
trait W<'a> {
fn g<T>(self, x: &'a T) -> &'static T;
}

// Frankly this error message is impossible to parse, but :shrug:.
impl<'a> W<'a> for &'static () {
fn g<T>(self, x: &'a T) -> &'static T {
f(&self, x)
//~^ ERROR borrowed data escapes outside of method
//~| ERROR `self` does not live long enough
}
}

fn main() {}
36 changes: 36 additions & 0 deletions tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
error[E0521]: borrowed data escapes outside of method
--> $DIR/ice-on-non-ref-sig-ty.rs:13:9
|
LL | impl<'a> W<'a> for &'static () {
| -- lifetime `'a` defined here
LL | fn g<T>(self, x: &'a T) -> &'static T {
| ---- - `x` is a reference that is only valid in the method body
| |
| `self` declared here, outside of the method body
LL | f(&self, x)
| ^^^^^^^^^^^
| |
| `x` escapes the method body here
| argument requires that `'a` must outlive `'static`

error[E0597]: `self` does not live long enough
--> $DIR/ice-on-non-ref-sig-ty.rs:13:11
|
LL | impl<'a> W<'a> for &'static () {
| ------- has lifetime `'static`
LL | fn g<T>(self, x: &'a T) -> &'static T {
| ------- also has lifetime `'static`
LL | f(&self, x)
| ^^^^^ `self` would have to be valid for `'static`...
...
LL | }
| - ...but `self` will be dropped here, when the function `g` returns
|
= help: use data from the highlighted arguments which match the `'static` lifetime of the return type
= note: functions cannot return a borrow to data owned within the function's scope, functions can only return borrows to data passed as arguments
= note: to learn more, visit <https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#dangling-references>

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0521, E0597.
For more information about an error, try `rustc --explain E0521`.
35 changes: 35 additions & 0 deletions tests/ui/lint/negative_literals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//@ check-fail

fn main() {
let _ = -1i32.abs();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f32.abs();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f64.asin();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f64.asinh();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f64.tan();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f64.tanh();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1.0_f64.cos().cos();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1.0_f64.cos().sin();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1.0_f64.sin().cos();
//~^ ERROR `-` has lower precedence than method calls
let _ = -1f64.sin().sin();
//~^ ERROR `-` has lower precedence than method calls

dbg!( -1.0_f32.cos() );
//~^ ERROR `-` has lower precedence than method calls

// should not warn
let _ = (-1i32).abs();
let _ = (-1f32).abs();
let _ = -(1i32).abs();
let _ = -(1f32).abs();
let _ = -(1i32.abs());
let _ = -(1f32.abs());
}
179 changes: 179 additions & 0 deletions tests/ui/lint/negative_literals.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:4:13
|
LL | let _ = -1i32.abs();
| ^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
= note: `#[deny(ambiguous_negative_literals)]` on by default
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1i32).abs();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1i32.abs());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:6:13
|
LL | let _ = -1f32.abs();
| ^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f32).abs();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f32.abs());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:8:13
|
LL | let _ = -1f64.asin();
| ^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f64).asin();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f64.asin());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:10:13
|
LL | let _ = -1f64.asinh();
| ^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f64).asinh();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f64.asinh());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:12:13
|
LL | let _ = -1f64.tan();
| ^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f64).tan();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f64.tan());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:14:13
|
LL | let _ = -1f64.tanh();
| ^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f64).tanh();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f64.tanh());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:16:13
|
LL | let _ = -1.0_f64.cos().cos();
| ^^^^^^^^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1.0_f64).cos().cos();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1.0_f64.cos().cos());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:18:13
|
LL | let _ = -1.0_f64.cos().sin();
| ^^^^^^^^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1.0_f64).cos().sin();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1.0_f64.cos().sin());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:20:13
|
LL | let _ = -1.0_f64.sin().cos();
| ^^^^^^^^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1.0_f64).sin().cos();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1.0_f64.sin().cos());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:22:13
|
LL | let _ = -1f64.sin().sin();
| ^^^^^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | let _ = (-1f64).sin().sin();
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | let _ = -(1f64.sin().sin());
| + +

error: `-` has lower precedence than method calls, which might be unexpected
--> $DIR/negative_literals.rs:25:11
|
LL | dbg!( -1.0_f32.cos() );
| ^^^^^^^^^^^^^^
|
= note: e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
help: add parentheses around the `-` and the literal to call the method on a negative literal
|
LL | dbg!( (-1.0_f32).cos() );
| + +
help: add parentheses around the literal and the method call to keep the current behavior
|
LL | dbg!( -(1.0_f32.cos()) );
| + +

error: aborting due to 11 previous errors

27 changes: 27 additions & 0 deletions tests/ui/polymorphization/inline-incorrect-early-bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This test demonstrates an ICE that may occur when we try to resolve the instance
// of a impl that has different generics than the trait it's implementing. This ensures
// we first check that the args are compatible before resolving the body, just like
// we do in projection before substituting a GAT.
//
// When polymorphization is enabled, we check the optimized MIR for unused parameters.
// This will invoke the inliner, leading to this ICE.

//@ compile-flags: -Zpolymorphize=on -Zinline-mir=yes

trait Trait {
fn foo<'a, K: 'a>(self, _: K);
}

impl Trait for () {
#[inline]
fn foo<K>(self, _: K) {
//~^ ERROR lifetime parameters or bounds on method `foo` do not match the trait declaration
todo!();
}
}

pub fn qux<T>() {
().foo(());
}

fn main() {}
15 changes: 15 additions & 0 deletions tests/ui/polymorphization/inline-incorrect-early-bound.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
--> $DIR/inline-incorrect-early-bound.rs:17:11
|
LL | fn foo<'a, K: 'a>(self, _: K);
| -----------
| | |
| | this bound might be missing in the impl
| lifetimes in impl do not match this method in trait
...
LL | fn foo<K>(self, _: K) {
| ^^^ lifetimes do not match method in trait

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0195`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This test demonstrates an ICE that may occur when we try to resolve the instance
// of a impl that has different generics than the trait it's implementing. This ensures
// we first check that the args are compatible before resolving the body, just like
// we do in projection before substituting a GAT.
//
// Const traits aren't the only way to achieve this ICE, but it's a convenient way
// to ensure the inliner is called.

//@ compile-flags: -Znext-solver -Zinline-mir=yes

#![feature(const_trait_impl, effects)]
//~^ WARN the feature `effects` is incomplete

trait Trait {
fn foo(self);
}

impl Trait for () {
#[inline]
fn foo<T>(self) {
//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
todo!();
}
}

const fn foo() {
().foo();
}

const UWU: () = foo();

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:11:30
|
LL | #![feature(const_trait_impl, effects)]
| ^^^^^^^
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
= note: `#[warn(incomplete_features)]` on by default

error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/inline-incorrect-early-bound-in-ctfe.rs:20:12
|
LL | fn foo(self);
| - expected 0 type parameters
...
LL | fn foo<T>(self) {
| ^ found 1 type parameter

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0049`.