Skip to content

Commit eb10639

Browse files
committed
Auto merge of rust-lang#128186 - matthiaskrgr:rollup-01b7t98, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#121364 (Implement lint against ambiguous negative literals) - rust-lang#127300 (Fix connect timeout for non-linux targets, read readiness of socket connection, Read readiness to detect errors. `Fixes rust-lang#127018`) - rust-lang#128138 (`#[naked]`: use an allowlist for allowed options on `asm!` in naked functions) - rust-lang#128158 (std: unsafe-wrap personality::gcc) - rust-lang#128171 (Make sure that args are compatible in `resolve_associated_item`) - rust-lang#128172 (Don't ICE if HIR and middle types disagree in borrowck error reporting) - rust-lang#128173 (Remove crashes for misuses of intrinsics) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 54be9ad + c98d704 commit eb10639

38 files changed

+762
-576
lines changed

compiler/rustc_ast/src/ast.rs

+36
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,42 @@ bitflags::bitflags! {
22642264
}
22652265
}
22662266

2267+
impl InlineAsmOptions {
2268+
pub fn human_readable_names(&self) -> Vec<&'static str> {
2269+
let mut options = vec![];
2270+
2271+
if self.contains(InlineAsmOptions::PURE) {
2272+
options.push("pure");
2273+
}
2274+
if self.contains(InlineAsmOptions::NOMEM) {
2275+
options.push("nomem");
2276+
}
2277+
if self.contains(InlineAsmOptions::READONLY) {
2278+
options.push("readonly");
2279+
}
2280+
if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
2281+
options.push("preserves_flags");
2282+
}
2283+
if self.contains(InlineAsmOptions::NORETURN) {
2284+
options.push("noreturn");
2285+
}
2286+
if self.contains(InlineAsmOptions::NOSTACK) {
2287+
options.push("nostack");
2288+
}
2289+
if self.contains(InlineAsmOptions::ATT_SYNTAX) {
2290+
options.push("att_syntax");
2291+
}
2292+
if self.contains(InlineAsmOptions::RAW) {
2293+
options.push("raw");
2294+
}
2295+
if self.contains(InlineAsmOptions::MAY_UNWIND) {
2296+
options.push("may_unwind");
2297+
}
2298+
2299+
options
2300+
}
2301+
}
2302+
22672303
impl std::fmt::Debug for InlineAsmOptions {
22682304
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22692305
bitflags::parser::to_writer(self, f)

compiler/rustc_ast_pretty/src/pprust/state.rs

+1-29
Original file line numberDiff line numberDiff line change
@@ -1505,35 +1505,7 @@ impl<'a> State<'a> {
15051505
AsmArg::Options(opts) => {
15061506
s.word("options");
15071507
s.popen();
1508-
let mut options = vec![];
1509-
if opts.contains(InlineAsmOptions::PURE) {
1510-
options.push("pure");
1511-
}
1512-
if opts.contains(InlineAsmOptions::NOMEM) {
1513-
options.push("nomem");
1514-
}
1515-
if opts.contains(InlineAsmOptions::READONLY) {
1516-
options.push("readonly");
1517-
}
1518-
if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
1519-
options.push("preserves_flags");
1520-
}
1521-
if opts.contains(InlineAsmOptions::NORETURN) {
1522-
options.push("noreturn");
1523-
}
1524-
if opts.contains(InlineAsmOptions::NOSTACK) {
1525-
options.push("nostack");
1526-
}
1527-
if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
1528-
options.push("att_syntax");
1529-
}
1530-
if opts.contains(InlineAsmOptions::RAW) {
1531-
options.push("raw");
1532-
}
1533-
if opts.contains(InlineAsmOptions::MAY_UNWIND) {
1534-
options.push("may_unwind");
1535-
}
1536-
s.commasep(Inconsistent, &options, |s, &opt| {
1508+
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
15371509
s.word(opt);
15381510
});
15391511
s.pclose();

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -4304,17 +4304,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
43044304
// search for relevant arguments.
43054305
let mut arguments = Vec::new();
43064306
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
4307-
if let ty::Ref(argument_region, _, _) = argument.kind() {
4308-
if argument_region == return_region {
4309-
// Need to use the `rustc_middle::ty` types to compare against the
4310-
// `return_region`. Then use the `rustc_hir` type to get only
4311-
// the lifetime span.
4312-
if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
4307+
if let ty::Ref(argument_region, _, _) = argument.kind()
4308+
&& argument_region == return_region
4309+
{
4310+
// Need to use the `rustc_middle::ty` types to compare against the
4311+
// `return_region`. Then use the `rustc_hir` type to get only
4312+
// the lifetime span.
4313+
match &fn_decl.inputs[index].kind {
4314+
hir::TyKind::Ref(lifetime, _) => {
43134315
// With access to the lifetime, we can get
43144316
// the span of it.
43154317
arguments.push((*argument, lifetime.ident.span));
4316-
} else {
4317-
bug!("ty type is a ref but hir type is not");
4318+
}
4319+
// Resolve `self` whose self type is `&T`.
4320+
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
4321+
if let Res::SelfTyAlias { alias_to, .. } = path.res
4322+
&& let Some(alias_to) = alias_to.as_local()
4323+
&& let hir::Impl { self_ty, .. } = self
4324+
.infcx
4325+
.tcx
4326+
.hir_node_by_def_id(alias_to)
4327+
.expect_item()
4328+
.expect_impl()
4329+
&& let hir::TyKind::Ref(lifetime, _) = self_ty.kind
4330+
{
4331+
arguments.push((*argument, lifetime.ident.span));
4332+
}
4333+
}
4334+
_ => {
4335+
// Don't ICE though. It might be a type alias.
43184336
}
43194337
}
43204338
}

compiler/rustc_hir_pretty/src/lib.rs

+1-29
Original file line numberDiff line numberDiff line change
@@ -1298,35 +1298,7 @@ impl<'a> State<'a> {
12981298
AsmArg::Options(opts) => {
12991299
s.word("options");
13001300
s.popen();
1301-
let mut options = vec![];
1302-
if opts.contains(ast::InlineAsmOptions::PURE) {
1303-
options.push("pure");
1304-
}
1305-
if opts.contains(ast::InlineAsmOptions::NOMEM) {
1306-
options.push("nomem");
1307-
}
1308-
if opts.contains(ast::InlineAsmOptions::READONLY) {
1309-
options.push("readonly");
1310-
}
1311-
if opts.contains(ast::InlineAsmOptions::PRESERVES_FLAGS) {
1312-
options.push("preserves_flags");
1313-
}
1314-
if opts.contains(ast::InlineAsmOptions::NORETURN) {
1315-
options.push("noreturn");
1316-
}
1317-
if opts.contains(ast::InlineAsmOptions::NOSTACK) {
1318-
options.push("nostack");
1319-
}
1320-
if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
1321-
options.push("att_syntax");
1322-
}
1323-
if opts.contains(ast::InlineAsmOptions::RAW) {
1324-
options.push("raw");
1325-
}
1326-
if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) {
1327-
options.push("may_unwind");
1328-
}
1329-
s.commasep(Inconsistent, &options, |s, &opt| {
1301+
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
13301302
s.word(opt);
13311303
});
13321304
s.pclose();

compiler/rustc_lint/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ lint_ambiguous_glob_reexport = ambiguous glob re-exports
55
.label_first_reexport = the name `{$name}` in the {$namespace} namespace is first re-exported here
66
.label_duplicate_reexport = but the name `{$name}` in the {$namespace} namespace is also re-exported here
77
8+
lint_ambiguous_negative_literals = `-` has lower precedence than method calls, which might be unexpected
9+
.example = e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`
10+
.negative_literal = add parentheses around the `-` and the literal to call the method on a negative literal
11+
.current_behavior = add parentheses around the literal and the method call to keep the current behavior
12+
813
lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
914
.addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
1015
.addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ mod noop_method_call;
7373
mod opaque_hidden_inferred_bound;
7474
mod pass_by_value;
7575
mod passes;
76+
mod precedence;
7677
mod ptr_nulls;
7778
mod redundant_semicolon;
7879
mod reference_casting;
@@ -111,6 +112,7 @@ use nonstandard_style::*;
111112
use noop_method_call::*;
112113
use opaque_hidden_inferred_bound::*;
113114
use pass_by_value::*;
115+
use precedence::*;
114116
use ptr_nulls::*;
115117
use redundant_semicolon::*;
116118
use reference_casting::*;
@@ -174,6 +176,7 @@ early_lint_methods!(
174176
RedundantSemicolons: RedundantSemicolons,
175177
UnusedDocComment: UnusedDocComment,
176178
Expr2024: Expr2024,
179+
Precedence: Precedence,
177180
]
178181
]
179182
);

compiler/rustc_lint/src/lints.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,35 @@ pub struct NonLocalDefinitionsCargoUpdateNote {
14991499
pub crate_name: Symbol,
15001500
}
15011501

1502+
// precedence.rs
1503+
#[derive(LintDiagnostic)]
1504+
#[diag(lint_ambiguous_negative_literals)]
1505+
#[note(lint_example)]
1506+
pub struct AmbiguousNegativeLiteralsDiag {
1507+
#[subdiagnostic]
1508+
pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
1509+
#[subdiagnostic]
1510+
pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion,
1511+
}
1512+
1513+
#[derive(Subdiagnostic)]
1514+
#[multipart_suggestion(lint_negative_literal, applicability = "maybe-incorrect")]
1515+
pub struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
1516+
#[suggestion_part(code = "(")]
1517+
pub start_span: Span,
1518+
#[suggestion_part(code = ")")]
1519+
pub end_span: Span,
1520+
}
1521+
1522+
#[derive(Subdiagnostic)]
1523+
#[multipart_suggestion(lint_current_behavior, applicability = "maybe-incorrect")]
1524+
pub struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
1525+
#[suggestion_part(code = "(")]
1526+
pub start_span: Span,
1527+
#[suggestion_part(code = ")")]
1528+
pub end_span: Span,
1529+
}
1530+
15021531
// pass_by_value.rs
15031532
#[derive(LintDiagnostic)]
15041533
#[diag(lint_pass_by_value)]

compiler/rustc_lint/src/precedence.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use rustc_ast::token::LitKind;
2+
use rustc_ast::{Expr, ExprKind, MethodCall, UnOp};
3+
use rustc_session::{declare_lint, declare_lint_pass};
4+
5+
use crate::lints::{
6+
AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag,
7+
AmbiguousNegativeLiteralsNegativeLiteralSuggestion,
8+
};
9+
use crate::{EarlyContext, EarlyLintPass, LintContext};
10+
11+
declare_lint! {
12+
/// The `ambiguous_negative_literals` lint checks for cases that are
13+
/// confusing between a negative literal and a negation that's not part
14+
/// of the literal.
15+
///
16+
/// ### Example
17+
///
18+
/// ```rust,compile_fail
19+
/// # #![allow(unused)]
20+
/// -1i32.abs(); // equals -1, while `(-1i32).abs()` equals 1
21+
/// ```
22+
///
23+
/// {{produces}}
24+
///
25+
/// ### Explanation
26+
///
27+
/// Method calls take precedence over unary precedence. Setting the
28+
/// precedence explicitly makes the code clearer and avoid potential bugs.
29+
pub AMBIGUOUS_NEGATIVE_LITERALS,
30+
Deny,
31+
"ambiguous negative literals operations",
32+
report_in_external_macro
33+
}
34+
35+
declare_lint_pass!(Precedence => [AMBIGUOUS_NEGATIVE_LITERALS]);
36+
37+
impl EarlyLintPass for Precedence {
38+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
39+
let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind else {
40+
return;
41+
};
42+
43+
let mut arg = operand;
44+
let mut at_least_one = false;
45+
while let ExprKind::MethodCall(box MethodCall { receiver, .. }) = &arg.kind {
46+
at_least_one = true;
47+
arg = receiver;
48+
}
49+
50+
if at_least_one
51+
&& let ExprKind::Lit(lit) = &arg.kind
52+
&& let LitKind::Integer | LitKind::Float = &lit.kind
53+
{
54+
cx.emit_span_lint(
55+
AMBIGUOUS_NEGATIVE_LITERALS,
56+
expr.span,
57+
AmbiguousNegativeLiteralsDiag {
58+
negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion {
59+
start_span: expr.span.shrink_to_lo(),
60+
end_span: arg.span.shrink_to_hi(),
61+
},
62+
current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion {
63+
start_span: operand.span.shrink_to_lo(),
64+
end_span: operand.span.shrink_to_hi(),
65+
},
66+
},
67+
);
68+
}
69+
}
70+
}

compiler/rustc_passes/src/naked_functions.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -244,22 +244,19 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
244244
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
245245
}
246246

247-
let unsupported_options: Vec<&'static str> = [
248-
(InlineAsmOptions::MAY_UNWIND, "`may_unwind`"),
249-
(InlineAsmOptions::NOMEM, "`nomem`"),
250-
(InlineAsmOptions::NOSTACK, "`nostack`"),
251-
(InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
252-
(InlineAsmOptions::PURE, "`pure`"),
253-
(InlineAsmOptions::READONLY, "`readonly`"),
254-
]
255-
.iter()
256-
.filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
257-
.collect();
247+
let supported_options =
248+
InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
249+
let unsupported_options = asm.options.difference(supported_options);
258250

259251
if !unsupported_options.is_empty() {
260252
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
261253
span,
262-
unsupported_options: unsupported_options.join(", "),
254+
unsupported_options: unsupported_options
255+
.human_readable_names()
256+
.into_iter()
257+
.map(|name| format!("`{name}`"))
258+
.collect::<Vec<_>>()
259+
.join(", "),
263260
});
264261
}
265262

compiler/rustc_ty_utils/src/instance.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,22 @@ fn resolve_associated_item<'tcx>(
191191

192192
// Any final impl is required to define all associated items.
193193
if !leaf_def.item.defaultness(tcx).has_value() {
194-
let guard = tcx.dcx().span_delayed_bug(
194+
let guar = tcx.dcx().span_delayed_bug(
195195
tcx.def_span(leaf_def.item.def_id),
196196
"missing value for assoc item in impl",
197197
);
198-
return Err(guard);
198+
return Err(guar);
199+
}
200+
201+
// Make sure that we're projecting to an item that has compatible args.
202+
// This may happen if we are resolving an instance before codegen, such
203+
// as during inlining. This check is also done in projection.
204+
if !tcx.check_args_compatible(leaf_def.item.def_id, args) {
205+
let guar = tcx.dcx().span_delayed_bug(
206+
tcx.def_span(leaf_def.item.def_id),
207+
"missing value for assoc item in impl",
208+
);
209+
return Err(guar);
199210
}
200211

201212
let args = tcx.erase_regions(args);

library/std/src/sys/pal/unix/net.rs

+19-10
Original file line numberDiff line numberDiff line change
@@ -214,16 +214,25 @@ impl Socket {
214214
}
215215
0 => {}
216216
_ => {
217-
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
218-
// for POLLHUP rather than read readiness
219-
if pollfd.revents & libc::POLLHUP != 0 {
220-
let e = self.take_error()?.unwrap_or_else(|| {
221-
io::const_io_error!(
222-
io::ErrorKind::Uncategorized,
223-
"no error set after POLLHUP",
224-
)
225-
});
226-
return Err(e);
217+
if cfg!(target_os = "vxworks") {
218+
// VxWorks poll does not return POLLHUP or POLLERR in revents. Check if the
219+
// connnection actually succeeded and return ok only when the socket is
220+
// ready and no errors were found.
221+
if let Some(e) = self.take_error()? {
222+
return Err(e);
223+
}
224+
} else {
225+
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
226+
// for POLLHUP or POLLERR rather than read readiness
227+
if pollfd.revents & (libc::POLLHUP | libc::POLLERR) != 0 {
228+
let e = self.take_error()?.unwrap_or_else(|| {
229+
io::const_io_error!(
230+
io::ErrorKind::Uncategorized,
231+
"no error set after POLLHUP",
232+
)
233+
});
234+
return Err(e);
235+
}
227236
}
228237

229238
return Ok(());

0 commit comments

Comments
 (0)