Skip to content

Commit 93b8bae

Browse files
committed
Auto merge of rust-lang#136470 - matthiaskrgr:rollup-iigrg27, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang#134777 (Enable more tests on Windows) - rust-lang#134807 (fix(rustdoc): always use a channel when linking to doc.rust-lang.org) - rust-lang#135621 (Move some std tests to integration tests) - rust-lang#135836 (bootstrap: only build `crt{begin,end}.o` when compiling to MUSL) - rust-lang#136235 (Pretty print pattern type values with transmute if they don't satisfy their pattern) - rust-lang#136392 (bootstrap: add wrapper macros for `feature = "tracing"`-gated `tracing` macros) - rust-lang#136462 (mir_build: Simplify `lower_pattern_range_endpoint`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 7daf4cf + 5ce6787 commit 93b8bae

File tree

128 files changed

+904
-840
lines changed

Some content is hidden

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

128 files changed

+904
-840
lines changed

compiler/rustc_const_eval/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ pub fn provide(providers: &mut Providers) {
5757
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
5858
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
5959
};
60+
providers.hooks.validate_scalar_in_layout =
61+
|tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout);
6062
}
6163

6264
/// `rustc_driver::main` installs a handler that will set this to `true` if

compiler/rustc_const_eval/src/util/check_validity_requirement.rs

+40-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants};
2-
use rustc_middle::bug;
2+
use rustc_middle::query::TyCtxtAt;
33
use rustc_middle::ty::layout::{
44
HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement,
55
};
6-
use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt};
6+
use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt};
7+
use rustc_middle::{bug, span_bug, ty};
78

89
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
910
use crate::interpret::{InterpCx, MemoryKind};
@@ -34,7 +35,7 @@ pub fn check_validity_requirement<'tcx>(
3435

3536
let layout_cx = LayoutCx::new(tcx, input.typing_env);
3637
if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
37-
check_validity_requirement_strict(layout, &layout_cx, kind)
38+
Ok(check_validity_requirement_strict(layout, &layout_cx, kind))
3839
} else {
3940
check_validity_requirement_lax(layout, &layout_cx, kind)
4041
}
@@ -46,7 +47,7 @@ fn check_validity_requirement_strict<'tcx>(
4647
ty: TyAndLayout<'tcx>,
4748
cx: &LayoutCx<'tcx>,
4849
kind: ValidityRequirement,
49-
) -> Result<bool, &'tcx LayoutError<'tcx>> {
50+
) -> bool {
5051
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
5152

5253
let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine);
@@ -69,14 +70,13 @@ fn check_validity_requirement_strict<'tcx>(
6970
// due to this.
7071
// The value we are validating is temporary and discarded at the end of this function, so
7172
// there is no point in reseting provenance and padding.
72-
Ok(cx
73-
.validate_operand(
74-
&allocated.into(),
75-
/*recursive*/ false,
76-
/*reset_provenance_and_padding*/ false,
77-
)
78-
.discard_err()
79-
.is_some())
73+
cx.validate_operand(
74+
&allocated.into(),
75+
/*recursive*/ false,
76+
/*reset_provenance_and_padding*/ false,
77+
)
78+
.discard_err()
79+
.is_some()
8080
}
8181

8282
/// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that
@@ -168,3 +168,31 @@ fn check_validity_requirement_lax<'tcx>(
168168

169169
Ok(true)
170170
}
171+
172+
pub(crate) fn validate_scalar_in_layout<'tcx>(
173+
tcx: TyCtxtAt<'tcx>,
174+
scalar: ScalarInt,
175+
ty: Ty<'tcx>,
176+
) -> bool {
177+
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
178+
179+
let typing_env = ty::TypingEnv::fully_monomorphized();
180+
let mut cx = InterpCx::new(tcx.tcx, tcx.span, typing_env, machine);
181+
182+
let Ok(layout) = cx.layout_of(ty) else {
183+
span_bug!(tcx.span, "could not compute layout of {scalar:?}:{ty:?}")
184+
};
185+
let allocated = cx
186+
.allocate(layout, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
187+
.expect("OOM: failed to allocate for uninit check");
188+
189+
cx.write_scalar(scalar, &allocated).unwrap();
190+
191+
cx.validate_operand(
192+
&allocated.into(),
193+
/*recursive*/ false,
194+
/*reset_provenance_and_padding*/ false,
195+
)
196+
.discard_err()
197+
.is_some()
198+
}

compiler/rustc_const_eval/src/util/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod type_name;
88

99
pub use self::alignment::{is_disaligned, is_within_packed};
1010
pub use self::check_validity_requirement::check_validity_requirement;
11+
pub(crate) use self::check_validity_requirement::validate_scalar_in_layout;
1112
pub use self::compare_types::{relate_types, sub_types};
1213
pub use self::type_name::type_name;
1314

compiler/rustc_middle/src/hooks/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ declare_hooks! {
112112
hook save_dep_graph() -> ();
113113

114114
hook query_key_hash_verify_all() -> ();
115+
116+
/// Ensure the given scalar is valid for the given type.
117+
/// This checks non-recursive runtime validity.
118+
hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool;
115119
}
116120

117121
#[cold]

compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
17411741
" as ",
17421742
)?;
17431743
}
1744-
ty::Pat(base_ty, pat) => {
1744+
ty::Pat(base_ty, pat) if self.tcx().validate_scalar_in_layout(int, ty) => {
17451745
self.pretty_print_const_scalar_int(int, *base_ty, print_ty)?;
17461746
p!(write(" is {pat:?}"));
17471747
}

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+42-39
Original file line numberDiff line numberDiff line change
@@ -155,42 +155,41 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
155155
fn lower_pattern_range_endpoint(
156156
&mut self,
157157
expr: Option<&'tcx hir::PatExpr<'tcx>>,
158-
) -> Result<
159-
(Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
160-
ErrorGuaranteed,
161-
> {
162-
match expr {
163-
None => Ok((None, None, None)),
164-
Some(expr) => {
165-
let (kind, ascr, inline_const) = match self.lower_lit(expr) {
166-
PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => {
167-
(subpattern.kind, None, def_id.as_local())
168-
}
169-
PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => {
170-
(subpattern.kind, None, None)
171-
}
172-
PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => {
173-
(kind, Some(ascription), None)
174-
}
175-
kind => (kind, None, None),
176-
};
177-
let value = match kind {
178-
PatKind::Constant { value } => value,
179-
PatKind::ExpandedConstant { subpattern, .. }
180-
if let PatKind::Constant { value } = subpattern.kind =>
181-
{
182-
value
183-
}
184-
_ => {
185-
let msg = format!(
186-
"found bad range pattern endpoint `{expr:?}` outside of error recovery"
187-
);
188-
return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
158+
// Out-parameters collecting extra data to be reapplied by the caller
159+
ascriptions: &mut Vec<Ascription<'tcx>>,
160+
inline_consts: &mut Vec<LocalDefId>,
161+
) -> Result<Option<PatRangeBoundary<'tcx>>, ErrorGuaranteed> {
162+
let Some(expr) = expr else { return Ok(None) };
163+
164+
// Lower the endpoint into a temporary `PatKind` that will then be
165+
// deconstructed to obtain the constant value and other data.
166+
let mut kind: PatKind<'tcx> = self.lower_lit(expr);
167+
168+
// Unpeel any ascription or inline-const wrapper nodes.
169+
loop {
170+
match kind {
171+
PatKind::AscribeUserType { ascription, subpattern } => {
172+
ascriptions.push(ascription);
173+
kind = subpattern.kind;
174+
}
175+
PatKind::ExpandedConstant { is_inline, def_id, subpattern } => {
176+
if is_inline {
177+
inline_consts.extend(def_id.as_local());
189178
}
190-
};
191-
Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const))
179+
kind = subpattern.kind;
180+
}
181+
_ => break,
192182
}
193183
}
184+
185+
// The unpeeled kind should now be a constant, giving us the endpoint value.
186+
let PatKind::Constant { value } = kind else {
187+
let msg =
188+
format!("found bad range pattern endpoint `{expr:?}` outside of error recovery");
189+
return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg));
190+
};
191+
192+
Ok(Some(PatRangeBoundary::Finite(value)))
194193
}
195194

196195
/// Overflowing literals are linted against in a late pass. This is mostly fine, except when we
@@ -253,11 +252,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
253252
self.tcx.dcx().span_bug(span, msg);
254253
}
255254

256-
let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?;
257-
let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?;
255+
// Collect extra data while lowering the endpoints, to be reapplied later.
256+
let mut ascriptions = vec![];
257+
let mut inline_consts = vec![];
258+
259+
let mut lower_endpoint =
260+
|expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts);
258261

259-
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
260-
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
262+
let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity);
263+
let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity);
261264

262265
let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
263266
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
@@ -298,13 +301,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
298301
// If we are handling a range with associated constants (e.g.
299302
// `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated
300303
// constants somewhere. Have them on the range pattern.
301-
for ascription in [lo_ascr, hi_ascr].into_iter().flatten() {
304+
for ascription in ascriptions {
302305
kind = PatKind::AscribeUserType {
303306
ascription,
304307
subpattern: Box::new(Pat { span, ty, kind }),
305308
};
306309
}
307-
for def in [lo_inline, hi_inline].into_iter().flatten() {
310+
for def in inline_consts {
308311
kind = PatKind::ExpandedConstant {
309312
def_id: def.to_def_id(),
310313
is_inline: true,

library/std/Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0"
77
repository = "https://github.com/rust-lang/rust.git"
88
description = "The Rust Standard Library"
99
edition = "2021"
10+
autobenches = false
1011

1112
[lib]
1213
crate-type = ["dylib", "rlib"]
@@ -130,6 +131,18 @@ name = "pipe-subprocess"
130131
path = "tests/pipe_subprocess.rs"
131132
harness = false
132133

134+
[[test]]
135+
name = "sync"
136+
path = "tests/sync/lib.rs"
137+
138+
[[test]]
139+
name = "floats"
140+
path = "tests/floats/lib.rs"
141+
142+
[[test]]
143+
name = "thread_local"
144+
path = "tests/thread_local/lib.rs"
145+
133146
[[bench]]
134147
name = "stdbenches"
135148
path = "benches/lib.rs"

library/std/benches/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
extern crate test;
66

77
mod hash;
8+
mod path;
9+
mod time;

library/std/benches/path.rs

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use core::hint::black_box;
2+
use std::collections::{BTreeSet, HashSet};
3+
use std::hash::{DefaultHasher, Hash, Hasher};
4+
use std::path::*;
5+
6+
#[bench]
7+
#[cfg_attr(miri, ignore)] // Miri isn't fast...
8+
fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
9+
let prefix = "my/home";
10+
let mut paths: Vec<_> =
11+
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
12+
13+
paths.sort();
14+
15+
b.iter(|| {
16+
black_box(paths.as_mut_slice()).sort_unstable();
17+
});
18+
}
19+
20+
#[bench]
21+
#[cfg_attr(miri, ignore)] // Miri isn't fast...
22+
fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
23+
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
24+
let paths: Vec<_> =
25+
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
26+
27+
let mut set = BTreeSet::new();
28+
29+
paths.iter().for_each(|p| {
30+
set.insert(p.as_path());
31+
});
32+
33+
b.iter(|| {
34+
set.remove(paths[500].as_path());
35+
set.insert(paths[500].as_path());
36+
});
37+
}
38+
39+
#[bench]
40+
#[cfg_attr(miri, ignore)] // Miri isn't fast...
41+
fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
42+
let prefix = "my/home";
43+
let paths: Vec<_> =
44+
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
45+
46+
let mut set = BTreeSet::new();
47+
48+
paths.iter().for_each(|p| {
49+
set.insert(p.as_path());
50+
});
51+
52+
b.iter(|| {
53+
set.remove(paths[500].as_path());
54+
set.insert(paths[500].as_path());
55+
});
56+
}
57+
58+
#[bench]
59+
#[cfg_attr(miri, ignore)] // Miri isn't fast...
60+
fn bench_path_hashset(b: &mut test::Bencher) {
61+
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
62+
let paths: Vec<_> =
63+
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
64+
65+
let mut set = HashSet::new();
66+
67+
paths.iter().for_each(|p| {
68+
set.insert(p.as_path());
69+
});
70+
71+
b.iter(|| {
72+
set.remove(paths[500].as_path());
73+
set.insert(black_box(paths[500].as_path()))
74+
});
75+
}
76+
77+
#[bench]
78+
#[cfg_attr(miri, ignore)] // Miri isn't fast...
79+
fn bench_path_hashset_miss(b: &mut test::Bencher) {
80+
let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
81+
let paths: Vec<_> =
82+
(0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect();
83+
84+
let mut set = HashSet::new();
85+
86+
paths.iter().for_each(|p| {
87+
set.insert(p.as_path());
88+
});
89+
90+
let probe = PathBuf::from(prefix).join("other");
91+
92+
b.iter(|| set.remove(black_box(probe.as_path())));
93+
}
94+
95+
#[bench]
96+
fn bench_hash_path_short(b: &mut test::Bencher) {
97+
let mut hasher = DefaultHasher::new();
98+
let path = Path::new("explorer.exe");
99+
100+
b.iter(|| black_box(path).hash(&mut hasher));
101+
102+
black_box(hasher.finish());
103+
}
104+
105+
#[bench]
106+
fn bench_hash_path_long(b: &mut test::Bencher) {
107+
let mut hasher = DefaultHasher::new();
108+
let path =
109+
Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff");
110+
111+
b.iter(|| black_box(path).hash(&mut hasher));
112+
113+
black_box(hasher.finish());
114+
}

0 commit comments

Comments
 (0)