Skip to content

Commit 4eb1612

Browse files
committed
Auto merge of #138521 - cuviper:stable-next, r=cuviper
[stable] Release 1.85.1 - [Fix the doctest-merging feature of the 2024 Edition.](#137899) - [Relax some `target_feature` checks when generating docs.](#137632) - [Fix errors in `std::fs::rename` on Windows 1607.](#137528) - [Downgrade bootstrap `cc` to fix custom targets.](#137460) - [Skip submodule updates when building Rust from a source tarball.](#137338) Added backports to fix CI: - Remove latest Windows SDK from 32-bit CI #137753 - Do not install rustup on Rust for Linux job #137947 cc `@rust-lang/release` r? cuviper
2 parents 4d91de4 + 4d11490 commit 4eb1612

File tree

19 files changed

+395
-211
lines changed

19 files changed

+395
-211
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,20 @@ jobs:
189189
- name: ensure the stable version number is correct
190190
run: src/ci/scripts/verify-stable-version-number.sh
191191

192+
# Temporary fix to unblock CI
193+
# Remove the latest Windows SDK for 32-bit Windows MSVC builds.
194+
# See issue https://github.com/rust-lang/rust/issues/137733 for more details.
195+
- name: Remove Windows SDK 10.0.26100.0
196+
shell: powershell
197+
if: ${{ matrix.image == 'i686-msvc' || matrix.image == 'dist-i686-msvc' }}
198+
run: |
199+
$kits = (Get-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots').KitsRoot10
200+
$sdk_version = "10.0.26100.0"
201+
202+
foreach ($kind in 'Bin', 'Lib', 'Include') {
203+
Remove-Item -Force -Recurse $kits\$kind\$sdk_version -ErrorAction Continue
204+
}
205+
192206
- name: run the build
193207
# Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
194208
run: src/ci/scripts/run-build-from-ci.sh 2>&1

RELEASES.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
Version 1.85.1 (2025-03-18)
2+
==========================
3+
4+
<a id="1.85.1"></a>
5+
6+
- [Fix the doctest-merging feature of the 2024 Edition.](https://github.com/rust-lang/rust/pull/137899/)
7+
- [Relax some `target_feature` checks when generating docs.](https://github.com/rust-lang/rust/pull/137632/)
8+
- [Fix errors in `std::fs::rename` on Windows 1607.](https://github.com/rust-lang/rust/pull/137528/)
9+
- [Downgrade bootstrap `cc` to fix custom targets.](https://github.com/rust-lang/rust/pull/137460/)
10+
- [Skip submodule updates when building Rust from a source tarball.](https://github.com/rust-lang/rust/pull/137338/)
11+
112
Version 1.85.0 (2025-02-20)
213
==========================
314

compiler/rustc_codegen_ssa/src/target_features.rs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
1111
use rustc_session::parse::feature_err;
1212
use rustc_span::{Span, Symbol, sym};
13-
use rustc_target::target_features;
13+
use rustc_target::target_features::{self, Stability};
1414

1515
use crate::errors;
1616

@@ -65,11 +65,16 @@ pub(crate) fn from_target_feature_attr(
6565
// Only allow target features whose feature gates have been enabled
6666
// and which are permitted to be toggled.
6767
if let Err(reason) = stability.toggle_allowed(/*enable*/ true) {
68-
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
69-
span: item.span(),
70-
feature,
71-
reason,
72-
});
68+
// We skip this error in rustdoc, where we want to allow all target features of
69+
// all targets, so we can't check their ABI compatibility and anyway we are not
70+
// generating code so "it's fine".
71+
if !tcx.sess.opts.actually_rustdoc {
72+
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
73+
span: item.span(),
74+
feature,
75+
reason,
76+
});
77+
}
7378
} else if let Some(nightly_feature) = stability.requires_nightly()
7479
&& !rust_features.enabled(nightly_feature)
7580
{
@@ -149,11 +154,38 @@ pub(crate) fn provide(providers: &mut Providers) {
149154
assert_eq!(cnum, LOCAL_CRATE);
150155
let target = &tcx.sess.target;
151156
if tcx.sess.opts.actually_rustdoc {
152-
// rustdoc needs to be able to document functions that use all the features, so
153-
// whitelist them all
154-
rustc_target::target_features::all_rust_features()
155-
.map(|(a, b)| (a.to_string(), b.compute_toggleability(target)))
156-
.collect()
157+
// HACK: rustdoc would like to pretend that we have all the target features, so we
158+
// have to merge all the lists into one. To ensure an unstable target never prevents
159+
// a stable one from working, we merge the stability info of all instances of the
160+
// same target feature name, with the "most stable" taking precedence. And then we
161+
// hope that this doesn't cause issues anywhere else in the compiler...
162+
let mut result: UnordMap<String, Stability<_>> = Default::default();
163+
for (name, stability) in rustc_target::target_features::all_rust_features() {
164+
use std::collections::hash_map::Entry;
165+
match result.entry(name.to_owned()) {
166+
Entry::Vacant(vacant_entry) => {
167+
vacant_entry.insert(stability.compute_toggleability(target));
168+
}
169+
Entry::Occupied(mut occupied_entry) => {
170+
// Merge the two stabilities, "more stable" taking precedence.
171+
match (occupied_entry.get(), &stability) {
172+
(Stability::Stable { .. }, _)
173+
| (
174+
Stability::Unstable { .. },
175+
Stability::Unstable { .. } | Stability::Forbidden { .. },
176+
)
177+
| (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => {
178+
// The stability in the entry is at least as good as the new one, just keep it.
179+
}
180+
_ => {
181+
// Overwrite stabilite.
182+
occupied_entry.insert(stability.compute_toggleability(target));
183+
}
184+
}
185+
}
186+
}
187+
}
188+
result
157189
} else {
158190
tcx.sess
159191
.target

library/std/src/fs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2402,7 +2402,7 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
24022402
/// # Platform-specific behavior
24032403
///
24042404
/// This function currently corresponds to the `rename` function on Unix
2405-
/// and the `SetFileInformationByHandle` function on Windows.
2405+
/// and the `MoveFileExW` or `SetFileInformationByHandle` function on Windows.
24062406
///
24072407
/// Because of this, the behavior when both `from` and `to` exist differs. On
24082408
/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If

library/std/src/sys/pal/windows/fs.rs

Lines changed: 60 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use super::api::{self, WinError};
22
use super::{IoResult, to_u16s};
3-
use crate::alloc::{alloc, handle_alloc_error};
3+
use crate::alloc::{Layout, alloc, dealloc};
44
use crate::borrow::Cow;
55
use crate::ffi::{OsStr, OsString, c_void};
66
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
7-
use crate::mem::{self, MaybeUninit};
7+
use crate::mem::{self, MaybeUninit, offset_of};
88
use crate::os::windows::io::{AsHandle, BorrowedHandle};
99
use crate::os::windows::prelude::*;
1010
use crate::path::{Path, PathBuf};
@@ -296,6 +296,10 @@ impl OpenOptions {
296296
impl File {
297297
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
298298
let path = maybe_verbatim(path)?;
299+
Self::open_native(&path, opts)
300+
}
301+
302+
fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> {
299303
let creation = opts.get_creation_mode()?;
300304
let handle = unsafe {
301305
c::CreateFileW(
@@ -1234,141 +1238,72 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
12341238
let old = maybe_verbatim(old)?;
12351239
let new = maybe_verbatim(new)?;
12361240

1237-
let new_len_without_nul_in_bytes = (new.len() - 1).try_into().unwrap();
1238-
1239-
// The last field of FILE_RENAME_INFO, the file name, is unsized,
1240-
// and FILE_RENAME_INFO has two padding bytes.
1241-
// Therefore we need to make sure to not allocate less than
1242-
// size_of::<c::FILE_RENAME_INFO>() bytes, which would be the case with
1243-
// 0 or 1 character paths + a null byte.
1244-
let struct_size = mem::size_of::<c::FILE_RENAME_INFO>()
1245-
.max(mem::offset_of!(c::FILE_RENAME_INFO, FileName) + new.len() * mem::size_of::<u16>());
1246-
1247-
let struct_size: u32 = struct_size.try_into().unwrap();
1248-
1249-
let create_file = |extra_access, extra_flags| {
1250-
let handle = unsafe {
1251-
HandleOrInvalid::from_raw_handle(c::CreateFileW(
1252-
old.as_ptr(),
1253-
c::SYNCHRONIZE | c::DELETE | extra_access,
1254-
c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE,
1255-
ptr::null(),
1256-
c::OPEN_EXISTING,
1257-
c::FILE_ATTRIBUTE_NORMAL | c::FILE_FLAG_BACKUP_SEMANTICS | extra_flags,
1258-
ptr::null_mut(),
1259-
))
1260-
};
1261-
1262-
OwnedHandle::try_from(handle).map_err(|_| io::Error::last_os_error())
1263-
};
1264-
1265-
// The following code replicates `MoveFileEx`'s behavior as reverse-engineered from its disassembly.
1266-
// If `old` refers to a mount point, we move it instead of the target.
1267-
let handle = match create_file(c::FILE_READ_ATTRIBUTES, c::FILE_FLAG_OPEN_REPARSE_POINT) {
1268-
Ok(handle) => {
1269-
let mut file_attribute_tag_info: MaybeUninit<c::FILE_ATTRIBUTE_TAG_INFO> =
1270-
MaybeUninit::uninit();
1271-
1272-
let result = unsafe {
1273-
cvt(c::GetFileInformationByHandleEx(
1274-
handle.as_raw_handle(),
1275-
c::FileAttributeTagInfo,
1276-
file_attribute_tag_info.as_mut_ptr().cast(),
1277-
mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
1278-
))
1241+
if unsafe { c::MoveFileExW(old.as_ptr(), new.as_ptr(), c::MOVEFILE_REPLACE_EXISTING) } == 0 {
1242+
let err = api::get_last_error();
1243+
// if `MoveFileExW` fails with ERROR_ACCESS_DENIED then try to move
1244+
// the file while ignoring the readonly attribute.
1245+
// This is accomplished by calling `SetFileInformationByHandle` with `FileRenameInfoEx`.
1246+
if err == WinError::ACCESS_DENIED {
1247+
let mut opts = OpenOptions::new();
1248+
opts.access_mode(c::DELETE);
1249+
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
1250+
let Ok(f) = File::open_native(&old, &opts) else { return Err(err).io_result() };
1251+
1252+
// Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
1253+
// This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
1254+
let Ok(new_len_without_nul_in_bytes): Result<u32, _> = ((new.len() - 1) * 2).try_into()
1255+
else {
1256+
return Err(err).io_result();
12791257
};
1280-
1281-
if let Err(err) = result {
1282-
if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _)
1283-
|| err.raw_os_error() == Some(c::ERROR_INVALID_FUNCTION as _)
1284-
{
1285-
// `GetFileInformationByHandleEx` documents that not all underlying drivers support all file information classes.
1286-
// Since we know we passed the correct arguments, this means the underlying driver didn't understand our request;
1287-
// `MoveFileEx` proceeds by reopening the file without inhibiting reparse point behavior.
1288-
None
1289-
} else {
1290-
Some(Err(err))
1291-
}
1292-
} else {
1293-
// SAFETY: The struct has been initialized by GetFileInformationByHandleEx
1294-
let file_attribute_tag_info = unsafe { file_attribute_tag_info.assume_init() };
1295-
let file_type = FileType::new(
1296-
file_attribute_tag_info.FileAttributes,
1297-
file_attribute_tag_info.ReparseTag,
1298-
);
1299-
1300-
if file_type.is_symlink() {
1301-
// The file is a mount point, junction point or symlink so
1302-
// don't reopen the file so that the link gets renamed.
1303-
Some(Ok(handle))
1304-
} else {
1305-
// Otherwise reopen the file without inhibiting reparse point behavior.
1306-
None
1258+
let offset: u32 = offset_of!(c::FILE_RENAME_INFO, FileName).try_into().unwrap();
1259+
let struct_size = offset + new_len_without_nul_in_bytes + 2;
1260+
let layout =
1261+
Layout::from_size_align(struct_size as usize, align_of::<c::FILE_RENAME_INFO>())
1262+
.unwrap();
1263+
1264+
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
1265+
let file_rename_info;
1266+
unsafe {
1267+
file_rename_info = alloc(layout).cast::<c::FILE_RENAME_INFO>();
1268+
if file_rename_info.is_null() {
1269+
return Err(io::ErrorKind::OutOfMemory.into());
13071270
}
1308-
}
1309-
}
1310-
// The underlying driver may not support `FILE_FLAG_OPEN_REPARSE_POINT`: Retry without it.
1311-
Err(err) if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _) => None,
1312-
Err(err) => Some(Err(err)),
1313-
}
1314-
.unwrap_or_else(|| create_file(0, 0))?;
13151271

1316-
let layout = core::alloc::Layout::from_size_align(
1317-
struct_size as _,
1318-
mem::align_of::<c::FILE_RENAME_INFO>(),
1319-
)
1320-
.unwrap();
1321-
1322-
let file_rename_info = unsafe { alloc(layout) } as *mut c::FILE_RENAME_INFO;
1323-
1324-
if file_rename_info.is_null() {
1325-
handle_alloc_error(layout);
1326-
}
1327-
1328-
// SAFETY: file_rename_info is a non-null pointer pointing to memory allocated by the global allocator.
1329-
let mut file_rename_info = unsafe { Box::from_raw(file_rename_info) };
1330-
1331-
// SAFETY: We have allocated enough memory for a full FILE_RENAME_INFO struct and a filename.
1332-
unsafe {
1333-
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
1334-
Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS | c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
1335-
});
1336-
1337-
(&raw mut (*file_rename_info).RootDirectory).write(ptr::null_mut());
1338-
(&raw mut (*file_rename_info).FileNameLength).write(new_len_without_nul_in_bytes);
1339-
1340-
new.as_ptr()
1341-
.copy_to_nonoverlapping((&raw mut (*file_rename_info).FileName) as *mut u16, new.len());
1342-
}
1272+
(&raw mut (*file_rename_info).Anonymous).write(c::FILE_RENAME_INFO_0 {
1273+
Flags: c::FILE_RENAME_FLAG_REPLACE_IF_EXISTS
1274+
| c::FILE_RENAME_FLAG_POSIX_SEMANTICS,
1275+
});
13431276

1344-
// We don't use `set_file_information_by_handle` here as `FILE_RENAME_INFO` is used for both `FileRenameInfo` and `FileRenameInfoEx`.
1345-
let result = unsafe {
1346-
cvt(c::SetFileInformationByHandle(
1347-
handle.as_raw_handle(),
1348-
c::FileRenameInfoEx,
1349-
(&raw const *file_rename_info).cast::<c_void>(),
1350-
struct_size,
1351-
))
1352-
};
1277+
(&raw mut (*file_rename_info).RootDirectory).write(ptr::null_mut());
1278+
// Don't include the NULL in the size
1279+
(&raw mut (*file_rename_info).FileNameLength).write(new_len_without_nul_in_bytes);
13531280

1354-
if let Err(err) = result {
1355-
if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _) {
1356-
// FileRenameInfoEx and FILE_RENAME_FLAG_POSIX_SEMANTICS were added in Windows 10 1607; retry with FileRenameInfo.
1357-
file_rename_info.Anonymous.ReplaceIfExists = 1;
1281+
new.as_ptr().copy_to_nonoverlapping(
1282+
(&raw mut (*file_rename_info).FileName).cast::<u16>(),
1283+
new.len(),
1284+
);
1285+
}
13581286

1359-
cvt(unsafe {
1287+
let result = unsafe {
13601288
c::SetFileInformationByHandle(
1361-
handle.as_raw_handle(),
1362-
c::FileRenameInfo,
1363-
(&raw const *file_rename_info).cast::<c_void>(),
1289+
f.as_raw_handle(),
1290+
c::FileRenameInfoEx,
1291+
file_rename_info.cast::<c_void>(),
13641292
struct_size,
13651293
)
1366-
})?;
1294+
};
1295+
unsafe { dealloc(file_rename_info.cast::<u8>(), layout) };
1296+
if result == 0 {
1297+
if api::get_last_error() == WinError::DIR_NOT_EMPTY {
1298+
return Err(WinError::DIR_NOT_EMPTY).io_result();
1299+
} else {
1300+
return Err(err).io_result();
1301+
}
1302+
}
13671303
} else {
1368-
return Err(err);
1304+
return Err(err).io_result();
13691305
}
13701306
}
1371-
13721307
Ok(())
13731308
}
13741309

src/bootstrap/Cargo.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ dependencies = [
8484

8585
[[package]]
8686
name = "cc"
87-
version = "1.2.0"
87+
version = "1.1.22"
8888
source = "registry+https://github.com/rust-lang/crates.io-index"
89-
checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
89+
checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0"
9090
dependencies = [
9191
"shlex",
9292
]

src/bootstrap/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ test = false
3636
# Most of the time updating these dependencies requires modifications to the
3737
# bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
3838
# otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
39-
cc = "=1.2.0"
39+
#
40+
# Do not upgrade this crate unless https://github.com/rust-lang/cc-rs/issues/1317 is fixed.
41+
cc = "=1.1.22"
4042
cmake = "=0.1.48"
4143

4244
build_helper = { path = "../build_helper" }

src/bootstrap/src/core/config/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2668,7 +2668,7 @@ impl Config {
26682668
/// used instead to provide a nice error to the user if the submodule is
26692669
/// missing.
26702670
pub(crate) fn update_submodule(&self, relative_path: &str) {
2671-
if !self.submodules() {
2671+
if self.rust_info.is_from_tarball() || !self.submodules() {
26722672
return;
26732673
}
26742674

src/bootstrap/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ impl Build {
471471
/// The given `err_hint` will be shown to the user if the submodule is not
472472
/// checked out and submodule management is disabled.
473473
pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
474+
if self.rust_info().is_from_tarball() {
475+
return;
476+
}
477+
474478
// When testing bootstrap itself, it is much faster to ignore
475479
// submodules. Almost all Steps work fine without their submodules.
476480
if cfg!(test) && !self.config.submodules() {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy