diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 79aac16355061..24b626ad96658 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -11,6 +11,8 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { for (i, stmt) in data.statements.iter_mut().enumerate() { match stmt.kind { StatementKind::Assign(box (og_place, Rvalue::Ref(region, borrow_knd, place))) => { + let mut place_local = place.local; + let mut last_len = 0; for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() { if p_elem == ProjectionElem::Deref && !p_ref.projection.is_empty() { // The type that we are derefing. @@ -23,15 +25,18 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { patch.add_statement(loc, StatementKind::StorageLive(temp)); // We are adding current p_ref's projections to our - // temp value. - let deref_place = - Place::from(p_ref.local).project_deeper(p_ref.projection, tcx); + // temp value, excluding projections we already covered. + let deref_place = Place::from(place_local) + .project_deeper(&p_ref.projection[last_len..], tcx); patch.add_assign( loc, Place::from(temp), Rvalue::Use(Operand::Move(deref_place)), ); + place_local = temp; + last_len = p_ref.projection.len(); + // We are creating a place by using our temp value's location // and copying derefed values which we need to create new statement. let temp_place = @@ -50,11 +55,6 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Since our job with the temp is done it should be gone let loc = Location { block: block, statement_index: i + 1 }; patch.add_statement(loc, StatementKind::StorageDead(temp)); - - // As all projections are off the base projection, if there are - // multiple derefs in the middle of projection, it might cause - // unsoundness, to not let that happen we break the loop. - break; } } } diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 6091b8fee00b6..e73b9c979eb1a 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -1012,7 +1012,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.help(msg); } err.help( - "if you can't comply with strict provenance and need to expose the pointer\ + "if you can't comply with strict provenance and need to expose the pointer \ provenance you can use `.expose_addr()` instead" ); diff --git a/library/std/src/sync/mpsc/blocking.rs b/library/std/src/sync/mpsc/blocking.rs index 4c852b8ee812f..021df7b096cbc 100644 --- a/library/std/src/sync/mpsc/blocking.rs +++ b/library/std/src/sync/mpsc/blocking.rs @@ -1,6 +1,5 @@ //! Generic support for building blocking abstractions. -use crate::mem; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sync::Arc; use crate::thread::{self, Thread}; @@ -47,18 +46,18 @@ impl SignalToken { wake } - /// Converts to an unsafe usize value. Useful for storing in a pipe's state + /// Converts to an unsafe raw pointer. Useful for storing in a pipe's state /// flag. #[inline] - pub unsafe fn cast_to_usize(self) -> usize { - mem::transmute(self.inner) + pub unsafe fn to_raw(self) -> *mut u8 { + Arc::into_raw(self.inner) as *mut u8 } - /// Converts from an unsafe usize value. Useful for retrieving a pipe's state + /// Converts from an unsafe raw pointer. Useful for retrieving a pipe's state /// flag. #[inline] - pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken { - SignalToken { inner: mem::transmute(signal_ptr) } + pub unsafe fn from_raw(signal_ptr: *mut u8) -> SignalToken { + SignalToken { inner: Arc::from_raw(signal_ptr as *mut Inner) } } } diff --git a/library/std/src/sync/mpsc/oneshot.rs b/library/std/src/sync/mpsc/oneshot.rs index 3dcf03f579a0f..0e259b8aecb9a 100644 --- a/library/std/src/sync/mpsc/oneshot.rs +++ b/library/std/src/sync/mpsc/oneshot.rs @@ -27,15 +27,15 @@ pub use self::UpgradeResult::*; use crate::cell::UnsafeCell; use crate::ptr; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicPtr, Ordering}; use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::Receiver; use crate::time::Instant; // Various states you can find a port in. -const EMPTY: usize = 0; // initial state: no data, no blocked receiver -const DATA: usize = 1; // data ready for receiver to take -const DISCONNECTED: usize = 2; // channel is disconnected OR upgraded +const EMPTY: *mut u8 = ptr::invalid_mut::(0); // initial state: no data, no blocked receiver +const DATA: *mut u8 = ptr::invalid_mut::(1); // data ready for receiver to take +const DISCONNECTED: *mut u8 = ptr::invalid_mut::(2); // channel is disconnected OR upgraded // Any other value represents a pointer to a SignalToken value. The // protocol ensures that when the state moves *to* a pointer, // ownership of the token is given to the packet, and when the state @@ -44,7 +44,7 @@ const DISCONNECTED: usize = 2; // channel is disconnected OR upgraded pub struct Packet { // Internal state of the chan/port pair (stores the blocked thread as well) - state: AtomicUsize, + state: AtomicPtr, // One-shot data slot location data: UnsafeCell>, // when used for the second time, a oneshot channel must be upgraded, and @@ -75,7 +75,7 @@ impl Packet { Packet { data: UnsafeCell::new(None), upgrade: UnsafeCell::new(NothingSent), - state: AtomicUsize::new(EMPTY), + state: AtomicPtr::new(EMPTY), } } @@ -108,7 +108,7 @@ impl Packet { // There is a thread waiting on the other end. We leave the 'DATA' // state inside so it'll pick it up on the other end. ptr => { - SignalToken::cast_from_usize(ptr).signal(); + SignalToken::from_raw(ptr).signal(); Ok(()) } } @@ -126,7 +126,7 @@ impl Packet { // like we're not empty, then immediately go through to `try_recv`. if self.state.load(Ordering::SeqCst) == EMPTY { let (wait_token, signal_token) = blocking::tokens(); - let ptr = unsafe { signal_token.cast_to_usize() }; + let ptr = unsafe { signal_token.to_raw() }; // race with senders to enter the blocking state if self.state.compare_exchange(EMPTY, ptr, Ordering::SeqCst, Ordering::SeqCst).is_ok() { @@ -142,7 +142,7 @@ impl Packet { } } else { // drop the signal token, since we never blocked - drop(unsafe { SignalToken::cast_from_usize(ptr) }); + drop(unsafe { SignalToken::from_raw(ptr) }); } } @@ -218,7 +218,7 @@ impl Packet { } // If someone's waiting, we gotta wake them up - ptr => UpWoke(SignalToken::cast_from_usize(ptr)), + ptr => UpWoke(SignalToken::from_raw(ptr)), } } } @@ -229,7 +229,7 @@ impl Packet { // If someone's waiting, we gotta wake them up ptr => unsafe { - SignalToken::cast_from_usize(ptr).signal(); + SignalToken::from_raw(ptr).signal(); }, } } @@ -301,7 +301,7 @@ impl Packet { // We woke ourselves up from select. ptr => unsafe { - drop(SignalToken::cast_from_usize(ptr)); + drop(SignalToken::from_raw(ptr)); Ok(false) }, } diff --git a/library/std/src/sync/mpsc/shared.rs b/library/std/src/sync/mpsc/shared.rs index 5616265554410..51917bd96bd60 100644 --- a/library/std/src/sync/mpsc/shared.rs +++ b/library/std/src/sync/mpsc/shared.rs @@ -15,7 +15,7 @@ use core::intrinsics::abort; use crate::cell::UnsafeCell; use crate::ptr; -use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize, Ordering}; use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::mpsc_queue as mpsc; use crate::sync::{Mutex, MutexGuard}; @@ -29,12 +29,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; const MAX_STEALS: isize = 5; #[cfg(not(test))] const MAX_STEALS: isize = 1 << 20; +const EMPTY: *mut u8 = ptr::null_mut(); // initial state: no data, no blocked receiver pub struct Packet { queue: mpsc::Queue, cnt: AtomicIsize, // How many items are on this channel steals: UnsafeCell, // How many times has a port received without blocking? - to_wake: AtomicUsize, // SignalToken for wake up + to_wake: AtomicPtr, // SignalToken for wake up // The number of channels which are currently using this packet. channels: AtomicUsize, @@ -68,7 +69,7 @@ impl Packet { queue: mpsc::Queue::new(), cnt: AtomicIsize::new(0), steals: UnsafeCell::new(0), - to_wake: AtomicUsize::new(0), + to_wake: AtomicPtr::new(EMPTY), channels: AtomicUsize::new(2), port_dropped: AtomicBool::new(false), sender_drain: AtomicIsize::new(0), @@ -93,8 +94,8 @@ impl Packet { pub fn inherit_blocker(&self, token: Option, guard: MutexGuard<'_, ()>) { if let Some(token) = token { assert_eq!(self.cnt.load(Ordering::SeqCst), 0); - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); - self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst); + assert_eq!(self.to_wake.load(Ordering::SeqCst), EMPTY); + self.to_wake.store(unsafe { token.to_raw() }, Ordering::SeqCst); self.cnt.store(-1, Ordering::SeqCst); // This store is a little sketchy. What's happening here is that @@ -250,10 +251,10 @@ impl Packet { unsafe { assert_eq!( self.to_wake.load(Ordering::SeqCst), - 0, + EMPTY, "This is a known bug in the Rust standard library. See https://github.com/rust-lang/rust/issues/39364" ); - let ptr = token.cast_to_usize(); + let ptr = token.to_raw(); self.to_wake.store(ptr, Ordering::SeqCst); let steals = ptr::replace(self.steals.get(), 0); @@ -272,8 +273,8 @@ impl Packet { } } - self.to_wake.store(0, Ordering::SeqCst); - drop(SignalToken::cast_from_usize(ptr)); + self.to_wake.store(EMPTY, Ordering::SeqCst); + drop(SignalToken::from_raw(ptr)); Abort } } @@ -415,9 +416,9 @@ impl Packet { // Consumes ownership of the 'to_wake' field. fn take_to_wake(&self) -> SignalToken { let ptr = self.to_wake.load(Ordering::SeqCst); - self.to_wake.store(0, Ordering::SeqCst); - assert!(ptr != 0); - unsafe { SignalToken::cast_from_usize(ptr) } + self.to_wake.store(EMPTY, Ordering::SeqCst); + assert!(ptr != EMPTY); + unsafe { SignalToken::from_raw(ptr) } } //////////////////////////////////////////////////////////////////////////// @@ -462,7 +463,7 @@ impl Packet { let prev = self.bump(steals + 1); if prev == DISCONNECTED { - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.to_wake.load(Ordering::SeqCst), EMPTY); true } else { let cur = prev + steals + 1; @@ -470,7 +471,7 @@ impl Packet { if prev < 0 { drop(self.take_to_wake()); } else { - while self.to_wake.load(Ordering::SeqCst) != 0 { + while self.to_wake.load(Ordering::SeqCst) != EMPTY { thread::yield_now(); } } @@ -494,7 +495,7 @@ impl Drop for Packet { // `to_wake`, so this assert cannot be removed with also removing // the `to_wake` assert. assert_eq!(self.cnt.load(Ordering::SeqCst), DISCONNECTED); - assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.to_wake.load(Ordering::SeqCst), EMPTY); assert_eq!(self.channels.load(Ordering::SeqCst), 0); } } diff --git a/library/std/src/sync/mpsc/stream.rs b/library/std/src/sync/mpsc/stream.rs index 2a1d3f8967e99..4c3812c79f619 100644 --- a/library/std/src/sync/mpsc/stream.rs +++ b/library/std/src/sync/mpsc/stream.rs @@ -17,7 +17,7 @@ use crate::ptr; use crate::thread; use crate::time::Instant; -use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicBool, AtomicIsize, AtomicPtr, Ordering}; use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::spsc_queue as spsc; use crate::sync::mpsc::Receiver; @@ -27,6 +27,7 @@ const DISCONNECTED: isize = isize::MIN; const MAX_STEALS: isize = 5; #[cfg(not(test))] const MAX_STEALS: isize = 1 << 20; +const EMPTY: *mut u8 = ptr::null_mut(); // initial state: no data, no blocked receiver pub struct Packet { // internal queue for all messages @@ -34,8 +35,8 @@ pub struct Packet { } struct ProducerAddition { - cnt: AtomicIsize, // How many items are on this channel - to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up + cnt: AtomicIsize, // How many items are on this channel + to_wake: AtomicPtr, // SignalToken for the blocked thread to wake up port_dropped: AtomicBool, // flag if the channel has been destroyed. } @@ -71,7 +72,7 @@ impl Packet { 128, ProducerAddition { cnt: AtomicIsize::new(0), - to_wake: AtomicUsize::new(0), + to_wake: AtomicPtr::new(EMPTY), port_dropped: AtomicBool::new(false), }, @@ -147,17 +148,17 @@ impl Packet { // Consumes ownership of the 'to_wake' field. fn take_to_wake(&self) -> SignalToken { let ptr = self.queue.producer_addition().to_wake.load(Ordering::SeqCst); - self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst); - assert!(ptr != 0); - unsafe { SignalToken::cast_from_usize(ptr) } + self.queue.producer_addition().to_wake.store(EMPTY, Ordering::SeqCst); + assert!(ptr != EMPTY); + unsafe { SignalToken::from_raw(ptr) } } // Decrements the count on the channel for a sleeper, returning the sleeper // back if it shouldn't sleep. Note that this is the location where we take // steals into account. fn decrement(&self, token: SignalToken) -> Result<(), SignalToken> { - assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); - let ptr = unsafe { token.cast_to_usize() }; + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), EMPTY); + let ptr = unsafe { token.to_raw() }; self.queue.producer_addition().to_wake.store(ptr, Ordering::SeqCst); let steals = unsafe { ptr::replace(self.queue.consumer_addition().steals.get(), 0) }; @@ -176,8 +177,8 @@ impl Packet { } } - self.queue.producer_addition().to_wake.store(0, Ordering::SeqCst); - Err(unsafe { SignalToken::cast_from_usize(ptr) }) + self.queue.producer_addition().to_wake.store(EMPTY, Ordering::SeqCst); + Err(unsafe { SignalToken::from_raw(ptr) }) } pub fn recv(&self, deadline: Option) -> Result> { @@ -376,7 +377,7 @@ impl Packet { // of time until the data is actually sent. if was_upgrade { assert_eq!(unsafe { *self.queue.consumer_addition().steals.get() }, 0); - assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), EMPTY); return Ok(true); } @@ -389,7 +390,7 @@ impl Packet { // If we were previously disconnected, then we know for sure that there // is no thread in to_wake, so just keep going let has_data = if prev == DISCONNECTED { - assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), EMPTY); true // there is data, that data is that we're disconnected } else { let cur = prev + steals + 1; @@ -412,7 +413,7 @@ impl Packet { if prev < 0 { drop(self.take_to_wake()); } else { - while self.queue.producer_addition().to_wake.load(Ordering::SeqCst) != 0 { + while self.queue.producer_addition().to_wake.load(Ordering::SeqCst) != EMPTY { thread::yield_now(); } } @@ -451,6 +452,6 @@ impl Drop for Packet { // `to_wake`, so this assert cannot be removed with also removing // the `to_wake` assert. assert_eq!(self.queue.producer_addition().cnt.load(Ordering::SeqCst), DISCONNECTED); - assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), 0); + assert_eq!(self.queue.producer_addition().to_wake.load(Ordering::SeqCst), EMPTY); } } diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index 8a5bf933d56ec..ab34d5c1e5504 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -1,10 +1,25 @@ +use env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use std::env; +use std::ffi::OsString; use std::path::PathBuf; +/// Given an executable called `name`, return the filename for the +/// executable for a particular target. +pub fn exe(name: &PathBuf) -> PathBuf { + if EXE_EXTENSION != "" && name.extension() != Some(EXE_EXTENSION.as_ref()) { + let mut name: OsString = name.clone().into(); + name.push(EXE_SUFFIX); + name.into() + } else { + name.clone() + } +} + fn main() { + let host = env::var("HOST").unwrap(); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-env-changed=RUSTC"); - println!("cargo:rustc-env=BUILD_TRIPLE={}", env::var("HOST").unwrap()); + println!("cargo:rustc-env=BUILD_TRIPLE={}", host); // This may not be a canonicalized path. let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap()); @@ -12,7 +27,7 @@ fn main() { if rustc.is_relative() { println!("cargo:rerun-if-env-changed=PATH"); for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { - let absolute = dir.join(&rustc); + let absolute = dir.join(&exe(&rustc)); if absolute.exists() { rustc = absolute; break; diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md index 941c65922d8f0..e7bf8d9a36f25 100644 --- a/src/doc/rustc/src/linker-plugin-lto.md +++ b/src/doc/rustc/src/linker-plugin-lto.md @@ -136,7 +136,7 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS ```sh rustup toolchain install --profile minimal nightly MINOR_VERSION=$(rustc +nightly --version | cut -d . -f 2) -LOWER_BOUND=44 +LOWER_BOUND=61 llvm_version() { toolchain="$1" @@ -179,5 +179,19 @@ The following table shows known good combinations of toolchain versions. | Rust 1.44 | Clang 9 | | Rust 1.45 | Clang 10 | | Rust 1.46 | Clang 10 | +| Rust 1.47 | Clang 11 | +| Rust 1.48 | Clang 11 | +| Rust 1.49 | Clang 11 | +| Rust 1.50 | Clang 11 | +| Rust 1.51 | Clang 11 | +| Rust 1.52 | Clang 12 | +| Rust 1.53 | Clang 12 | +| Rust 1.54 | Clang 12 | +| Rust 1.55 | Clang 12 | +| Rust 1.56 | Clang 13 | +| Rust 1.57 | Clang 13 | +| Rust 1.58 | Clang 13 | +| Rust 1.59 | Clang 13 | +| Rust 1.60 | Clang 14 | Note that the compatibility policy for this feature might change in the future. diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 50ae22b99cdf8..abc899d4caf09 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -310,7 +310,10 @@ fn run_test( let (test, line_offset, supports_color) = make_test(test, Some(crate_name), lang_string.test_harness, opts, edition, Some(test_id)); - let output_file = outdir.path().join("rust_out"); + // Make sure we emit well-formed executable names for our platform. + let mut output_file = outdir.path().join("rust_out"); + output_file.set_extension(env::consts::EXE_EXTENSION); + let output_file = output_file; let rustc_binary = rustdoc_options .test_builder diff --git a/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff b/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff new file mode 100644 index 0000000000000..d465724326e46 --- /dev/null +++ b/src/test/mir-opt/derefer_test_multiple.main.Derefer.diff @@ -0,0 +1,100 @@ +- // MIR for `main` before Derefer ++ // MIR for `main` after Derefer + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/derefer_test_multiple.rs:2:12: 2:12 + let mut _1: (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:3:9: 3:14 + let mut _3: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:4:22: 4:28 + let mut _5: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:5:22: 5:28 + let mut _7: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:6:22: 6:28 ++ let mut _10: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ let mut _11: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ let mut _12: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ let mut _13: &mut (i32, &mut (i32, &mut (i32, i32))); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ let mut _14: &mut (i32, &mut (i32, i32)); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ let mut _15: &mut (i32, i32); // in scope 0 at $DIR/derefer_test_multiple.rs:8:13: 8:30 + scope 1 { + debug a => _1; // in scope 1 at $DIR/derefer_test_multiple.rs:3:9: 3:14 + let mut _2: (i32, &mut (i32, i32)); // in scope 1 at $DIR/derefer_test_multiple.rs:4:9: 4:14 + scope 2 { + debug b => _2; // in scope 2 at $DIR/derefer_test_multiple.rs:4:9: 4:14 + let mut _4: (i32, &mut (i32, &mut (i32, i32))); // in scope 2 at $DIR/derefer_test_multiple.rs:5:9: 5:14 + scope 3 { + debug c => _4; // in scope 3 at $DIR/derefer_test_multiple.rs:5:9: 5:14 + let mut _6: (i32, &mut (i32, &mut (i32, &mut (i32, i32)))); // in scope 3 at $DIR/derefer_test_multiple.rs:6:9: 6:14 + scope 4 { + debug d => _6; // in scope 4 at $DIR/derefer_test_multiple.rs:6:9: 6:14 + let _8: &mut i32; // in scope 4 at $DIR/derefer_test_multiple.rs:7:9: 7:10 + scope 5 { + debug x => _8; // in scope 5 at $DIR/derefer_test_multiple.rs:7:9: 7:10 + let _9: &mut i32; // in scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 + scope 6 { + debug y => _9; // in scope 6 at $DIR/derefer_test_multiple.rs:8:9: 8:10 + } + } + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/derefer_test_multiple.rs:3:9: 3:14 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/derefer_test_multiple.rs:3:17: 3:25 + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/derefer_test_multiple.rs:3:17: 3:25 + StorageLive(_2); // scope 1 at $DIR/derefer_test_multiple.rs:4:9: 4:14 + StorageLive(_3); // scope 1 at $DIR/derefer_test_multiple.rs:4:22: 4:28 + _3 = &mut _1; // scope 1 at $DIR/derefer_test_multiple.rs:4:22: 4:28 + (_2.0: i32) = const 99_i32; // scope 1 at $DIR/derefer_test_multiple.rs:4:17: 4:29 + (_2.1: &mut (i32, i32)) = move _3; // scope 1 at $DIR/derefer_test_multiple.rs:4:17: 4:29 + StorageDead(_3); // scope 1 at $DIR/derefer_test_multiple.rs:4:28: 4:29 + StorageLive(_4); // scope 2 at $DIR/derefer_test_multiple.rs:5:9: 5:14 + StorageLive(_5); // scope 2 at $DIR/derefer_test_multiple.rs:5:22: 5:28 + _5 = &mut _2; // scope 2 at $DIR/derefer_test_multiple.rs:5:22: 5:28 + (_4.0: i32) = const 11_i32; // scope 2 at $DIR/derefer_test_multiple.rs:5:17: 5:29 + (_4.1: &mut (i32, &mut (i32, i32))) = move _5; // scope 2 at $DIR/derefer_test_multiple.rs:5:17: 5:29 + StorageDead(_5); // scope 2 at $DIR/derefer_test_multiple.rs:5:28: 5:29 + StorageLive(_6); // scope 3 at $DIR/derefer_test_multiple.rs:6:9: 6:14 + StorageLive(_7); // scope 3 at $DIR/derefer_test_multiple.rs:6:22: 6:28 + _7 = &mut _4; // scope 3 at $DIR/derefer_test_multiple.rs:6:22: 6:28 + (_6.0: i32) = const 13_i32; // scope 3 at $DIR/derefer_test_multiple.rs:6:17: 6:29 + (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))) = move _7; // scope 3 at $DIR/derefer_test_multiple.rs:6:17: 6:29 + StorageDead(_7); // scope 3 at $DIR/derefer_test_multiple.rs:6:28: 6:29 + StorageLive(_8); // scope 4 at $DIR/derefer_test_multiple.rs:7:9: 7:10 +- _8 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ StorageLive(_10); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _10 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ StorageLive(_11); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _11 = move ((*_10).1: &mut (i32, &mut (i32, i32))); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ StorageLive(_12); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _12 = move ((*_11).1: &mut (i32, i32)); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ _8 = &mut ((*_12).1: i32); // scope 4 at $DIR/derefer_test_multiple.rs:7:13: 7:30 ++ StorageDead(_10); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 ++ StorageDead(_11); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 ++ StorageDead(_12); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 + StorageLive(_9); // scope 5 at $DIR/derefer_test_multiple.rs:8:9: 8:10 +- _9 = &mut ((*((*((*(_6.1: &mut (i32, &mut (i32, &mut (i32, i32))))).1: &mut (i32, &mut (i32, i32)))).1: &mut (i32, i32))).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ StorageLive(_13); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _13 = move (_6.1: &mut (i32, &mut (i32, &mut (i32, i32)))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ StorageLive(_14); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _14 = move ((*_13).1: &mut (i32, &mut (i32, i32))); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ StorageLive(_15); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _15 = move ((*_14).1: &mut (i32, i32)); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ _9 = &mut ((*_15).1: i32); // scope 5 at $DIR/derefer_test_multiple.rs:8:13: 8:30 ++ StorageDead(_13); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2 ++ StorageDead(_14); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2 ++ StorageDead(_15); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2 + _0 = const (); // scope 0 at $DIR/derefer_test_multiple.rs:2:12: 9:2 + StorageDead(_9); // scope 5 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + StorageDead(_8); // scope 4 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + StorageDead(_6); // scope 3 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + StorageDead(_4); // scope 2 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + StorageDead(_2); // scope 1 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + StorageDead(_1); // scope 0 at $DIR/derefer_test_multiple.rs:9:1: 9:2 + return; // scope 0 at $DIR/derefer_test_multiple.rs:9:2: 9:2 ++ } ++ ++ bb1 (cleanup): { ++ resume; // scope 0 at $DIR/derefer_test_multiple.rs:2:1: 9:2 + } + } + diff --git a/src/test/mir-opt/derefer_test_multiple.rs b/src/test/mir-opt/derefer_test_multiple.rs new file mode 100644 index 0000000000000..a27363447fee5 --- /dev/null +++ b/src/test/mir-opt/derefer_test_multiple.rs @@ -0,0 +1,9 @@ +// EMIT_MIR derefer_test_multiple.main.Derefer.diff +fn main () { + let mut a = (42, 43); + let mut b = (99, &mut a); + let mut c = (11, &mut b); + let mut d = (13, &mut c); + let x = &mut (*d.1).1.1.1; + let y = &mut (*d.1).1.1.1; +} diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr index 489cb03ddd316..e7a6c1837bd56 100644 --- a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr +++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr @@ -9,7 +9,7 @@ note: the lint level is defined here | LL | #![deny(lossy_provenance_casts)] | ^^^^^^^^^^^^^^^^^^^^^^ - = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead error: under strict provenance it is considered bad style to cast pointer `*const u8` to integer `u32` --> $DIR/lint-strict-provenance-lossy-casts.rs:9:22 @@ -17,7 +17,7 @@ error: under strict provenance it is considered bad style to cast pointer `*cons LL | let addr_32bit = &x as *const u8 as u32; | ^^^^^^^^^^^^^^^^^^^^^^ help: use `.addr()` to obtain the address of a pointer: `(&x as *const u8).addr() as u32` | - = help: if you can't comply with strict provenance and need to expose the pointerprovenance you can use `.expose_addr()` instead + = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead error: aborting due to 2 previous errors