Auto merge of #137747 - cuviper:beta-next, r=cuviper
[beta] backports
- Pass vendored sources from bootstrap to generate-copyright #137020
- Fix `-win7-windows-msvc` target since 26eeac1a1e* #137270
- skip submodule updating logics on tarballs #137338
- Improve behavior of `IF_LET_RESCOPE` around temporaries and place expressions #137444
- downgrade bootstrap `cc` #137460
- Remove latest Windows SDK from 32-bit CI #137753
- [beta-1.86] Ensure we can package directories ending with '.rs' (rust-lang/cargo#15248) #137842
r? cuviper
This commit is contained in:
commit
61e1603ac7
21 changed files with 290 additions and 179 deletions
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
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,
|
||||
|
|
@ -9,6 +9,7 @@ use rustc_errors::{
|
|||
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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
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)?;
|
||||
}
|
||||
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(())
|
||||
}
|
||||
ControlFlow::Break(expr.span)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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..];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
@ -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>) {
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use crate::Mode;
|
|||
use crate::core::build_steps::dist::distdir;
|
||||
use crate::core::build_steps::test;
|
||||
use crate::core::build_steps::tool::{self, SourceType, Tool};
|
||||
use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
|
||||
use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::core::config::TargetSelection;
|
||||
use crate::core::config::flags::get_completion;
|
||||
|
|
@ -212,11 +213,39 @@ impl Step for GenerateCopyright {
|
|||
let dest = builder.out.join("COPYRIGHT.html");
|
||||
let dest_libstd = builder.out.join("COPYRIGHT-library.html");
|
||||
|
||||
let paths_to_vendor = default_paths_to_vendor(builder);
|
||||
for (_, submodules) in &paths_to_vendor {
|
||||
for submodule in submodules {
|
||||
builder.build.require_submodule(submodule, None);
|
||||
}
|
||||
}
|
||||
let cargo_manifests = paths_to_vendor
|
||||
.into_iter()
|
||||
.map(|(path, _submodules)| path.to_str().unwrap().to_string())
|
||||
.inspect(|path| assert!(!path.contains(','), "{path} contains a comma in its name"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
|
||||
let vendored_sources = if let Some(path) = builder.vendored_crates_path() {
|
||||
path
|
||||
} else {
|
||||
let cache_dir = builder.out.join("tmp").join("generate-copyright-vendor");
|
||||
builder.ensure(Vendor {
|
||||
sync_args: Vec::new(),
|
||||
versioned_dirs: true,
|
||||
root_dir: builder.src.clone(),
|
||||
output_dir: cache_dir.clone(),
|
||||
});
|
||||
cache_dir
|
||||
};
|
||||
|
||||
let mut cmd = builder.tool_cmd(Tool::GenerateCopyright);
|
||||
cmd.env("CARGO_MANIFESTS", &cargo_manifests);
|
||||
cmd.env("LICENSE_METADATA", &license_metadata);
|
||||
cmd.env("DEST", &dest);
|
||||
cmd.env("DEST_LIBSTD", &dest_libstd);
|
||||
cmd.env("OUT_DIR", &builder.out);
|
||||
cmd.env("SRC_DIR", &builder.src);
|
||||
cmd.env("VENDOR_DIR", &vendored_sources);
|
||||
cmd.env("CARGO", &builder.initial_cargo);
|
||||
// it is important that generate-copyright runs from the root of the
|
||||
// source tree, because it uses relative paths
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK;
|
|||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::utils::exec::command;
|
||||
|
||||
pub const VENDOR_DIR: &str = "vendor";
|
||||
|
||||
/// Returns the cargo workspaces to vendor for `x vendor` and dist tarballs.
|
||||
///
|
||||
/// Returns a `Vec` of `(path_to_manifest, submodules_required)` where
|
||||
|
|
@ -29,13 +31,14 @@ pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'sta
|
|||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct Vendor {
|
||||
sync_args: Vec<PathBuf>,
|
||||
versioned_dirs: bool,
|
||||
root_dir: PathBuf,
|
||||
pub(crate) sync_args: Vec<PathBuf>,
|
||||
pub(crate) versioned_dirs: bool,
|
||||
pub(crate) root_dir: PathBuf,
|
||||
pub(crate) output_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Step for Vendor {
|
||||
type Output = ();
|
||||
type Output = VendorOutput;
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
|
|
@ -48,10 +51,13 @@ impl Step for Vendor {
|
|||
sync_args: run.builder.config.cmd.vendor_sync_args(),
|
||||
versioned_dirs: run.builder.config.cmd.vendor_versioned_dirs(),
|
||||
root_dir: run.builder.src.clone(),
|
||||
output_dir: run.builder.src.join(VENDOR_DIR),
|
||||
});
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
builder.info(&format!("Vendoring sources to {:?}", self.root_dir));
|
||||
|
||||
let mut cmd = command(&builder.initial_cargo);
|
||||
cmd.arg("vendor");
|
||||
|
||||
|
|
@ -81,8 +87,14 @@ impl Step for Vendor {
|
|||
// which uses the unstable `public-dependency` feature.
|
||||
cmd.env("RUSTC_BOOTSTRAP", "1");
|
||||
|
||||
cmd.current_dir(self.root_dir);
|
||||
cmd.current_dir(self.root_dir).arg(&self.output_dir);
|
||||
|
||||
cmd.run(builder);
|
||||
let config = cmd.run_capture_stdout(builder);
|
||||
VendorOutput { config: config.stdout() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct VendorOutput {
|
||||
pub(crate) config: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -924,8 +924,7 @@ impl Builder<'_> {
|
|||
|
||||
if self.config.rust_remap_debuginfo {
|
||||
let mut env_var = OsString::new();
|
||||
if self.config.vendor {
|
||||
let vendor = self.build.src.join("vendor");
|
||||
if let Some(vendor) = self.build.vendored_crates_path() {
|
||||
env_var.push(vendor);
|
||||
env_var.push("=/rust/deps");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2748,7 +2748,7 @@ impl Config {
|
|||
/// used instead to provide a nice error to the user if the submodule is
|
||||
/// missing.
|
||||
pub(crate) fn update_submodule(&self, relative_path: &str) {
|
||||
if !self.submodules() {
|
||||
if self.rust_info.is_from_tarball() || !self.submodules() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ pub use utils::change_tracker::{
|
|||
CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes,
|
||||
};
|
||||
|
||||
use crate::core::build_steps::vendor::VENDOR_DIR;
|
||||
|
||||
const LLVM_TOOLS: &[&str] = &[
|
||||
"llvm-cov", // used to generate coverage report
|
||||
"llvm-nm", // used to inspect binaries; it shows symbol names, their sizes and visibility
|
||||
|
|
@ -470,6 +472,10 @@ impl Build {
|
|||
/// The given `err_hint` will be shown to the user if the submodule is not
|
||||
/// checked out and submodule management is disabled.
|
||||
pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
|
||||
if self.rust_info().is_from_tarball() {
|
||||
return;
|
||||
}
|
||||
|
||||
// When testing bootstrap itself, it is much faster to ignore
|
||||
// submodules. Almost all Steps work fine without their submodules.
|
||||
if cfg!(test) && !self.config.submodules() {
|
||||
|
|
@ -782,6 +788,11 @@ impl Build {
|
|||
self.out.join(target).join("md-doc")
|
||||
}
|
||||
|
||||
/// Path to the vendored Rust crates.
|
||||
fn vendored_crates_path(&self) -> Option<PathBuf> {
|
||||
if self.config.vendor { Some(self.src.join(VENDOR_DIR)) } else { None }
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an external version of LLVM not managed by bootstrap.
|
||||
/// In particular, we expect llvm sources to be available when this is false.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit fcb465caf719e68f05671947db75a66ca7fadb2a
|
||||
Subproject commit adf9b6ad14cfa10ff680d5806741a144f7163698
|
||||
|
|
@ -11,10 +11,6 @@ pub enum Error {
|
|||
Io(#[from] std::io::Error),
|
||||
#[error("Failed get output from cargo-metadata: {0:?}")]
|
||||
GettingMetadata(#[from] cargo_metadata::Error),
|
||||
#[error("Failed to run cargo vendor: {0:?}")]
|
||||
LaunchingVendor(std::io::Error),
|
||||
#[error("Failed to complete cargo vendor")]
|
||||
RunningVendor,
|
||||
#[error("Bad path {0:?} whilst scraping files")]
|
||||
Scraping(PathBuf),
|
||||
}
|
||||
|
|
@ -43,25 +39,19 @@ pub struct PackageMetadata {
|
|||
pub is_in_libstd: Option<bool>,
|
||||
}
|
||||
|
||||
/// Use `cargo metadata` and `cargo vendor` to get a list of dependencies and their license data.
|
||||
/// Use `cargo metadata` to get a list of dependencies and their license data. License files will
|
||||
/// also be pulled from the vendor path (generated by bootstrap).
|
||||
///
|
||||
/// This will involve running `cargo vendor` into `vendor_path` so we can
|
||||
/// grab the license files.
|
||||
///
|
||||
/// Any dependency with a path beginning with `root_path` is ignored, as we
|
||||
/// assume `reuse` has covered it already.
|
||||
/// Any dependency with a path beginning with `root_path` is ignored, as we assume `reuse` has
|
||||
/// covered it already.
|
||||
pub fn get_metadata_and_notices(
|
||||
cargo: &Path,
|
||||
vendor_path: &Path,
|
||||
root_path: &Path,
|
||||
manifest_paths: &[&Path],
|
||||
manifest_paths: &[PathBuf],
|
||||
) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
|
||||
let mut output = get_metadata(cargo, root_path, manifest_paths)?;
|
||||
|
||||
// Now do a cargo-vendor and grab everything
|
||||
println!("Vendoring deps into {}...", vendor_path.display());
|
||||
run_cargo_vendor(cargo, &vendor_path, manifest_paths)?;
|
||||
|
||||
// Now for each dependency we found, go and grab any important looking files
|
||||
for (package, metadata) in output.iter_mut() {
|
||||
load_important_files(package, metadata, &vendor_path)?;
|
||||
|
|
@ -77,7 +67,7 @@ pub fn get_metadata_and_notices(
|
|||
pub fn get_metadata(
|
||||
cargo: &Path,
|
||||
root_path: &Path,
|
||||
manifest_paths: &[&Path],
|
||||
manifest_paths: &[PathBuf],
|
||||
) -> Result<BTreeMap<Package, PackageMetadata>, Error> {
|
||||
let mut output = BTreeMap::new();
|
||||
// Look at the metadata for each manifest
|
||||
|
|
@ -113,28 +103,6 @@ pub fn get_metadata(
|
|||
Ok(output)
|
||||
}
|
||||
|
||||
/// Run cargo-vendor, fetching into the given dir
|
||||
fn run_cargo_vendor(cargo: &Path, dest: &Path, manifest_paths: &[&Path]) -> Result<(), Error> {
|
||||
let mut vendor_command = std::process::Command::new(cargo);
|
||||
vendor_command.env("RUSTC_BOOTSTRAP", "1");
|
||||
vendor_command.arg("vendor");
|
||||
vendor_command.arg("--quiet");
|
||||
vendor_command.arg("--versioned-dirs");
|
||||
for manifest_path in manifest_paths {
|
||||
vendor_command.arg("-s");
|
||||
vendor_command.arg(manifest_path);
|
||||
}
|
||||
vendor_command.arg(dest);
|
||||
|
||||
let vendor_status = vendor_command.status().map_err(Error::LaunchingVendor)?;
|
||||
|
||||
if !vendor_status.success() {
|
||||
return Err(Error::RunningVendor);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add important files off disk into this dependency.
|
||||
///
|
||||
/// Maybe one-day Cargo.toml will contain enough information that we don't need
|
||||
|
|
|
|||
|
|
@ -17,29 +17,36 @@ mod cargo_metadata;
|
|||
fn main() -> Result<(), Error> {
|
||||
let dest_file = env_path("DEST")?;
|
||||
let libstd_dest_file = env_path("DEST_LIBSTD")?;
|
||||
let out_dir = env_path("OUT_DIR")?;
|
||||
let src_dir = env_path("SRC_DIR")?;
|
||||
let vendor_dir = env_path("VENDOR_DIR")?;
|
||||
let cargo = env_path("CARGO")?;
|
||||
let license_metadata = env_path("LICENSE_METADATA")?;
|
||||
|
||||
let root_path = std::path::absolute(".")?;
|
||||
let cargo_manifests = env_string("CARGO_MANIFESTS")?
|
||||
.split(",")
|
||||
.map(|manifest| manifest.into())
|
||||
.collect::<Vec<PathBuf>>();
|
||||
let library_manifests = cargo_manifests
|
||||
.iter()
|
||||
.filter(|path| {
|
||||
if let Ok(stripped) = path.strip_prefix(&src_dir) {
|
||||
stripped.starts_with("library")
|
||||
} else {
|
||||
panic!("manifest {path:?} not relative to source dir {src_dir:?}");
|
||||
}
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Scan Cargo dependencies
|
||||
let mut collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
|
||||
&cargo,
|
||||
&out_dir.join("vendor"),
|
||||
&root_path,
|
||||
&[
|
||||
Path::new("./Cargo.toml"),
|
||||
Path::new("./src/tools/cargo/Cargo.toml"),
|
||||
Path::new("./library/Cargo.toml"),
|
||||
],
|
||||
)?;
|
||||
let mut collected_cargo_metadata =
|
||||
cargo_metadata::get_metadata_and_notices(&cargo, &vendor_dir, &src_dir, &cargo_manifests)?;
|
||||
|
||||
let library_collected_cargo_metadata = cargo_metadata::get_metadata_and_notices(
|
||||
&cargo,
|
||||
&out_dir.join("library-vendor"),
|
||||
&root_path,
|
||||
&[Path::new("./library/Cargo.toml")],
|
||||
&vendor_dir,
|
||||
&src_dir,
|
||||
&library_manifests,
|
||||
)?;
|
||||
|
||||
for (key, value) in collected_cargo_metadata.iter_mut() {
|
||||
|
|
@ -54,7 +61,7 @@ fn main() -> Result<(), Error> {
|
|||
let library_collected_tree_metadata = Metadata {
|
||||
files: collected_tree_metadata
|
||||
.files
|
||||
.trim_clone(&Path::new("./library"), &Path::new("."))
|
||||
.trim_clone(&src_dir.join("library"), &src_dir)
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
|
|
@ -193,6 +200,17 @@ struct License {
|
|||
copyright: Vec<String>,
|
||||
}
|
||||
|
||||
/// Grab an environment variable as string, or fail nicely.
|
||||
fn env_string(var: &str) -> Result<String, Error> {
|
||||
match std::env::var(var) {
|
||||
Ok(var) => Ok(var),
|
||||
Err(std::env::VarError::NotUnicode(_)) => {
|
||||
anyhow::bail!("environment variable {var} is not utf-8")
|
||||
}
|
||||
Err(std::env::VarError::NotPresent) => anyhow::bail!("missing environment variable {var}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Grab an environment variable as a PathBuf, or fail nicely.
|
||||
fn env_path(var: &str) -> Result<PathBuf, Error> {
|
||||
if let Some(var) = std::env::var_os(var) {
|
||||
|
|
|
|||
33
tests/ui/drop/lint-if-let-rescope-false-positives.rs
Normal file
33
tests/ui/drop/lint-if-let-rescope-false-positives.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//@ edition: 2021
|
||||
//@ check-pass
|
||||
|
||||
#![deny(if_let_rescope)]
|
||||
|
||||
struct Drop;
|
||||
impl std::ops::Drop for Drop {
|
||||
fn drop(&mut self) {
|
||||
println!("drop")
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop {
|
||||
fn as_ref(&self) -> Option<i32> {
|
||||
Some(1)
|
||||
}
|
||||
}
|
||||
|
||||
fn consume(_: impl Sized) -> Option<i32> { Some(1) }
|
||||
|
||||
fn main() {
|
||||
let drop = Drop;
|
||||
|
||||
// Make sure we don't drop if we don't actually make a temporary.
|
||||
if let None = drop.as_ref() {} else {}
|
||||
|
||||
// Make sure we don't lint if we consume the droppy value.
|
||||
if let None = consume(Drop) {} else {}
|
||||
|
||||
// Make sure we don't lint on field exprs of place exprs.
|
||||
let tup_place = (Drop, ());
|
||||
if let None = consume(tup_place.1) {} else {}
|
||||
}
|
||||
|
|
@ -94,6 +94,12 @@ fn main() {
|
|||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||
}
|
||||
|
||||
match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
|
||||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
|
||||
//~| WARN: this changes meaning in Rust 2024
|
||||
//~| HELP: the value is now dropped here in Edition 2024
|
||||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||
|
||||
// We want to keep the `if let`s below as direct descendents of match arms,
|
||||
// so the formatting is suppressed.
|
||||
#[rustfmt::skip]
|
||||
|
|
|
|||
|
|
@ -94,6 +94,12 @@ fn main() {
|
|||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||
}
|
||||
|
||||
if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
|
||||
//~| WARN: this changes meaning in Rust 2024
|
||||
//~| HELP: the value is now dropped here in Edition 2024
|
||||
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||
|
||||
// We want to keep the `if let`s below as direct descendents of match arms,
|
||||
// so the formatting is suppressed.
|
||||
#[rustfmt::skip]
|
||||
|
|
|
|||
|
|
@ -175,5 +175,26 @@ LL - while (if let Some(_value) = droppy().get() { false } else { true }) {
|
|||
LL + while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: `if let` assigns a shorter lifetime since Edition 2024
|
||||
--> $DIR/lint-if-let-rescope.rs:97:8
|
||||
|
|
||||
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^--------------^^^
|
||||
| |
|
||||
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
|
||||
|
|
||||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
|
||||
help: the value is now dropped here in Edition 2024
|
||||
--> $DIR/lint-if-let-rescope.rs:97:51
|
||||
|
|
||||
LL | if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||
| ^
|
||||
help: a `match` with a single arm can preserve the drop order up to Edition 2021
|
||||
|
|
||||
LL - if let Some(_value) = Some((droppy(), ()).1) {} else {}
|
||||
LL + match Some((droppy(), ()).1) { Some(_value) => {} _ => {}}
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue