Skip to content

Commit

Permalink
Auto merge of #128278 - tgross35:rollup-zv7q0h5, r=tgross35
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #125897 (from_ref, from_mut: clarify documentation)
 - #128207 (improve error message when `global_asm!` uses `asm!` options)
 - #128241 (Remove logic to suggest clone of function output)
 - #128259 ([illumos/solaris] set MSG_NOSIGNAL while writing to sockets)
 - #128262 (Delete `SimplifyArmIdentity` and `SimplifyBranchSame` tests)
 - #128266 (update `rust.channel` default value documentation)
 - #128267 (Add rustdoc GUI test to check title with and without search)
 - #128271 (Disable jump threading of float equality)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 27, 2024
2 parents d9e1dea + f62ae7e commit fbccf50
Show file tree
Hide file tree
Showing 39 changed files with 501 additions and 587 deletions.
5 changes: 5 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2266,6 +2266,11 @@ bitflags::bitflags! {
}

impl InlineAsmOptions {
pub const COUNT: usize = Self::all().bits().count_ones() as usize;

pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN);

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

Expand Down
31 changes: 0 additions & 31 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1306,37 +1306,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
// result of `foo(...)` won't help.
break 'outer;
}

// We're suggesting `.clone()` on an borrowed value. See if the expression we have
// is an argument to a function or method call, and try to suggest cloning the
// *result* of the call, instead of the argument. This is closest to what people
// would actually be looking for in most cases, with maybe the exception of things
// like `fn(T) -> T`, but even then it is reasonable.
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
let mut prev = expr;
while let hir::Node::Expr(parent) = self.infcx.tcx.parent_hir_node(prev.hir_id) {
if let hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) = parent.kind
&& let Some(call_ty) = typeck_results.node_type_opt(parent.hir_id)
&& let call_ty = call_ty.peel_refs()
&& (!call_ty
.walk()
.any(|t| matches!(t.unpack(), ty::GenericArgKind::Lifetime(_)))
|| if let ty::Alias(ty::Projection, _) = call_ty.kind() {
// FIXME: this isn't quite right with lifetimes on assoc types,
// but ignore for now. We will only suggest cloning if
// `<Ty as Trait>::Assoc: Clone`, which should keep false positives
// down to a managable ammount.
true
} else {
false
})
&& self.implements_clone(call_ty)
&& self.suggest_cloning_inner(err, call_ty, parent)
{
return;
}
prev = parent;
}
}
}
let ty = ty.peel_refs();
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_builtin_macros/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ builtin_macros_format_use_positional = consider using a positional formatting ar
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
.suggestion = remove this option
builtin_macros_invalid_crate_attribute = invalid crate attribute
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
Expand Down
65 changes: 43 additions & 22 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
}

/// Report an invalid option error.
///
/// This function must be called immediately after the option token is parsed.
/// Otherwise, the suggestion will be incorrect.
fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
// Tool-only output
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span });
}

/// Try to set the provided option in the provided `AsmArgs`.
/// If it is already set, report a duplicate option error.
///
Expand All @@ -318,13 +328,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
fn try_set_option<'a>(
p: &Parser<'a>,
args: &mut AsmArgs,
is_global_asm: bool,
symbol: Symbol,
option: ast::InlineAsmOptions,
) {
if !args.options.contains(option) {
args.options |= option;
} else {
if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
err_unsupported_option(p, symbol, p.prev_token.span);
} else if args.options.contains(option) {
err_duplicate_option(p, symbol, p.prev_token.span);
} else {
args.options |= option;
}
}

Expand All @@ -338,25 +351,33 @@ fn parse_options<'a>(
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;

while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
if !is_global_asm && p.eat_keyword(sym::pure) {
try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
} else if !is_global_asm && p.eat_keyword(sym::nomem) {
try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
} else if !is_global_asm && p.eat_keyword(sym::readonly) {
try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
} else if !is_global_asm && p.eat_keyword(sym::preserves_flags) {
try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
} else if !is_global_asm && p.eat_keyword(sym::noreturn) {
try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
} else if !is_global_asm && p.eat_keyword(sym::nostack) {
try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
} else if !is_global_asm && p.eat_keyword(sym::may_unwind) {
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
} else if p.eat_keyword(sym::att_syntax) {
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
} else if p.eat_keyword(kw::Raw) {
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
} else {
const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
(sym::pure, ast::InlineAsmOptions::PURE),
(sym::nomem, ast::InlineAsmOptions::NOMEM),
(sym::readonly, ast::InlineAsmOptions::READONLY),
(sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS),
(sym::noreturn, ast::InlineAsmOptions::NORETURN),
(sym::nostack, ast::InlineAsmOptions::NOSTACK),
(sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND),
(sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX),
(kw::Raw, ast::InlineAsmOptions::RAW),
];

'blk: {
for (symbol, option) in OPTIONS {
let kw_matched =
if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
p.eat_keyword(symbol)
} else {
p.eat_keyword_noexpect(symbol)
};

if kw_matched {
try_set_option(p, args, is_global_asm, symbol, option);
break 'blk;
}
}

return p.unexpected();
}

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,17 @@ pub(crate) struct AsmOptAlreadyprovided {
pub(crate) full_span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_global_asm_unsupported_option)]
pub(crate) struct GlobalAsmUnsupportedOption {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) symbol: Symbol,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub(crate) full_span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_test_runner_invalid)]
pub(crate) struct TestRunnerInvalid {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_mir_transform/src/jump_threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,13 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
BinOp::Ne => ScalarInt::FALSE,
_ => return None,
};
if value.const_.ty().is_floating_point() {
// Floating point equality does not follow bit-patterns.
// -0.0 and NaN both have special rules for equality,
// and therefore we cannot use integer comparisons for them.
// Avoid handling them, though this could be extended in the future.
return None;
}
let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?;
let conds = conditions.map(self.arena, |c| Condition {
value,
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ impl<'a> Parser<'a> {

/// If the next token is the given keyword, eats it and returns `true`.
/// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
// Public for rustfmt usage.
// Public for rustc_builtin_macros and rustfmt usage.
#[inline]
pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
if self.check_keyword(kw) {
Expand Down Expand Up @@ -631,8 +631,11 @@ impl<'a> Parser<'a> {
false
}

/// If the next token is the given keyword, eats it and returns `true`.
/// Otherwise, returns `false`. No expectation is added.
// Public for rustc_builtin_macros usage.
#[inline]
fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
if self.token.is_keyword(kw) {
self.bump();
true
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_passes/src/naked_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
}

let supported_options =
InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
let unsupported_options = asm.options.difference(supported_options);

let unsupported_options = asm.options.difference(InlineAsmOptions::NAKED_OPTIONS);
if !unsupported_options.is_empty() {
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
span,
Expand Down
5 changes: 4 additions & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,10 @@
# The "channel" for the Rust build to produce. The stable/beta channels only
# allow using stable features, whereas the nightly and dev channels allow using
# nightly features
#channel = "dev"
#
# If using tarball sources, default value for `channel` is taken from the `src/ci/channel` file;
# otherwise, it's "dev".
#channel = if "is a tarball source" { content of `src/ci/channel` file } else { "dev" }

# A descriptive string to be appended to `rustc --version` output, which is
# also used in places like debuginfo `DW_AT_producer`. This may be useful for
Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// valid for zero sized reads if the vector didn't allocate.
///
/// The caller must ensure that the vector outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// function returns, or else it will end up dangling.
/// Modifying the vector may cause its buffer to be reallocated,
/// which would also make any pointers to it invalid.
///
Expand Down Expand Up @@ -1337,7 +1337,7 @@ impl<T, A: Allocator> Vec<T, A> {
/// raw pointer valid for zero sized reads if the vector didn't allocate.
///
/// The caller must ensure that the vector outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// function returns, or else it will end up dangling.
/// Modifying the vector may cause its buffer to be reallocated,
/// which would also make any pointers to it invalid.
///
Expand Down
88 changes: 84 additions & 4 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,8 +777,51 @@ where

/// Convert a reference to a raw pointer.
///
/// This is equivalent to `r as *const T`, but is a bit safer since it will never silently change
/// type or mutability, in particular if the code is refactored.
/// For `r: &T`, `from_ref(r)` is equivalent to `r as *const T` (except for the caveat noted below),
/// but is a bit safer since it will never silently change type or mutability, in particular if the
/// code is refactored.
///
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
/// will end up dangling.
///
/// The caller must also ensure that the memory the pointer (non-transitively) points to is never
/// written to (except inside an `UnsafeCell`) using this pointer or any pointer derived from it. If
/// you need to mutate the pointee, use [`from_mut`]`. Specifically, to turn a mutable reference `m:
/// &mut T` into `*const T`, prefer `from_mut(m).cast_const()` to obtain a pointer that can later be
/// used for mutation.
///
/// ## Interaction with lifetime extension
///
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
/// tail expressions. This code is valid, albeit in a non-obvious way:
/// ```rust
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// // The temporary holding the return value of `foo` has its lifetime extended,
/// // because the surrounding expression involves no function call.
/// let p = &foo() as *const T;
/// unsafe { p.read() };
/// ```
/// Naively replacing the cast with `from_ref` is not valid:
/// ```rust,no_run
/// # use std::ptr;
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
/// // because the surrounding expression involves no function call.
/// let p = ptr::from_ref(&foo());
/// unsafe { p.read() }; // UB! Reading from a dangling pointer ⚠️
/// ```
/// The recommended way to write this code is to avoid relying on lifetime extension
/// when raw pointers are involved:
/// ```rust
/// # use std::ptr;
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// let x = foo();
/// let p = ptr::from_ref(&x);
/// unsafe { p.read() };
/// ```
#[inline(always)]
#[must_use]
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
Expand All @@ -791,8 +834,45 @@ pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {

/// Convert a mutable reference to a raw pointer.
///
/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change
/// type or mutability, in particular if the code is refactored.
/// For `r: &mut T`, `from_mut(r)` is equivalent to `r as *mut T` (except for the caveat noted
/// below), but is a bit safer since it will never silently change type or mutability, in particular
/// if the code is refactored.
///
/// The caller must ensure that the pointee outlives the pointer this function returns, or else it
/// will end up dangling.
///
/// ## Interaction with lifetime extension
///
/// Note that this has subtle interactions with the rules for lifetime extension of temporaries in
/// tail expressions. This code is valid, albeit in a non-obvious way:
/// ```rust
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// // The temporary holding the return value of `foo` has its lifetime extended,
/// // because the surrounding expression involves no function call.
/// let p = &mut foo() as *mut T;
/// unsafe { p.write(T::default()) };
/// ```
/// Naively replacing the cast with `from_mut` is not valid:
/// ```rust,no_run
/// # use std::ptr;
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// // The temporary holding the return value of `foo` does *not* have its lifetime extended,
/// // because the surrounding expression involves no function call.
/// let p = ptr::from_mut(&mut foo());
/// unsafe { p.write(T::default()) }; // UB! Writing to a dangling pointer ⚠️
/// ```
/// The recommended way to write this code is to avoid relying on lifetime extension
/// when raw pointers are involved:
/// ```rust
/// # use std::ptr;
/// # type T = i32;
/// # fn foo() -> T { 42 }
/// let mut x = foo();
/// let p = ptr::from_mut(&mut x);
/// unsafe { p.write(T::default()) };
/// ```
#[inline(always)]
#[must_use]
#[stable(feature = "ptr_from_ref", since = "1.76.0")]
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ impl<T> [T] {
/// Returns a raw pointer to the slice's buffer.
///
/// The caller must ensure that the slice outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// function returns, or else it will end up dangling.
///
/// The caller must also ensure that the memory the pointer (non-transitively) points to
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
Expand Down Expand Up @@ -761,7 +761,7 @@ impl<T> [T] {
/// Returns an unsafe mutable pointer to the slice's buffer.
///
/// The caller must ensure that the slice outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
/// function returns, or else it will end up dangling.
///
/// Modifying the container referenced by this slice may cause its buffer
/// to be reallocated, which would also make any pointers to it invalid.
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/os/unix/net/datagram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use crate::{fmt, io};
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "nto",
))]
Expand All @@ -31,6 +33,8 @@ use libc::MSG_NOSIGNAL;
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "solaris",
target_os = "illumos",
target_os = "haiku",
target_os = "nto",
)))]
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys_common/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ cfg_if::cfg_if! {
target_os = "hurd",
target_os = "dragonfly", target_os = "freebsd",
target_os = "openbsd", target_os = "netbsd",
target_os = "solaris", target_os = "illumos",
target_os = "haiku", target_os = "nto"))] {
use libc::MSG_NOSIGNAL;
} else {
Expand Down
Loading

0 comments on commit fbccf50

Please sign in to comment.