diff options
| author | bors <bors@rust-lang.org> | 2024-01-26 06:59:26 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-01-26 06:59:26 +0000 |
| commit | fae15df5c60ccf0f9eaa96651c869d2c2001fddb (patch) | |
| tree | b452546913281a644984fff0862defd7ec76890e /src | |
| parent | 9f4d1a41a6dccf00caace1e9fd20011d586d8b69 (diff) | |
| parent | 2318b0825cc2892a388b307d38389658f09ac3b6 (diff) | |
| download | rust-fae15df5c60ccf0f9eaa96651c869d2c2001fddb.tar.gz rust-fae15df5c60ccf0f9eaa96651c869d2c2001fddb.zip | |
Auto merge of #3280 - rust-lang:rustup-2024-01-26, r=RalfJung
Automatic Rustup
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/src/core/build_steps/compile.rs | 7 | ||||
| -rw-r--r-- | src/bootstrap/src/lib.rs | 2 | ||||
| -rw-r--r-- | src/doc/rustc/src/SUMMARY.md | 1 | ||||
| -rw-r--r-- | src/doc/rustc/src/platform-support.md | 1 | ||||
| -rw-r--r-- | src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md | 30 | ||||
| -rw-r--r-- | src/doc/style-guide/src/editions.md | 4 | ||||
| -rw-r--r-- | src/doc/style-guide/src/expressions.md | 55 | ||||
| -rw-r--r-- | src/librustdoc/html/templates/item_union.html | 14 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/crashes/ice-6254.rs | 2 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/crashes/ice-6254.stderr | 15 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/modulo_one.rs | 3 | ||||
| -rw-r--r-- | src/tools/clippy/tests/ui/modulo_one.stderr | 8 | ||||
| -rw-r--r-- | src/tools/compiletest/src/header.rs | 3 | ||||
| -rw-r--r-- | src/tools/compiletest/src/header/tests.rs | 21 | ||||
| -rw-r--r-- | src/tools/miri/rust-version | 2 | ||||
| -rw-r--r-- | src/tools/miri/src/machine.rs | 54 | ||||
| -rw-r--r-- | src/tools/miri/src/shims/intrinsics/mod.rs | 13 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/const-addrs.rs | 38 | ||||
| -rw-r--r-- | src/tools/miri/tests/pass/intrinsics.rs | 15 |
19 files changed, 230 insertions, 58 deletions
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index f954f01fe4e..e06bc3fb09a 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -367,10 +367,13 @@ fn copy_self_contained_objects( let srcdir = builder .wasi_root(target) .unwrap_or_else(|| { - panic!("Target {:?} does not have a \"wasi-root\" key", target.triple) + panic!( + "Target {:?} does not have a \"wasi-root\" key in Config.toml", + target.triple + ) }) .join("lib") - .join(target.to_string().replace("-preview1", "")); + .join(target.to_string().replace("-preview1", "").replace("-preview2", "")); for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] { copy_and_stamp( builder, diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 1336abf6c7a..1726e7aacbc 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -88,7 +88,7 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[ (Some(Mode::Std), "no_sync", None), (Some(Mode::Std), "backtrace_in_libstd", None), /* Extra values not defined in the built-in targets yet, but used in std */ - (Some(Mode::Std), "target_env", Some(&["libnx"])), + (Some(Mode::Std), "target_env", Some(&["libnx", "preview2"])), // (Some(Mode::Std), "target_os", Some(&[])), // #[cfg(bootstrap)] zkvm (Some(Mode::Std), "target_os", Some(&["zkvm"])), diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1998b008dc8..990998ea704 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -59,6 +59,7 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) + - [wasm32-wasi-preview2](platform-support/wasm32-wasi-preview2.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f648a60b6c4..fb751b7229e 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -360,6 +360,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7-A Linux with NEON, MUSL +[`wasm32-wasi-preview2`](platform-support/wasm32-wasi-preview2.md) | ✓ | | WebAssembly [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md new file mode 100644 index 00000000000..837efd13d41 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview2.md @@ -0,0 +1,30 @@ +# `wasm32-wasi-preview2` + +**Tier: 3** + +The `wasm32-wasi-preview2` target is a new and still (as of January 2024) an +experimental target. This target is an extension to `wasm32-wasi-preview1` target, +originally known as `wasm32-wasi`. It is the next evolution in the development of +wasi (the [WebAssembly System Interface](https://wasi.dev)) that uses the WebAssembly +[component model] to allow for a standardized set of syscalls that are intended to empower +WebAssembly binaries with native host capabilities. + +[component model]: https://github.com/WebAssembly/component-model + +## Target maintainers + +- Alex Crichton, https://github.com/alexcrichton +- Ryan Levick, https://github.com/rylev + +## Requirements + +This target is cross-compiled. The target supports `std` fully. + +## Platform requirements + +The WebAssembly runtime should support the wasi preview 2 API set. + +This target is not a stable target. This means that there are only a few engines +which implement wasi preview 2, for example: + +* Wasmtime - `-W component-model` diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 19e62c4867c..b9a89c20cee 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -36,6 +36,10 @@ For a full history of changes in the Rust 2024 style edition, see the git history of the style guide. Notable changes in the Rust 2024 style edition include: +- [#114764](https://github.com/rust-lang/rust/pull/114764) As the last member + of a delimited expression, delimited expressions are generally combinable, + regardless of the number of members. Previously only applied with exactly + one member (except for closures with explicit blocks). - Miscellaneous `rustfmt` bugfixes. - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order). - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase". diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 12037b5992e..171a24cd89d 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -818,11 +818,11 @@ E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. ## Combinable expressions -Where a function call has a single argument, and that argument is formatted -across multiple-lines, format the outer call as if it were a single-line call, +When the last argument in a function call is formatted across +multiple-lines, format the outer call as if it were a single-line call, if the result fits. Apply the same combining behaviour to any similar expressions which have multi-line, block-indented lists of sub-expressions -delimited by parentheses (e.g., macros or tuple struct literals). E.g., +delimited by parentheses, brackets, or braces. E.g., ```rust foo(bar( @@ -848,20 +848,61 @@ let arr = [combinable( an_expr, another_expr, )]; + +let x = Thing(an_expr, another_expr, match cond { + A => 1, + B => 2, +}); + +let x = format!("Stuff: {}", [ + an_expr, + another_expr, +]); + +let x = func(an_expr, another_expr, SomeStruct { + field: this_is_long, + another_field: 123, +}); ``` Apply this behavior recursively. -For a function with multiple arguments, if the last argument is a multi-line -closure with an explicit block, there are no other closure arguments, and all -the arguments and the first line of the closure fit on the first line, use the -same combining behavior: +If the last argument is a multi-line closure with an explicit block, +only apply the combining behavior if there are no other closure arguments. ```rust +// Combinable foo(first_arg, x, |param| { action(); foo(param) }) +// Not combinable, because the closure is not the last argument +foo( + first_arg, + |param| { + action(); + foo(param) + }, + whatever, +) +// Not combinable, because the first line of the closure does not fit +foo( + first_arg, + x, + move |very_long_param_causing_line_to_overflow| -> Bar { + action(); + foo(param) + }, +) +// Not combinable, because there is more than one closure argument +foo( + first_arg, + |x| x.bar(), + |param| { + action(); + foo(param) + }, +) ``` ## Ranges diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html index 8db7986fa75..b1c1d5a63a0 100644 --- a/src/librustdoc/html/templates/item_union.html +++ b/src/librustdoc/html/templates/item_union.html @@ -1,8 +1,8 @@ <pre class="rust item-decl"><code> - {{ self.render_attributes_in_pre() | safe }} - {{ self.render_union() | safe }} + {{ self.render_attributes_in_pre()|safe }} + {{ self.render_union()|safe }} </code></pre> -{{ self.document() | safe }} +{{ self.document()|safe }} {% if self.fields_iter().peek().is_some() %} <h2 id="fields" class="fields section-header"> {# #} Fields<a href="#fields" class="anchor">§</a> {# #} @@ -12,13 +12,13 @@ <span id="structfield.{{ name }}" {#+ #} class="{{ ItemType::StructField +}} section-header"> {# #} <a href="#structfield.{{ name }}" class="anchor field">§</a> {# #} - <code>{{ name }}: {{+ self.print_ty(ty) | safe }}</code> {# #} + <code>{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #} </span> {% if let Some(stability_class) = self.stability_field(field) %} <span class="stab {{ stability_class }}"></span> {% endif %} - {{ self.document_field(field) | safe }} + {{ self.document_field(field)|safe }} {% endfor %} {% endif %} -{{ self.render_assoc_items() | safe }} -{{ self.document_type_layout() | safe }} +{{ self.render_assoc_items()|safe }} +{{ self.document_type_layout()|safe }} diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.rs b/src/tools/clippy/tests/ui/crashes/ice-6254.rs index 2ae426cf789..8af60890390 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6254.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-6254.rs @@ -11,8 +11,6 @@ fn main() { // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071) match FOO_REF_REF { FOO_REF_REF => {}, - //~^ ERROR: to use a constant of type `Foo` in a pattern, `Foo` must be annotated - //~| NOTE: for more information, see issue #62411 <https://github.com/rust-lang/ru Foo(_) => {}, } } diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr b/src/tools/clippy/tests/ui/crashes/ice-6254.stderr deleted file mode 100644 index 7a34e6cceee..00000000000 --- a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/ice-6254.rs:13:9 - | -LL | FOO_REF_REF => {}, - | ^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - = note: `-D indirect-structural-match` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(indirect_structural_match)]` - -error: aborting due to 1 previous error - diff --git a/src/tools/clippy/tests/ui/modulo_one.rs b/src/tools/clippy/tests/ui/modulo_one.rs index c1dbe9d9a87..c332a15f157 100644 --- a/src/tools/clippy/tests/ui/modulo_one.rs +++ b/src/tools/clippy/tests/ui/modulo_one.rs @@ -33,7 +33,6 @@ fn main() { INT_MIN % NEG_ONE; //~^ ERROR: this operation will panic at runtime //~| ERROR: any number modulo -1 will panic/overflow or result in 0 - // ONLY caught by rustc + // Not caught by lint, we don't look into static items, even if entirely immutable. INT_MIN % STATIC_NEG_ONE; - //~^ ERROR: this operation will panic at runtime } diff --git a/src/tools/clippy/tests/ui/modulo_one.stderr b/src/tools/clippy/tests/ui/modulo_one.stderr index cc211ab6cd3..06bbb0f5d9a 100644 --- a/src/tools/clippy/tests/ui/modulo_one.stderr +++ b/src/tools/clippy/tests/ui/modulo_one.stderr @@ -12,12 +12,6 @@ error: this operation will panic at runtime LL | INT_MIN % NEG_ONE; | ^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow -error: this operation will panic at runtime - --> $DIR/modulo_one.rs:37:5 - | -LL | INT_MIN % STATIC_NEG_ONE; - | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow - error: any number modulo 1 will be 0 --> $DIR/modulo_one.rs:8:5 | @@ -57,5 +51,5 @@ error: any number modulo -1 will panic/overflow or result in 0 LL | INT_MIN % NEG_ONE; | ^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index e70e01e8757..ff907152ca9 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1109,9 +1109,6 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { } fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision { - if config.system_llvm && line.starts_with("no-system-llvm") { - return IgnoreDecision::Ignore { reason: "ignored when the system LLVM is used".into() }; - } if let Some(needed_components) = config.parse_name_value_directive(line, "needs-llvm-components") { diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 8882f1582ac..c859e8acade 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -243,15 +243,6 @@ fn aux_build() { } #[test] -fn no_system_llvm() { - let config: Config = cfg().system_llvm(false).build(); - assert!(!check_ignore(&config, "// no-system-llvm")); - - let config: Config = cfg().system_llvm(true).build(); - assert!(check_ignore(&config, "// no-system-llvm")); -} - -#[test] fn llvm_version() { let config: Config = cfg().llvm_version("8.1.2").build(); assert!(check_ignore(&config, "// min-llvm-version: 9.0")); @@ -267,6 +258,18 @@ fn llvm_version() { } #[test] +fn system_llvm_version() { + let config: Config = cfg().system_llvm(true).llvm_version("17.0.0").build(); + assert!(check_ignore(&config, "// min-system-llvm-version: 18.0")); + + let config: Config = cfg().system_llvm(true).llvm_version("18.0.0").build(); + assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0")); + + let config: Config = cfg().llvm_version("17.0.0").build(); + assert!(!check_ignore(&config, "// min-system-llvm-version: 18.0")); +} + +#[test] fn ignore_target() { let config: Config = cfg().target("x86_64-unknown-linux-gnu").build(); diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 62bef6d52d9..6624672775f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f6ee4bf3847277d6d6e2007ff664f8ea0895b11b +dd2559e08e1530806740931037d6bb83ef956161 diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 567ac6cff67..946887637ff 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -3,12 +3,14 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell}; +use std::collections::hash_map::Entry; use std::fmt; use std::path::Path; use std::process; use either::Either; use rand::rngs::StdRng; +use rand::Rng; use rand::SeedableRng; use rustc_ast::ast::Mutability; @@ -45,6 +47,11 @@ pub const SIGRTMIN: i32 = 34; /// `SIGRTMAX` - `SIGRTMIN` >= 8 (which is the value of `_POSIX_RTSIG_MAX`) pub const SIGRTMAX: i32 = 42; +/// Each const has multiple addresses, but only this many. Since const allocations are never +/// deallocated, choosing a new [`AllocId`] and thus base address for each evaluation would +/// produce unbounded memory usage. +const ADDRS_PER_CONST: usize = 16; + /// Extra data stored with each stack frame pub struct FrameExtra<'tcx> { /// Extra data for the Borrow Tracker. @@ -65,12 +72,19 @@ pub struct FrameExtra<'tcx> { /// optimization. /// This is used by `MiriMachine::current_span` and `MiriMachine::caller_span` pub is_user_relevant: bool, + + /// We have a cache for the mapping from [`mir::Const`] to resulting [`AllocId`]. + /// However, we don't want all frames to always get the same result, so we insert + /// an additional bit of "salt" into the cache key. This salt is fixed per-frame + /// so that within a call, a const will have a stable address. + salt: usize, } impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Omitting `timing`, it does not support `Debug`. - let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _ } = self; + let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = + self; f.debug_struct("FrameData") .field("borrow_tracker", borrow_tracker) .field("catch_unwind", catch_unwind) @@ -80,7 +94,8 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> { impl VisitProvenance for FrameExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _ } = self; + let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = + self; catch_unwind.visit_provenance(visit); borrow_tracker.visit_provenance(visit); @@ -552,6 +567,11 @@ pub struct MiriMachine<'mir, 'tcx> { /// The spans we will use to report where an allocation was created and deallocated in /// diagnostics. pub(crate) allocation_spans: RefCell<FxHashMap<AllocId, (Span, Option<Span>)>>, + + /// Maps MIR consts to their evaluated result. We combine the const with a "salt" (`usize`) + /// that is fixed per stack frame; this lets us have sometimes different results for the + /// same const while ensuring consistent results within a single call. + const_cache: RefCell<FxHashMap<(mir::Const<'tcx>, usize), OpTy<'tcx, Provenance>>>, } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -677,6 +697,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { stack_size, collect_leak_backtraces: config.collect_leak_backtraces, allocation_spans: RefCell::new(FxHashMap::default()), + const_cache: RefCell::new(FxHashMap::default()), } } @@ -788,6 +809,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { stack_size: _, collect_leak_backtraces: _, allocation_spans: _, + const_cache: _, } = self; threads.visit_provenance(visit); @@ -1345,6 +1367,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { catch_unwind: None, timing, is_user_relevant: ecx.machine.is_user_relevant(&frame), + salt: ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_CONST, }; Ok(frame.with_extra(extra)) @@ -1450,4 +1473,31 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.machine.allocation_spans.borrow_mut().insert(alloc_id, (span, None)); Ok(()) } + + fn eval_mir_constant<F>( + ecx: &InterpCx<'mir, 'tcx, Self>, + val: mir::Const<'tcx>, + span: Option<Span>, + layout: Option<TyAndLayout<'tcx>>, + eval: F, + ) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>> + where + F: Fn( + &InterpCx<'mir, 'tcx, Self>, + mir::Const<'tcx>, + Option<Span>, + Option<TyAndLayout<'tcx>>, + ) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>, + { + let frame = ecx.active_thread_stack().last().unwrap(); + let mut cache = ecx.machine.const_cache.borrow_mut(); + match cache.entry((val, frame.extra.salt)) { + Entry::Vacant(ve) => { + let op = eval(ecx, val, span, layout)?; + ve.insert(op.clone()); + Ok(op) + } + Entry::Occupied(oe) => Ok(oe.get().clone()), + } + } } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index a1db7bf74f2..e34fb118f72 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -5,6 +5,7 @@ use std::iter; use log::trace; +use rand::Rng; use rustc_apfloat::{Float, Round}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::{ @@ -141,6 +142,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_pointer(Pointer::new(ptr.provenance, masked_addr), dest)?; } + // We want to return either `true` or `false` at random, or else something like + // ``` + // if !is_val_statically_known(0) { unreachable_unchecked(); } + // ``` + // Would not be considered UB, or the other way around (`is_val_statically_known(0)`). + "is_val_statically_known" => { + let [arg] = check_arg_count(args)?; + this.validate_operand(arg)?; + let branch: bool = this.machine.rng.get_mut().gen(); + this.write_scalar(Scalar::from_bool(branch), dest)?; + } + // Floating-point operations "fabsf32" => { let [f] = check_arg_count(args)?; diff --git a/src/tools/miri/tests/pass/const-addrs.rs b/src/tools/miri/tests/pass/const-addrs.rs new file mode 100644 index 00000000000..6c14f0b679c --- /dev/null +++ b/src/tools/miri/tests/pass/const-addrs.rs @@ -0,0 +1,38 @@ +// The const fn interpreter creates a new AllocId every time it evaluates any const. +// If we do that in Miri, repeatedly evaluating a const causes unbounded memory use +// we need to keep track of the base address for that AllocId, and the allocation is never +// deallocated. +// In Miri we explicitly store previously-assigned AllocIds for each const and ensure +// that we only hand out a finite number of AllocIds per const. +// MIR inlining will put every evaluation of the const we're repeatedly evaluting into the same +// stack frame, breaking this test. +//@compile-flags: -Zinline-mir=no +#![feature(strict_provenance)] + +const EVALS: usize = 256; + +use std::collections::HashSet; +fn main() { + let mut addrs = HashSet::new(); + for _ in 0..EVALS { + addrs.insert(const_addr()); + } + // Check that the const allocation has multiple base addresses + assert!(addrs.len() > 1); + // But also that we get a limited number of unique base addresses + assert!(addrs.len() < EVALS); + + // Check that within a call we always produce the same address + let mut prev = 0; + for iter in 0..EVALS { + let addr = "test".as_bytes().as_ptr().addr(); + if iter > 0 { + assert_eq!(prev, addr); + } + prev = addr; + } +} + +fn const_addr() -> usize { + "test".as_bytes().as_ptr().addr() +} diff --git a/src/tools/miri/tests/pass/intrinsics.rs b/src/tools/miri/tests/pass/intrinsics.rs index 8c6eeab2219..8e46bd7ad48 100644 --- a/src/tools/miri/tests/pass/intrinsics.rs +++ b/src/tools/miri/tests/pass/intrinsics.rs @@ -33,6 +33,21 @@ fn main() { assert_eq!(intrinsics::likely(false), false); assert_eq!(intrinsics::unlikely(true), true); + let mut saw_true = false; + let mut saw_false = false; + + for _ in 0..50 { + if unsafe { intrinsics::is_val_statically_known(0) } { + saw_true = true; + } else { + saw_false = true; + } + } + assert!( + saw_true && saw_false, + "`is_val_statically_known` failed to return both true and false. Congrats, you won the lottery!" + ); + intrinsics::forget(Bomb); let _v = intrinsics::discriminant_value(&Some(())); |
