Skip to content

Commit

Permalink
Auto merge of #128186 - matthiaskrgr:rollup-01b7t98, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - #121364 (Implement lint against ambiguous negative literals)
 - #127300 (Fix connect timeout for non-linux targets, read readiness of socket connection, Read readiness to detect errors. `Fixes #127018`)
 - #128138 (`#[naked]`: use an allowlist for allowed options on `asm!` in naked functions)
 - #128158 (std: unsafe-wrap personality::gcc)
 - #128171 (Make sure that args are compatible in `resolve_associated_item`)
 - #128172 (Don't ICE if HIR and middle types disagree in borrowck error reporting)
 - #128173 (Remove crashes for misuses of intrinsics)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 25, 2024
2 parents 54be9ad + c98d704 commit eb10639
Show file tree
Hide file tree
Showing 38 changed files with 762 additions and 576 deletions.
36 changes: 36 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 1 addition & 29 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
34 changes: 26 additions & 8 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
}
}
Expand Down
30 changes: 1 addition & 29 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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::*;
Expand Down Expand Up @@ -174,6 +176,7 @@ early_lint_methods!(
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
Expr2024: Expr2024,
Precedence: Precedence,
]
]
);
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
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
Expand Up @@ -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(", "),
});
}

Expand Down
15 changes: 13 additions & 2 deletions compiler/rustc_ty_utils/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 19 additions & 10 deletions library/std/src/sys/pal/unix/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(());
Expand Down
Loading

0 comments on commit eb10639

Please sign in to comment.