Skip to content

Commit

Permalink
Auto merge of rust-lang#95944 - Dylan-DPC:rollup-idggkrh, r=Dylan-DPC
Browse files Browse the repository at this point in the history
Rollup of 7 pull requests

Successful merges:

 - rust-lang#95008 ([`let_chains`] Forbid `let` inside parentheses)
 - rust-lang#95801 (Replace RwLock by a futex based one on Linux)
 - rust-lang#95864 (Fix miscompilation of inline assembly with outputs in cases where we emit an invoke instead of call instruction.)
 - rust-lang#95894 (Fix formatting error in pin.rs docs)
 - rust-lang#95895 (Clarify str::from_utf8_unchecked's invariants)
 - rust-lang#95901 (Remove duplicate aliases for `check codegen_{cranelift,gcc}` and fix `build codegen_gcc`)
 - rust-lang#95927 (CI: do not compile libcore twice when performing LLVM PGO)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Apr 11, 2022
2 parents 90ca447 + 070e8ed commit de392c7
Show file tree
Hide file tree
Showing 16 changed files with 1,104 additions and 502 deletions.
54 changes: 42 additions & 12 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,21 @@ impl<'a> AstValidator<'a> {
let err = "`let` expressions are not supported here";
let mut diag = sess.struct_span_err(expr.span, err);
diag.note("only supported directly in conditions of `if` and `while` expressions");
diag.note("as well as when nested within `&&` and parentheses in those conditions");
if let ForbiddenLetReason::ForbiddenWithOr(span) = forbidden_let_reason {
diag.span_note(
span,
"`||` operators are not currently supported in let chain expressions",
);
match forbidden_let_reason {
ForbiddenLetReason::GenericForbidden => {}
ForbiddenLetReason::NotSupportedOr(span) => {
diag.span_note(
span,
"`||` operators are not supported in let chain expressions",
);
}
ForbiddenLetReason::NotSupportedParentheses(span) => {
diag.span_note(
span,
"`let`s wrapped in parentheses are not supported in a context with let \
chains",
);
}
}
diag.emit();
} else {
Expand Down Expand Up @@ -1009,9 +1018,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.with_let_management(Some(ForbiddenLetReason::GenericForbidden), |this, forbidden_let_reason| {
match &expr.kind {
ExprKind::Binary(Spanned { node: BinOpKind::Or, span }, lhs, rhs) => {
let forbidden_let_reason = Some(ForbiddenLetReason::ForbiddenWithOr(*span));
this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(lhs));
this.with_let_management(forbidden_let_reason, |this, _| this.visit_expr(rhs));
let local_reason = Some(ForbiddenLetReason::NotSupportedOr(*span));
this.with_let_management(local_reason, |this, _| this.visit_expr(lhs));
this.with_let_management(local_reason, |this, _| this.visit_expr(rhs));
}
ExprKind::If(cond, then, opt_else) => {
this.visit_block(then);
Expand All @@ -1036,7 +1045,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
}
ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
ExprKind::Paren(local_expr) => {
fn has_let_expr(expr: &Expr) -> bool {
match expr.kind {
ExprKind::Binary(_, ref lhs, ref rhs) => has_let_expr(lhs) || has_let_expr(rhs),
ExprKind::Let(..) => true,
_ => false,
}
}
let local_reason = if has_let_expr(local_expr) {
Some(ForbiddenLetReason::NotSupportedParentheses(local_expr.span))
}
else {
forbidden_let_reason
};
this.with_let_management(local_reason, |this, _| this.visit_expr(local_expr));
}
ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
this.with_let_management(forbidden_let_reason, |this, _| visit::walk_expr(this, expr));
return;
}
Expand Down Expand Up @@ -1810,8 +1835,13 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
/// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy)]
enum ForbiddenLetReason {
/// A let chain with the `||` operator
ForbiddenWithOr(Span),
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
NotSupportedOr(Span),
/// A let chain with invalid parentheses
///
/// For exemple, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
NotSupportedParentheses(Span),
}
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });

// Switch to the 'normal' basic block if we did an `invoke` instead of a `call`
if let Some((dest, _, _)) = dest_catch_funclet {
self.switch_to_block(dest);
}

// Write results to outputs
for (idx, op) in operands.iter().enumerate() {
if let InlineAsmOperandRef::Out { reg, place: Some(place), .. }
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@
//! relies on pinning requires unsafe code, but be aware that deciding to make
//! use of pinning in your type (for example by implementing some operation on
//! <code>[Pin]<[&]Self></code> or <code>[Pin]<[&mut] Self></code>) has consequences for your
//! [`Drop`][Drop]implementation as well: if an element of your type could have been pinned,
//! [`Drop`][Drop] implementation as well: if an element of your type could have been pinned,
//! you must treat [`Drop`][Drop] as implicitly taking <code>[Pin]<[&mut] Self></code>.
//!
//! For example, you could implement [`Drop`][Drop] as follows:
Expand Down
6 changes: 1 addition & 5 deletions library/core/src/str/converts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,7 @@ pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
///
/// # Safety
///
/// This function is unsafe because it does not check that the bytes passed to
/// it are valid UTF-8. If this constraint is violated, undefined behavior
/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
///
/// [`&str`]: str
/// The bytes passed in must be valid UTF-8.
///
/// # Examples
///
Expand Down
20 changes: 14 additions & 6 deletions library/std/src/sys/unix/futex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
use crate::sync::atomic::AtomicI32;
use crate::time::Duration;

/// Wait for a futex_wake operation to wake us.
///
/// Returns directly if the futex doesn't hold the expected value.
///
/// Returns false on timeout, and true in all other cases.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) -> bool {
use super::time::Timespec;
Expand Down Expand Up @@ -68,18 +73,23 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
}
}

/// Wake up one thread that's blocked on futex_wait on this futex.
///
/// Returns true if this actually woke up such a thread,
/// or false if no thread was waiting on this futex.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wake(futex: &AtomicI32) {
pub fn futex_wake(futex: &AtomicI32) -> bool {
unsafe {
libc::syscall(
libc::SYS_futex,
futex as *const AtomicI32,
libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG,
1,
);
) > 0
}
}

/// Wake up all threads that are waiting on futex_wait on this futex.
#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn futex_wake_all(futex: &AtomicI32) {
unsafe {
Expand All @@ -93,12 +103,10 @@ pub fn futex_wake_all(futex: &AtomicI32) {
}

#[cfg(target_os = "emscripten")]
pub fn futex_wake(futex: &AtomicI32) {
pub fn futex_wake(futex: &AtomicI32) -> bool {
extern "C" {
fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int;
}

unsafe {
emscripten_futex_wake(futex as *const AtomicI32, 1);
}
unsafe { emscripten_futex_wake(futex as *const AtomicI32, 1) > 0 }
}
Loading

0 comments on commit de392c7

Please sign in to comment.