Skip to content

Commit b218b95

Browse files
committed
Auto merge of rust-lang#77381 - Dylan-DPC:rollup-0sr6p5p, r=Dylan-DPC
Rollup of 12 pull requests Successful merges: - rust-lang#76909 (Add Iterator::advance_by and DoubleEndedIterator::advance_back_by) - rust-lang#77153 (Fix recursive nonterminal expansion during pretty-print/reparse check) - rust-lang#77202 (Defer Apple SDKROOT detection to link time.) - rust-lang#77303 (const evaluatable: improve `TooGeneric` handling) - rust-lang#77305 (move candidate_from_obligation_no_cache) - rust-lang#77315 (Rename AllocErr to AllocError) - rust-lang#77319 (Stable hashing: add comments and tests concerning platform-independence) - rust-lang#77324 (Don't fire `const_item_mutation` lint on writes through a pointer) - rust-lang#77343 (Validate `rustc_args_required_const`) - rust-lang#77349 (Update cargo) - rust-lang#77360 (References to ZSTs may be at arbitrary aligned addresses) - rust-lang#77371 (Remove trailing space in error message) Failed merges: r? `@ghost`
2 parents 9bb55dc + 85e77ed commit b218b95

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1194
-516
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+86
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15241524
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
15251525
add_pre_link_args(cmd, sess, flavor);
15261526

1527+
// NO-OPT-OUT, OBJECT-FILES-NO
1528+
add_apple_sdk(cmd, sess, flavor);
1529+
15271530
// NO-OPT-OUT
15281531
add_link_script(cmd, sess, tmpdir, crate_type);
15291532

@@ -2083,3 +2086,86 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
20832086
config::Lto::No | config::Lto::ThinLocal => false,
20842087
}
20852088
}
2089+
2090+
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
2091+
let arch = &sess.target.target.arch;
2092+
let os = &sess.target.target.target_os;
2093+
let llvm_target = &sess.target.target.llvm_target;
2094+
if sess.target.target.target_vendor != "apple"
2095+
|| !matches!(os.as_str(), "ios" | "tvos")
2096+
|| flavor != LinkerFlavor::Gcc
2097+
{
2098+
return;
2099+
}
2100+
let sdk_name = match (arch.as_str(), os.as_str()) {
2101+
("aarch64", "tvos") => "appletvos",
2102+
("x86_64", "tvos") => "appletvsimulator",
2103+
("arm", "ios") => "iphoneos",
2104+
("aarch64", "ios") => "iphoneos",
2105+
("x86", "ios") => "iphonesimulator",
2106+
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx10.15",
2107+
("x86_64", "ios") => "iphonesimulator",
2108+
_ => {
2109+
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
2110+
return;
2111+
}
2112+
};
2113+
let sdk_root = match get_apple_sdk_root(sdk_name) {
2114+
Ok(s) => s,
2115+
Err(e) => {
2116+
sess.err(&e);
2117+
return;
2118+
}
2119+
};
2120+
let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen");
2121+
cmd.args(&["-arch", arch_name, "-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
2122+
}
2123+
2124+
fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
2125+
// Following what clang does
2126+
// (https://github.com/llvm/llvm-project/blob/
2127+
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
2128+
// to allow the SDK path to be set. (For clang, xcrun sets
2129+
// SDKROOT; for rustc, the user or build system can set it, or we
2130+
// can fall back to checking for xcrun on PATH.)
2131+
if let Ok(sdkroot) = env::var("SDKROOT") {
2132+
let p = Path::new(&sdkroot);
2133+
match sdk_name {
2134+
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
2135+
"appletvos"
2136+
if sdkroot.contains("TVSimulator.platform")
2137+
|| sdkroot.contains("MacOSX.platform") => {}
2138+
"appletvsimulator"
2139+
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
2140+
"iphoneos"
2141+
if sdkroot.contains("iPhoneSimulator.platform")
2142+
|| sdkroot.contains("MacOSX.platform") => {}
2143+
"iphonesimulator"
2144+
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
2145+
}
2146+
"macosx10.15"
2147+
if sdkroot.contains("iPhoneOS.platform")
2148+
|| sdkroot.contains("iPhoneSimulator.platform") => {}
2149+
// Ignore `SDKROOT` if it's not a valid path.
2150+
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
2151+
_ => return Ok(sdkroot),
2152+
}
2153+
}
2154+
let res =
2155+
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
2156+
|output| {
2157+
if output.status.success() {
2158+
Ok(String::from_utf8(output.stdout).unwrap())
2159+
} else {
2160+
let error = String::from_utf8(output.stderr);
2161+
let error = format!("process exit with error: {}", error.unwrap());
2162+
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
2163+
}
2164+
},
2165+
);
2166+
2167+
match res {
2168+
Ok(output) => Ok(output.trim().to_string()),
2169+
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
2170+
}
2171+
}

compiler/rustc_data_structures/src/sip128.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,28 @@ impl SipHasher128 {
125125

126126
// A specialized write function for values with size <= 8.
127127
//
128-
// The hashing of multi-byte integers depends on endianness. E.g.:
128+
// The input must be zero-extended to 64-bits by the caller. This extension
129+
// isn't hashed, but the implementation requires it for correctness.
130+
//
131+
// This function, given the same integer size and value, has the same effect
132+
// on both little- and big-endian hardware. It operates on values without
133+
// depending on their sequence in memory, so is independent of endianness.
134+
//
135+
// However, we want SipHasher128 to be platform-dependent, in order to be
136+
// consistent with the platform-dependent SipHasher in libstd. In other
137+
// words, we want:
138+
//
129139
// - little-endian: `write_u32(0xDDCCBBAA)` == `write([0xAA, 0xBB, 0xCC, 0xDD])`
130140
// - big-endian: `write_u32(0xDDCCBBAA)` == `write([0xDD, 0xCC, 0xBB, 0xAA])`
131141
//
132-
// This function does the right thing for little-endian hardware. On
133-
// big-endian hardware `x` must be byte-swapped first to give the right
134-
// behaviour. After any byte-swapping, the input must be zero-extended to
135-
// 64-bits. The caller is responsible for the byte-swapping and
136-
// zero-extension.
142+
// Therefore, in order to produce endian-dependent results, SipHasher128's
143+
// `write_xxx` Hasher trait methods byte-swap `x` prior to zero-extending.
144+
//
145+
// If clients of SipHasher128 itself want platform-independent results, they
146+
// *also* must byte-swap integer inputs before invoking the `write_xxx`
147+
// methods on big-endian hardware (that is, two byte-swaps must occur--one
148+
// in the client, and one in SipHasher128). Additionally, they must extend
149+
// `usize` and `isize` types to 64 bits on 32-bit systems.
137150
#[inline]
138151
fn short_write<T>(&mut self, _x: T, x: u64) {
139152
let size = mem::size_of::<T>();

compiler/rustc_data_structures/src/sip128/tests.rs

+45-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use super::*;
22

33
use std::hash::{Hash, Hasher};
4-
use std::{mem, slice};
54

65
// Hash just the bytes of the slice, without length prefix
76
struct Bytes<'a>(&'a [u8]);
@@ -399,20 +398,55 @@ fn test_hash_no_concat_alias() {
399398
}
400399

401400
#[test]
402-
fn test_write_short_works() {
403-
let test_usize = 0xd0c0b0a0usize;
401+
fn test_short_write_works() {
402+
let test_u8 = 0xFF_u8;
403+
let test_u16 = 0x1122_u16;
404+
let test_u32 = 0x22334455_u32;
405+
let test_u64 = 0x33445566_778899AA_u64;
406+
let test_u128 = 0x11223344_55667788_99AABBCC_DDEEFF77_u128;
407+
let test_usize = 0xD0C0B0A0_usize;
408+
409+
let test_i8 = -1_i8;
410+
let test_i16 = -2_i16;
411+
let test_i32 = -3_i32;
412+
let test_i64 = -4_i64;
413+
let test_i128 = -5_i128;
414+
let test_isize = -6_isize;
415+
404416
let mut h1 = SipHasher128::new_with_keys(0, 0);
405-
h1.write_usize(test_usize);
406417
h1.write(b"bytes");
407418
h1.write(b"string");
408-
h1.write_u8(0xFFu8);
409-
h1.write_u8(0x01u8);
419+
h1.write_u8(test_u8);
420+
h1.write_u16(test_u16);
421+
h1.write_u32(test_u32);
422+
h1.write_u64(test_u64);
423+
h1.write_u128(test_u128);
424+
h1.write_usize(test_usize);
425+
h1.write_i8(test_i8);
426+
h1.write_i16(test_i16);
427+
h1.write_i32(test_i32);
428+
h1.write_i64(test_i64);
429+
h1.write_i128(test_i128);
430+
h1.write_isize(test_isize);
431+
410432
let mut h2 = SipHasher128::new_with_keys(0, 0);
411-
h2.write(unsafe {
412-
slice::from_raw_parts(&test_usize as *const _ as *const u8, mem::size_of::<usize>())
413-
});
414433
h2.write(b"bytes");
415434
h2.write(b"string");
416-
h2.write(&[0xFFu8, 0x01u8]);
417-
assert_eq!(h1.finish128(), h2.finish128());
435+
h2.write(&test_u8.to_ne_bytes());
436+
h2.write(&test_u16.to_ne_bytes());
437+
h2.write(&test_u32.to_ne_bytes());
438+
h2.write(&test_u64.to_ne_bytes());
439+
h2.write(&test_u128.to_ne_bytes());
440+
h2.write(&test_usize.to_ne_bytes());
441+
h2.write(&test_i8.to_ne_bytes());
442+
h2.write(&test_i16.to_ne_bytes());
443+
h2.write(&test_i32.to_ne_bytes());
444+
h2.write(&test_i64.to_ne_bytes());
445+
h2.write(&test_i128.to_ne_bytes());
446+
h2.write(&test_isize.to_ne_bytes());
447+
448+
let h1_hash = h1.finish128();
449+
let h2_hash = h2.finish128();
450+
451+
assert_eq!(h1_hash, h2_hash);
418452
}

compiler/rustc_data_structures/src/stable_hasher.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use smallvec::SmallVec;
55
use std::hash::{BuildHasher, Hash, Hasher};
66
use std::mem;
77

8+
#[cfg(test)]
9+
mod tests;
10+
811
/// When hashing something that ends up affecting properties like symbol names,
912
/// we want these symbol names to be calculated independently of other factors
1013
/// like what architecture you're compiling *from*.
@@ -129,7 +132,8 @@ impl Hasher for StableHasher {
129132
fn write_isize(&mut self, i: isize) {
130133
// Always treat isize as i64 so we get the same results on 32 and 64 bit
131134
// platforms. This is important for symbol hashes when cross compiling,
132-
// for example.
135+
// for example. Sign extending here is preferable as it means that the
136+
// same negative number hashes the same on both 32 and 64 bit platforms.
133137
self.state.write_i64((i as i64).to_le());
134138
}
135139
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use super::*;
2+
3+
// The tests below compare the computed hashes to particular expected values
4+
// in order to test that we produce the same results on different platforms,
5+
// regardless of endianness and `usize` and `isize` size differences (this
6+
// of course assumes we run these tests on platforms that differ in those
7+
// ways). The expected values depend on the hashing algorithm used, so they
8+
// need to be updated whenever StableHasher changes its hashing algorithm.
9+
10+
#[test]
11+
fn test_hash_integers() {
12+
// Test that integers are handled consistently across platforms.
13+
let test_u8 = 0xAB_u8;
14+
let test_u16 = 0xFFEE_u16;
15+
let test_u32 = 0x445577AA_u32;
16+
let test_u64 = 0x01234567_13243546_u64;
17+
let test_u128 = 0x22114433_66557788_99AACCBB_EEDDFF77_u128;
18+
let test_usize = 0xD0C0B0A0_usize;
19+
20+
let test_i8 = -100_i8;
21+
let test_i16 = -200_i16;
22+
let test_i32 = -300_i32;
23+
let test_i64 = -400_i64;
24+
let test_i128 = -500_i128;
25+
let test_isize = -600_isize;
26+
27+
let mut h = StableHasher::new();
28+
test_u8.hash(&mut h);
29+
test_u16.hash(&mut h);
30+
test_u32.hash(&mut h);
31+
test_u64.hash(&mut h);
32+
test_u128.hash(&mut h);
33+
test_usize.hash(&mut h);
34+
test_i8.hash(&mut h);
35+
test_i16.hash(&mut h);
36+
test_i32.hash(&mut h);
37+
test_i64.hash(&mut h);
38+
test_i128.hash(&mut h);
39+
test_isize.hash(&mut h);
40+
41+
// This depends on the hashing algorithm. See note at top of file.
42+
let expected = (2736651863462566372, 8121090595289675650);
43+
44+
assert_eq!(h.finalize(), expected);
45+
}
46+
47+
#[test]
48+
fn test_hash_usize() {
49+
// Test that usize specifically is handled consistently across platforms.
50+
let test_usize = 0xABCDEF01_usize;
51+
52+
let mut h = StableHasher::new();
53+
test_usize.hash(&mut h);
54+
55+
// This depends on the hashing algorithm. See note at top of file.
56+
let expected = (5798740672699530587, 11186240177685111648);
57+
58+
assert_eq!(h.finalize(), expected);
59+
}
60+
61+
#[test]
62+
fn test_hash_isize() {
63+
// Test that isize specifically is handled consistently across platforms.
64+
let test_isize = -7_isize;
65+
66+
let mut h = StableHasher::new();
67+
test_isize.hash(&mut h);
68+
69+
// This depends on the hashing algorithm. See note at top of file.
70+
let expected = (14721296605626097289, 11385941877786388409);
71+
72+
assert_eq!(h.finalize(), expected);
73+
}

compiler/rustc_middle/src/ty/error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl<'tcx> ty::TyS<'tcx> {
232232
let n = tcx.lift(&n).unwrap();
233233
match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
234234
_ if t.is_simple_ty() => format!("array `{}`", self).into(),
235-
Some(n) => format!("array of {} element{} ", n, pluralize!(n)).into(),
235+
Some(n) => format!("array of {} element{}", n, pluralize!(n)).into(),
236236
None => "array".into(),
237237
}
238238
}

compiler/rustc_mir/src/const_eval/eval_queries.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1414
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
1515
use rustc_span::source_map::Span;
1616
use rustc_target::abi::{Abi, LayoutOf};
17-
use std::convert::TryInto;
17+
use std::convert::{TryFrom, TryInto};
1818

1919
pub fn note_on_undefined_behavior_error() -> &'static str {
2020
"The rules on what exactly is undefined behavior aren't clear, \
@@ -148,10 +148,10 @@ pub(super) fn op_to_const<'tcx>(
148148
Scalar::Raw { data, .. } => {
149149
assert!(mplace.layout.is_zst());
150150
assert_eq!(
151-
data,
152-
mplace.layout.align.abi.bytes().into(),
153-
"this MPlaceTy must come from `try_as_mplace` being used on a zst, so we know what
154-
value this integer address must have",
151+
u64::try_from(data).unwrap() % mplace.layout.align.abi.bytes(),
152+
0,
153+
"this MPlaceTy must come from a validated constant, thus we can assume the \
154+
alignment is correct",
155155
);
156156
ConstValue::Scalar(Scalar::zst())
157157
}

compiler/rustc_mir/src/transform/check_const_item_mutation.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,15 @@ impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> {
6060
// so emitting a lint would be redundant.
6161
if !lhs.projection.is_empty() {
6262
if let Some(def_id) = self.is_const_item(lhs.local) {
63-
self.lint_const_item_usage(def_id, loc, |lint| {
64-
let mut lint = lint.build("attempting to modify a `const` item");
65-
lint.note("each usage of a `const` item creates a new temporary - the original `const` item will not be modified");
66-
lint
67-
})
63+
// Don't lint on writes through a pointer
64+
// (e.g. `unsafe { *FOO = 0; *BAR.field = 1; }`)
65+
if !matches!(lhs.projection.last(), Some(PlaceElem::Deref)) {
66+
self.lint_const_item_usage(def_id, loc, |lint| {
67+
let mut lint = lint.build("attempting to modify a `const` item");
68+
lint.note("each usage of a `const` item creates a new temporary - the original `const` item will not be modified");
69+
lint
70+
})
71+
}
6872
}
6973
}
7074
// We are looking for MIR of the form:

compiler/rustc_mir/src/transform/promote_consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Vec<usize>> {
137137
LitKind::Int(a, _) => {
138138
ret.push(a as usize);
139139
}
140-
_ => return None,
140+
_ => bug!("invalid arg index"),
141141
}
142142
}
143143
Some(ret)

0 commit comments

Comments
 (0)