Skip to content
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

[beta] backports #137747

Merged
merged 12 commits into from
Mar 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ jobs:
- name: ensure the stable version number is correct
run: src/ci/scripts/verify-stable-version-number.sh

# Temporary fix to unblock CI
# Remove the latest Windows SDK for 32-bit Windows MSVC builds.
# See issue https://github.com/rust-lang/rust/issues/137733 for more details.
- name: Remove Windows SDK 10.0.26100.0
shell: powershell
if: ${{ matrix.name == 'i686-msvc-1' || matrix.name == 'i686-msvc-2' || matrix.name == 'dist-i686-msvc' }}
run: |
$kits = (Get-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots').KitsRoot10
$sdk_version = "10.0.26100.0"

foreach ($kind in 'Bin', 'Lib', 'Include') {
Remove-Item -Force -Recurse $kits\$kind\$sdk_version -ErrorAction Continue
}

- name: run the build
# Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
run: src/ci/scripts/run-build-from-ci.sh 2>&1
Expand Down
156 changes: 79 additions & 77 deletions compiler/rustc_lint/src/if_let_rescope.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::iter::repeat;
use std::ops::ControlFlow;

use hir::intravisit::Visitor;
use hir::intravisit::{self, Visitor};
use rustc_ast::Recovered;
use rustc_errors::{
Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
};
use rustc_hir::{self as hir, HirIdSet};
use rustc_macros::LintDiagnostic;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::adjustment::Adjust;
use rustc_session::lint::{FutureIncompatibilityReason, LintId};
use rustc_session::{declare_lint, impl_lint_pass};
use rustc_span::Span;
Expand Down Expand Up @@ -160,7 +161,7 @@ impl IfLetRescope {
let lifetime_end = source_map.end_point(conseq.span);

if let ControlFlow::Break(significant_dropper) =
(FindSignificantDropper { cx }).visit_expr(init)
(FindSignificantDropper { cx }).check_if_let_scrutinee(init)
{
first_if_to_lint = first_if_to_lint.or_else(|| Some((span, expr.hir_id)));
significant_droppers.push(significant_dropper);
Expand Down Expand Up @@ -363,96 +364,97 @@ enum SingleArmMatchBegin {
WithoutOpenBracket(Span),
}

struct FindSignificantDropper<'tcx, 'a> {
struct FindSignificantDropper<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}

impl<'tcx, 'a> Visitor<'tcx> for FindSignificantDropper<'tcx, 'a> {
type Result = ControlFlow<Span>;
impl<'tcx> FindSignificantDropper<'_, 'tcx> {
/// Check the scrutinee of an `if let` to see if it promotes any temporary values
/// that would change drop order in edition 2024. Specifically, it checks the value
/// of the scrutinee itself, and also recurses into the expression to find any ref
/// exprs (or autoref) which would promote temporaries that would be scoped to the
/// end of this `if`.
fn check_if_let_scrutinee(&mut self, init: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
self.check_promoted_temp_with_drop(init)?;
self.visit_expr(init)
}

fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
if self
/// Check that an expression is not a promoted temporary with a significant
/// drop impl.
///
/// An expression is a promoted temporary if it has an addr taken (i.e. `&expr` or autoref)
/// or is the scrutinee of the `if let`, *and* the expression is not a place
/// expr, and it has a significant drop.
fn check_promoted_temp_with_drop(&self, expr: &'tcx hir::Expr<'tcx>) -> ControlFlow<Span> {
if !expr.is_place_expr(|base| {
self.cx
.typeck_results()
.adjustments()
.get(base.hir_id)
.is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
}) && self
.cx
.typeck_results()
.expr_ty(expr)
.has_significant_drop(self.cx.tcx, self.cx.typing_env())
{
return ControlFlow::Break(expr.span);
ControlFlow::Break(expr.span)
} else {
ControlFlow::Continue(())
}
match expr.kind {
hir::ExprKind::ConstBlock(_)
| hir::ExprKind::Lit(_)
| hir::ExprKind::Path(_)
| hir::ExprKind::Assign(_, _, _)
| hir::ExprKind::AssignOp(_, _, _)
| hir::ExprKind::Break(_, _)
| hir::ExprKind::Continue(_)
| hir::ExprKind::Ret(_)
| hir::ExprKind::Become(_)
| hir::ExprKind::InlineAsm(_)
| hir::ExprKind::OffsetOf(_, _)
| hir::ExprKind::Repeat(_, _)
| hir::ExprKind::Err(_)
| hir::ExprKind::Struct(_, _, _)
| hir::ExprKind::Closure(_)
| hir::ExprKind::Block(_, _)
| hir::ExprKind::DropTemps(_)
| hir::ExprKind::Loop(_, _, _, _) => ControlFlow::Continue(()),
}
}

hir::ExprKind::Tup(exprs) | hir::ExprKind::Array(exprs) => {
for expr in exprs {
self.visit_expr(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::Call(callee, args) => {
self.visit_expr(callee)?;
for expr in args {
self.visit_expr(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::MethodCall(_, receiver, args, _) => {
self.visit_expr(receiver)?;
for expr in args {
self.visit_expr(expr)?;
impl<'tcx> Visitor<'tcx> for FindSignificantDropper<'_, 'tcx> {
type Result = ControlFlow<Span>;

fn visit_block(&mut self, b: &'tcx hir::Block<'tcx>) -> Self::Result {
// Blocks introduce temporary terminating scope for all of its
// statements, so just visit the tail expr, skipping over any
// statements. This prevents false positives like `{ let x = &Drop; }`.
if let Some(expr) = b.expr { self.visit_expr(expr) } else { ControlFlow::Continue(()) }
}

fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
// Check for promoted temporaries from autoref, e.g.
// `if let None = TypeWithDrop.as_ref() {} else {}`
// where `fn as_ref(&self) -> Option<...>`.
for adj in self.cx.typeck_results().expr_adjustments(expr) {
match adj.kind {
// Skip when we hit the first deref expr.
Adjust::Deref(_) => break,
Adjust::Borrow(_) => {
self.check_promoted_temp_with_drop(expr)?;
}
ControlFlow::Continue(())
}
hir::ExprKind::Index(left, right, _) | hir::ExprKind::Binary(_, left, right) => {
self.visit_expr(left)?;
self.visit_expr(right)
_ => {}
}
hir::ExprKind::Unary(_, expr)
| hir::ExprKind::Cast(expr, _)
| hir::ExprKind::Type(expr, _)
| hir::ExprKind::UnsafeBinderCast(_, expr, _)
| hir::ExprKind::Yield(expr, _)
| hir::ExprKind::AddrOf(_, _, expr)
| hir::ExprKind::Match(expr, _, _)
| hir::ExprKind::Field(expr, _)
| hir::ExprKind::Let(&hir::LetExpr {
init: expr,
span: _,
pat: _,
ty: _,
recovered: Recovered::No,
}) => self.visit_expr(expr),
hir::ExprKind::Let(_) => ControlFlow::Continue(()),
}

hir::ExprKind::If(cond, _, _) => {
if let hir::ExprKind::Let(hir::LetExpr {
init,
span: _,
pat: _,
ty: _,
recovered: Recovered::No,
}) = cond.kind
{
self.visit_expr(init)?;
}
ControlFlow::Continue(())
match expr.kind {
// Account for cases like `if let None = Some(&Drop) {} else {}`.
hir::ExprKind::AddrOf(_, _, expr) => {
self.check_promoted_temp_with_drop(expr)?;
intravisit::walk_expr(self, expr)
}
// `(Drop, ()).1` introduces a temporary and then moves out of
// part of it, therefore we should check it for temporaries.
// FIXME: This may have false positives if we move the part
// that actually has drop, but oh well.
hir::ExprKind::Index(expr, _, _) | hir::ExprKind::Field(expr, _) => {
self.check_promoted_temp_with_drop(expr)?;
intravisit::walk_expr(self, expr)
}
// If always introduces a temporary terminating scope for its cond and arms,
// so don't visit them.
hir::ExprKind::If(..) => ControlFlow::Continue(()),
// Match introduces temporary terminating scopes for arms, so don't visit
// them, and only visit the scrutinee to account for cases like:
// `if let None = match &Drop { _ => Some(1) } {} else {}`.
hir::ExprKind::Match(scrut, _, _) => self.visit_expr(scrut),
// Self explanatory.
hir::ExprKind::DropTemps(_) => ControlFlow::Continue(()),
// Otherwise, walk into the expr's parts.
_ => intravisit::walk_expr(self, expr),
}
}
}
4 changes: 2 additions & 2 deletions library/std/src/sys/pal/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ compat_fn_with_fallback! {
pub fn NtReleaseKeyedEvent(
EventHandle: HANDLE,
Key: *const c_void,
Alertable: BOOLEAN,
Alertable: bool,
Timeout: *mut i64
) -> NTSTATUS {
panic!("keyed events not available")
Expand All @@ -213,7 +213,7 @@ compat_fn_with_fallback! {
pub fn NtWaitForKeyedEvent(
EventHandle: HANDLE,
Key: *const c_void,
Alertable: BOOLEAN,
Alertable: bool,
Timeout: *mut i64
) -> NTSTATUS {
panic!("keyed events not available")
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/random/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn fill_bytes(mut bytes: &mut [u8]) {
while !bytes.is_empty() {
let len = bytes.len().try_into().unwrap_or(u32::MAX);
let ret = unsafe { c::RtlGenRandom(bytes.as_mut_ptr().cast(), len) };
assert_ne!(ret, 0, "failed to generate random data");
assert!(ret, "failed to generate random data");
bytes = &mut bytes[len as usize..];
}
}
2 changes: 1 addition & 1 deletion library/std/src/sys/sync/mutex/windows7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl Mutex {

#[inline]
pub fn try_lock(&self) -> bool {
unsafe { c::TryAcquireSRWLockExclusive(raw(self)) != 0 }
unsafe { c::TryAcquireSRWLockExclusive(raw(self)) }
}

#[inline]
Expand Down
8 changes: 4 additions & 4 deletions library/std/src/sys/sync/thread_parking/windows7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ mod keyed_events {

pub unsafe fn park(parker: Pin<&Parker>) {
// Wait for unpark() to produce this event.
c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut());
c::NtWaitForKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut());
// Set the state back to EMPTY (from either PARKED or NOTIFIED).
// Note that we don't just write EMPTY, but use swap() to also
// include an acquire-ordered read to synchronize with unpark()'s
Expand All @@ -218,7 +218,7 @@ mod keyed_events {

// Wait for unpark() to produce this event.
let unparked =
c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS;
c::NtWaitForKeyedEvent(handle, parker.ptr(), false, &mut timeout) == c::STATUS_SUCCESS;

// Set the state back to EMPTY (from either PARKED or NOTIFIED).
let prev_state = parker.state.swap(EMPTY, Acquire);
Expand All @@ -228,7 +228,7 @@ mod keyed_events {
// was set to NOTIFIED, which means we *just* missed an
// unpark(), which is now blocked on us to wait for it.
// Wait for it to consume the event and unblock that thread.
c::NtWaitForKeyedEvent(handle, parker.ptr(), 0, ptr::null_mut());
c::NtWaitForKeyedEvent(handle, parker.ptr(), false, ptr::null_mut());
}
}
pub unsafe fn unpark(parker: Pin<&Parker>) {
Expand All @@ -239,7 +239,7 @@ mod keyed_events {
// To prevent this thread from blocking indefinitely in that case,
// park_impl() will, after seeing the state set to NOTIFIED after
// waking up, call NtWaitForKeyedEvent again to unblock us.
c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), 0, ptr::null_mut());
c::NtReleaseKeyedEvent(keyed_event_handle(), parker.ptr(), false, ptr::null_mut());
}

fn keyed_event_handle() -> c::HANDLE {
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ dependencies = [

[[package]]
name = "cc"
version = "1.2.0"
version = "1.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
dependencies = [
"shlex",
]
Expand Down
4 changes: 3 additions & 1 deletion src/bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ test = false
# Most of the time updating these dependencies requires modifications to the
# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
cc = "=1.2.0"
#
# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
cc = "=1.1.22"
cmake = "=0.1.48"

build_helper = { path = "../build_helper" }
Expand Down
28 changes: 9 additions & 19 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use object::read::archive::ArchiveFile;

use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::tool::{self, Tool};
use crate::core::build_steps::vendor::default_paths_to_vendor;
use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
use crate::core::build_steps::{compile, llvm};
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
Expand Down Expand Up @@ -1050,19 +1050,6 @@ impl Step for PlainSourceTarball {
if builder.config.dist_vendor {
builder.require_and_update_all_submodules();

// Vendor all Cargo dependencies
let mut cmd = command(&builder.initial_cargo);
cmd.arg("vendor").arg("--versioned-dirs");

for (p, _) in default_paths_to_vendor(builder) {
cmd.arg("--sync").arg(p);
}

cmd
// Will read the libstd Cargo.toml which uses the unstable `public-dependency` feature.
.env("RUSTC_BOOTSTRAP", "1")
.current_dir(plain_dst_src);

// Vendor packages that are required by opt-dist to collect PGO profiles.
let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
.iter()
Expand All @@ -1074,15 +1061,18 @@ impl Step for PlainSourceTarball {
manifest_path.push("Cargo.toml");
manifest_path
});
for manifest_path in pkgs_for_pgo_training {
cmd.arg("--sync").arg(manifest_path);
}

let config = cmd.run_capture(builder).stdout();
// Vendor all Cargo dependencies
let vendor = builder.ensure(Vendor {
sync_args: pkgs_for_pgo_training.collect(),
versioned_dirs: true,
root_dir: plain_dst_src.into(),
output_dir: VENDOR_DIR.into(),
});

let cargo_config_dir = plain_dst_src.join(".cargo");
builder.create_dir(&cargo_config_dir);
builder.create(&cargo_config_dir.join("config.toml"), &config);
builder.create(&cargo_config_dir.join("config.toml"), &vendor.config);
}

// Delete extraneous directories
Expand Down
Loading
Loading