Skip to content

Commit 418be0c

Browse files
committed
Auto merge of #3803 - RalfJung:rustup, r=RalfJung
Rustup
2 parents 34002f1 + 3dbf677 commit 418be0c

File tree

7 files changed

+66
-8
lines changed

7 files changed

+66
-8
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ jobs:
123123
run: |
124124
git config --global user.name 'The Miri Cronjob Bot'
125125
git config --global user.email '[email protected]'
126+
- name: Install nightly toolchain
127+
run: rustup toolchain install nightly --profile minimal
126128
- name: get changes from rustc
127129
run: ./miri rustc-pull
128130
- name: Install rustup-toolchain-install-master

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1d8f135b20fac63c493d5963ce02963b46ca0986
1+
e9c965df7b75ab5b1ae8f9a2680839ac1a1a3880

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ extern crate tracing;
5858
// The rustc crates we need
5959
extern crate rustc_apfloat;
6060
extern crate rustc_ast;
61+
extern crate rustc_attr;
6162
extern crate rustc_const_eval;
6263
extern crate rustc_data_structures;
6364
extern crate rustc_errors;

src/machine.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rand::rngs::StdRng;
1111
use rand::Rng;
1212
use rand::SeedableRng;
1313

14+
use rustc_attr::InlineAttr;
1415
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1516
#[allow(unused)]
1617
use rustc_data_structures::static_assert_size;
@@ -23,6 +24,7 @@ use rustc_middle::{
2324
Instance, Ty, TyCtxt,
2425
},
2526
};
27+
use rustc_session::config::InliningThreshold;
2628
use rustc_span::def_id::{CrateNum, DefId};
2729
use rustc_span::{Span, SpanData, Symbol};
2830
use rustc_target::abi::{Align, Size};
@@ -47,10 +49,10 @@ pub const SIGRTMIN: i32 = 34;
4749
/// `SIGRTMAX` - `SIGRTMIN` >= 8 (which is the value of `_POSIX_RTSIG_MAX`)
4850
pub const SIGRTMAX: i32 = 42;
4951

50-
/// Each const has multiple addresses, but only this many. Since const allocations are never
51-
/// deallocated, choosing a new [`AllocId`] and thus base address for each evaluation would
52-
/// produce unbounded memory usage.
53-
const ADDRS_PER_CONST: usize = 16;
52+
/// Each anonymous global (constant, vtable, function pointer, ...) has multiple addresses, but only
53+
/// this many. Since const allocations are never deallocated, choosing a new [`AllocId`] and thus
54+
/// base address for each evaluation would produce unbounded memory usage.
55+
const ADDRS_PER_ANON_GLOBAL: usize = 32;
5456

5557
/// Extra data stored with each stack frame
5658
pub struct FrameExtra<'tcx> {
@@ -1372,7 +1374,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
13721374
catch_unwind: None,
13731375
timing,
13741376
is_user_relevant: ecx.machine.is_user_relevant(&frame),
1375-
salt: ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_CONST,
1377+
salt: ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL,
13761378
};
13771379

13781380
Ok(frame.with_extra(extra))
@@ -1518,4 +1520,45 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15181520
Entry::Occupied(oe) => Ok(oe.get().clone()),
15191521
}
15201522
}
1523+
1524+
fn get_global_alloc_salt(
1525+
ecx: &InterpCx<'tcx, Self>,
1526+
instance: Option<ty::Instance<'tcx>>,
1527+
) -> usize {
1528+
let unique = if let Some(instance) = instance {
1529+
// Functions cannot be identified by pointers, as asm-equal functions can get
1530+
// deduplicated by the linker (we set the "unnamed_addr" attribute for LLVM) and
1531+
// functions can be duplicated across crates. We thus generate a new `AllocId` for every
1532+
// mention of a function. This means that `main as fn() == main as fn()` is false, while
1533+
// `let x = main as fn(); x == x` is true. However, as a quality-of-life feature it can
1534+
// be useful to identify certain functions uniquely, e.g. for backtraces. So we identify
1535+
// whether codegen will actually emit duplicate functions. It does that when they have
1536+
// non-lifetime generics, or when they can be inlined. All other functions are given a
1537+
// unique address. This is not a stable guarantee! The `inline` attribute is a hint and
1538+
// cannot be relied upon for anything. But if we don't do this, the
1539+
// `__rust_begin_short_backtrace`/`__rust_end_short_backtrace` logic breaks and panic
1540+
// backtraces look terrible.
1541+
let is_generic = instance
1542+
.args
1543+
.into_iter()
1544+
.any(|kind| !matches!(kind.unpack(), ty::GenericArgKind::Lifetime(_)));
1545+
let can_be_inlined = matches!(
1546+
ecx.tcx.sess.opts.unstable_opts.cross_crate_inline_threshold,
1547+
InliningThreshold::Always
1548+
) || !matches!(
1549+
ecx.tcx.codegen_fn_attrs(instance.def_id()).inline,
1550+
InlineAttr::Never
1551+
);
1552+
!is_generic && !can_be_inlined
1553+
} else {
1554+
// Non-functions are never unique.
1555+
false
1556+
};
1557+
// Always use the same salt if the allocation is unique.
1558+
if unique {
1559+
CTFE_ALLOC_SALT
1560+
} else {
1561+
ecx.machine.rng.borrow_mut().gen::<usize>() % ADDRS_PER_ANON_GLOBAL
1562+
}
1563+
}
15211564
}

tests/pass/dyn-traits.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,17 @@ fn unsized_dyn_autoderef() {
141141
}
142142
*/
143143

144+
fn vtable_ptr_eq() {
145+
use std::{fmt, ptr};
146+
147+
// We don't always get the same vtable when casting this to a wide pointer.
148+
let x = &2;
149+
let x_wide = x as &dyn fmt::Display;
150+
assert!((0..256).any(|_| !ptr::eq(x as &dyn fmt::Display, x_wide)));
151+
}
152+
144153
fn main() {
145154
ref_box_dyn();
146155
box_box_trait();
156+
vtable_ptr_eq();
147157
}

tests/pass/function_pointers.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ fn main() {
8282
assert!(return_fn_ptr(i) == i);
8383
assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32);
8484
// Miri gives different addresses to different reifications of a generic function.
85-
assert!(return_fn_ptr(f) != f);
85+
// at least if we try often enough.
86+
assert!((0..256).any(|_| return_fn_ptr(f) != f));
8687
// However, if we only turn `f` into a function pointer and use that pointer,
8788
// it is equal to itself.
8889
let f2 = f as fn() -> i32;

tests/pass/rc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ fn rc_fat_ptr_eq() {
7575
let p = Rc::new(1) as Rc<dyn Debug>;
7676
let a: *const dyn Debug = &*p;
7777
let r = Rc::into_raw(p);
78-
assert!(a == r);
78+
// Only compare the pointer parts, as the vtable might differ.
79+
assert!(a as *const () == r as *const ());
7980
drop(unsafe { Rc::from_raw(r) });
8081
}
8182

0 commit comments

Comments
 (0)