Auto merge of #138114 - compiler-errors:rollup-7xr4b69, r=compiler-errors
Rollup of 25 pull requests Successful merges: - #135733 (Implement `&pin const self` and `&pin mut self` sugars) - #135895 (Document workings of successors more clearly) - #136922 (Pattern types: Avoid having to handle an Option for range ends in the type system or the HIR) - #137303 (Remove `MaybeForgetReturn` suggestion) - #137327 (Undeprecate env::home_dir) - #137358 (Match Ergonomics 2024: add context and examples to the unstable book) - #137534 ([rustdoc] hide item that is not marked as doc(inline) and whose src is doc(hidden)) - #137565 (Try to point of macro expansion from resolver and method errors if it involves macro var) - #137637 (Check dyn flavor before registering upcast goal on wide pointer cast in MIR typeck) - #137643 (Add DWARF test case for non-C-like `repr128` enums) - #137744 (Re-add `Clone`-derive on `Thir`) - #137758 (fix usage of ty decl macro fragments in attributes) - #137764 (Ensure that negative auto impls are always applicable) - #137772 (Fix char count in `Display` for `ByteStr`) - #137798 (ci: use ubuntu 24 on arm large runner) - #137802 (miri native-call support: all previously exposed provenance is accessible to the callee) - #137805 (adjust Layout debug printing to match the internal field name) - #137808 (Do not require that unsafe fields lack drop glue) - #137820 (Clarify why InhabitedPredicate::instantiate_opt exists) - #137825 (Provide more context on resolve error caused from incorrect RTN) - #137834 (rustc_fluent_macro: use CARGO_CRATE_NAME instead of CARGO_PKG_NAME) - #137868 (Add minimal platform support documentation for powerpc-unknown-linux-gnuspe) - #137910 (Improve error message for `AsyncFn` trait failure for RPIT) - #137920 (interpret/provenance_map: consistently use range_is_empty) - #138038 (Update `compiler-builtins` to 0.1.151) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
98a48781fe
169 changed files with 2261 additions and 1107 deletions
|
|
@ -54,7 +54,7 @@ runners:
|
|||
<<: *base-job
|
||||
|
||||
- &job-aarch64-linux-8c
|
||||
os: ubuntu-22.04-arm64-8core-32gb
|
||||
os: ubuntu-24.04-arm64-8core-32gb
|
||||
<<: *base-job
|
||||
envs:
|
||||
env-x86_64-apple-tests: &env-x86_64-apple-tests
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
|
||||
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
|
||||
- [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md)
|
||||
- [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md)
|
||||
- [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
|
||||
- [powerpc64-ibm-aix](platform-support/aix.md)
|
||||
- [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md)
|
||||
|
|
|
|||
|
|
@ -348,9 +348,9 @@ target | std | host | notes
|
|||
[`mipsisa64r6el-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ✓ | ✓ | 64-bit MIPS Release 6 Little Endian
|
||||
`msp430-none-elf` | * | | 16-bit MSP430 microcontrollers
|
||||
[`powerpc-unknown-freebsd`](platform-support/freebsd.md) | ? | | PowerPC FreeBSD
|
||||
`powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux
|
||||
[`powerpc-unknown-linux-gnuspe`](platform-support/powerpc-unknown-linux-gnuspe.md) | ✓ | | PowerPC SPE Linux
|
||||
`powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3
|
||||
[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux
|
||||
[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux with musl 1.2.3
|
||||
[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems
|
||||
[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | |
|
||||
[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
# powerpc-unknown-linux-gnuspe
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
`powerpc-unknown-linux-gnuspe` is a target for Linux on 32-bit PowerPC
|
||||
processors that implement the Signal Processing Engine (SPE), such as e500, and
|
||||
uses a different ABI than standard `powerpc-unknown-linux-gnu`.
|
||||
When building for other 32-bit PowerPC processors, use
|
||||
`powerpc-unknown-linux-gnu` instead.
|
||||
|
||||
See also [Debian Wiki](https://wiki.debian.org/PowerPCSPEPort) for details on
|
||||
this platform, and [ABI reference](https://web.archive.org/web/20120608163804/https://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf)
|
||||
for details on SPE ABI.
|
||||
|
||||
Note that support for PowerPC SPE by GCC was [removed in GCC 9](https://gcc.gnu.org/gcc-8/changes.html),
|
||||
so recent GCC cannot be used as linker/compiler for this target.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
There are currently no formally documented target maintainers.
|
||||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
**Tier: 3**
|
||||
|
||||
This target is very similar to already existing ones like `powerpc_unknown_linux_musl` and `powerpc_unknown_linux_gnuspe`.
|
||||
This target is very similar to already existing ones like `powerpc-unknown-linux-musl` and `powerpc-unknown-linux-gnuspe`.
|
||||
This one has PowerPC SPE support for musl. Unfortunately, the last supported gcc version with PowerPC SPE is 8.4.0.
|
||||
|
||||
See also [platform support documentation of `powerpc-unknown-linux-gnuspe`](powerpc-unknown-linux-gnuspe.md) for information about PowerPC SPE.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- [@BKPepe](https://github.com/BKPepe)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,32 @@ The tracking issue for this feature is: [#123076]
|
|||
This feature is incomplete and not yet intended for general use.
|
||||
|
||||
This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
|
||||
in Rust.
|
||||
For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
|
||||
[Editions 2024 and later].
|
||||
in Rust, allowing `&` patterns in more places. For example:
|
||||
```rust,edition2024
|
||||
#![feature(ref_pat_eat_one_layer_2024_structural)]
|
||||
#![allow(incomplete_features)]
|
||||
#
|
||||
# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`.
|
||||
# trait Eq<T> {}
|
||||
# impl<T> Eq<T> for T {}
|
||||
# fn has_type<T>(_: impl Eq<T>) {}
|
||||
|
||||
// `&` can match against a `ref` binding mode instead of a reference type:
|
||||
let (x, &y) = &(0, 1);
|
||||
has_type::<&u8>(x);
|
||||
has_type::<u8>(y);
|
||||
|
||||
// `&` can match against `&mut` references:
|
||||
let &z = &mut 2;
|
||||
has_type::<u8>(z);
|
||||
```
|
||||
|
||||
For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for
|
||||
[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference].
|
||||
|
||||
For alternative experimental match ergonomics, see the feature
|
||||
[`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md).
|
||||
|
||||
[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
|
||||
[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
|
||||
[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes
|
||||
|
|
|
|||
|
|
@ -9,12 +9,33 @@ The tracking issue for this feature is: [#123076]
|
|||
This feature is incomplete and not yet intended for general use.
|
||||
|
||||
This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
|
||||
in Rust.
|
||||
For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
|
||||
[Editions 2024 and later].
|
||||
in Rust, allowing `&` patterns in more places. For example:
|
||||
|
||||
```rust,edition2024
|
||||
#![feature(ref_pat_eat_one_layer_2024)]
|
||||
#![allow(incomplete_features)]
|
||||
#
|
||||
# // Tests type equality in a way that avoids coercing `&&T` or `&mut T` to `&T`.
|
||||
# trait Eq<T> {}
|
||||
# impl<T> Eq<T> for T {}
|
||||
# fn has_type<T>(_: impl Eq<T>) {}
|
||||
|
||||
// `&` can match against a `ref` binding mode instead of a reference type:
|
||||
let (x, &y) = &(0, 1);
|
||||
has_type::<&u8>(x);
|
||||
has_type::<u8>(y);
|
||||
|
||||
// `&` can match against `&mut` references:
|
||||
let &z = &mut 2;
|
||||
has_type::<u8>(z);
|
||||
```
|
||||
|
||||
For specifics, see the corresponding typing rules for [Editions 2021 and earlier] and for
|
||||
[Editions 2024 and later]. For more information on binding modes, see [The Rust Reference].
|
||||
|
||||
For alternative experimental match ergonomics, see the feature
|
||||
[`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md).
|
||||
|
||||
[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
|
||||
[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
|
||||
[The Rust Reference]: https://doc.rust-lang.org/reference/patterns.html#binding-modes
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_span::symbol::sym;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::clean;
|
||||
use crate::clean::utils::inherits_doc_hidden;
|
||||
use crate::clean::{Item, ItemIdSet};
|
||||
use crate::clean::{self, Item, ItemIdSet, reexport_chain};
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::{DocFolder, strip_item};
|
||||
use crate::passes::{ImplStripper, Pass};
|
||||
|
|
@ -89,6 +88,25 @@ impl Stripper<'_, '_> {
|
|||
impl DocFolder for Stripper<'_, '_> {
|
||||
fn fold_item(&mut self, i: Item) -> Option<Item> {
|
||||
let has_doc_hidden = i.is_doc_hidden();
|
||||
|
||||
if let clean::ImportItem(clean::Import { source, .. }) = &i.kind
|
||||
&& let Some(source_did) = source.did
|
||||
&& let Some(import_def_id) = i.def_id().and_then(|def_id| def_id.as_local())
|
||||
{
|
||||
let reexports = reexport_chain(self.tcx, import_def_id, source_did);
|
||||
|
||||
// Check if any reexport in the chain has a hidden source
|
||||
let has_hidden_source = reexports
|
||||
.iter()
|
||||
.filter_map(|reexport| reexport.id())
|
||||
.any(|reexport_did| self.tcx.is_doc_hidden(reexport_did))
|
||||
|| self.tcx.is_doc_hidden(source_did);
|
||||
|
||||
if has_hidden_source {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let is_impl_or_exported_macro = match i.kind {
|
||||
clean::ImplItem(..) => true,
|
||||
// If the macro has the `#[macro_export]` attribute, it means it's accessible at the
|
||||
|
|
|
|||
|
|
@ -1108,14 +1108,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
|
||||
std::mem::discriminant(&pat.kind).hash(&mut self.s);
|
||||
match pat.kind {
|
||||
TyPatKind::Range(s, e, i) => {
|
||||
if let Some(s) = s {
|
||||
self.hash_const_arg(s);
|
||||
}
|
||||
if let Some(e) = e {
|
||||
self.hash_const_arg(e);
|
||||
}
|
||||
std::mem::discriminant(&i).hash(&mut self.s);
|
||||
TyPatKind::Range(s, e) => {
|
||||
self.hash_const_arg(s);
|
||||
self.hash_const_arg(e);
|
||||
},
|
||||
TyPatKind::Err(_) => {},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,9 +285,19 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
|
||||
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
||||
fn expose_ptr(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> {
|
||||
fn expose_provenance(&self, provenance: Provenance) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
let mut global_state = this.machine.alloc_addresses.borrow_mut();
|
||||
|
||||
let (alloc_id, tag) = match provenance {
|
||||
Provenance::Concrete { alloc_id, tag } => (alloc_id, tag),
|
||||
Provenance::Wildcard => {
|
||||
// No need to do anything for wildcard pointers as
|
||||
// their provenances have already been previously exposed.
|
||||
return interp_ok(());
|
||||
}
|
||||
};
|
||||
|
||||
// In strict mode, we don't need this, so we can save some cycles by not tracking it.
|
||||
if global_state.provenance_mode == ProvenanceMode::Strict {
|
||||
return interp_ok(());
|
||||
|
|
@ -422,6 +432,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
let rel_offset = this.truncate_to_target_usize(addr.bytes().wrapping_sub(base_addr));
|
||||
Some((alloc_id, Size::from_bytes(rel_offset)))
|
||||
}
|
||||
|
||||
/// Prepare all exposed memory for a native call.
|
||||
/// This overapproximates the modifications which external code might make to memory:
|
||||
/// We set all reachable allocations as initialized, mark all reachable provenances as exposed
|
||||
/// and overwrite them with `Provenance::WILDCARD`.
|
||||
fn prepare_exposed_for_native_call(&mut self) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
// We need to make a deep copy of this list, but it's fine; it also serves as scratch space
|
||||
// for the search within `prepare_for_native_call`.
|
||||
let exposed: Vec<AllocId> =
|
||||
this.machine.alloc_addresses.get_mut().exposed.iter().copied().collect();
|
||||
this.prepare_for_native_call(exposed)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> MiriMachine<'tcx> {
|
||||
|
|
|
|||
|
|
@ -1291,18 +1291,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
|
|||
/// Called on `ptr as usize` casts.
|
||||
/// (Actually computing the resulting `usize` doesn't need machine help,
|
||||
/// that's just `Scalar::try_to_int`.)
|
||||
#[inline(always)]
|
||||
fn expose_provenance(
|
||||
ecx: &InterpCx<'tcx, Self>,
|
||||
provenance: Self::Provenance,
|
||||
) -> InterpResult<'tcx> {
|
||||
match provenance {
|
||||
Provenance::Concrete { alloc_id, tag } => ecx.expose_ptr(alloc_id, tag),
|
||||
Provenance::Wildcard => {
|
||||
// No need to do anything for wildcard pointers as
|
||||
// their provenances have already been previously exposed.
|
||||
interp_ok(())
|
||||
}
|
||||
}
|
||||
ecx.expose_provenance(provenance)
|
||||
}
|
||||
|
||||
/// Convert a pointer with provenance into an allocation-offset pair and extra provenance info.
|
||||
|
|
|
|||
|
|
@ -160,16 +160,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
let imm = this.read_immediate(arg)?;
|
||||
libffi_args.push(imm_to_carg(&imm, this)?);
|
||||
// If we are passing a pointer, prepare the memory it points to.
|
||||
// If we are passing a pointer, expose its provenance. Below, all exposed memory
|
||||
// (previously exposed and new exposed) will then be properly prepared.
|
||||
if matches!(arg.layout.ty.kind(), ty::RawPtr(..)) {
|
||||
let ptr = imm.to_scalar().to_pointer(this)?;
|
||||
let Some(prov) = ptr.provenance else {
|
||||
// Pointer without provenance may not access any memory.
|
||||
continue;
|
||||
};
|
||||
// We use `get_alloc_id` for its best-effort behaviour with Wildcard provenance.
|
||||
let Some(alloc_id) = prov.get_alloc_id() else {
|
||||
// Wildcard pointer, whatever it points to must be already exposed.
|
||||
// Pointer without provenance may not access any memory anyway, skip.
|
||||
continue;
|
||||
};
|
||||
// The first time this happens, print a warning.
|
||||
|
|
@ -178,12 +174,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem);
|
||||
}
|
||||
|
||||
this.prepare_for_native_call(alloc_id, prov)?;
|
||||
this.expose_provenance(prov)?;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: In the future, we should also call `prepare_for_native_call` on all previously
|
||||
// exposed allocations, since C may access any of them.
|
||||
// Prepare all exposed memory.
|
||||
this.prepare_exposed_for_native_call()?;
|
||||
|
||||
// Convert them to `libffi::high::Arg` type.
|
||||
let libffi_args = libffi_args
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#![feature(box_as_ptr)]
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr::null;
|
||||
use std::ptr;
|
||||
|
||||
fn main() {
|
||||
test_increment_int();
|
||||
|
|
@ -20,6 +20,8 @@ fn main() {
|
|||
test_pass_dangling();
|
||||
test_swap_ptr_triple_dangling();
|
||||
test_return_ptr();
|
||||
test_pass_ptr_as_int();
|
||||
test_pass_ptr_via_previously_shared_mem();
|
||||
}
|
||||
|
||||
/// Test function that modifies an int.
|
||||
|
|
@ -112,7 +114,7 @@ fn test_swap_ptr() {
|
|||
}
|
||||
|
||||
let x = 61;
|
||||
let (mut ptr0, mut ptr1) = (&raw const x, null());
|
||||
let (mut ptr0, mut ptr1) = (&raw const x, ptr::null());
|
||||
|
||||
unsafe { swap_ptr(&mut ptr0, &mut ptr1) };
|
||||
assert_eq!(unsafe { *ptr1 }, x);
|
||||
|
|
@ -131,7 +133,7 @@ fn test_swap_ptr_tuple() {
|
|||
}
|
||||
|
||||
let x = 71;
|
||||
let mut tuple = Tuple { ptr0: &raw const x, ptr1: null() };
|
||||
let mut tuple = Tuple { ptr0: &raw const x, ptr1: ptr::null() };
|
||||
|
||||
unsafe { swap_ptr_tuple(&mut tuple) }
|
||||
assert_eq!(unsafe { *tuple.ptr1 }, x);
|
||||
|
|
@ -148,7 +150,7 @@ fn test_overwrite_dangling() {
|
|||
drop(b);
|
||||
|
||||
unsafe { overwrite_ptr(&mut ptr) };
|
||||
assert_eq!(ptr, null());
|
||||
assert_eq!(ptr, ptr::null());
|
||||
}
|
||||
|
||||
/// Test function that passes a dangling pointer.
|
||||
|
|
@ -200,3 +202,33 @@ fn test_return_ptr() {
|
|||
let ptr = unsafe { return_ptr(ptr) };
|
||||
assert_eq!(unsafe { *ptr }, x);
|
||||
}
|
||||
|
||||
/// Test casting a pointer to an integer and passing that to C.
|
||||
fn test_pass_ptr_as_int() {
|
||||
extern "C" {
|
||||
fn pass_ptr_as_int(ptr: usize, set_to_val: i32);
|
||||
}
|
||||
|
||||
let mut m: MaybeUninit<i32> = MaybeUninit::uninit();
|
||||
unsafe { pass_ptr_as_int(m.as_mut_ptr() as usize, 42) };
|
||||
assert_eq!(unsafe { m.assume_init() }, 42);
|
||||
}
|
||||
|
||||
fn test_pass_ptr_via_previously_shared_mem() {
|
||||
extern "C" {
|
||||
fn set_shared_mem(ptr: *mut *mut i32);
|
||||
fn init_ptr_stored_in_shared_mem(val: i32);
|
||||
}
|
||||
|
||||
let mut m: *mut i32 = ptr::null_mut();
|
||||
let ptr_to_m = &raw mut m;
|
||||
unsafe { set_shared_mem(&raw mut m) };
|
||||
|
||||
let mut m2: MaybeUninit<i32> = MaybeUninit::uninit();
|
||||
// Store a pointer to m2 somewhere that C code can access it.
|
||||
unsafe { ptr_to_m.write(m2.as_mut_ptr()) };
|
||||
// Have C code write there.
|
||||
unsafe { init_ptr_stored_in_shared_mem(42) };
|
||||
// Ensure this memory is now considered initialized.
|
||||
assert_eq!(unsafe { m2.assume_init() }, 42);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,34 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// See comments in build_native_lib()
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
/* Test: test_access_pointer */
|
||||
|
||||
EXPORT void print_pointer(const int *ptr) {
|
||||
EXPORT void print_pointer(const int32_t *ptr) {
|
||||
printf("printing pointer dereference from C: %d\n", *ptr);
|
||||
}
|
||||
|
||||
/* Test: test_access_simple */
|
||||
|
||||
typedef struct Simple {
|
||||
int field;
|
||||
int32_t field;
|
||||
} Simple;
|
||||
|
||||
EXPORT int access_simple(const Simple *s_ptr) {
|
||||
EXPORT int32_t access_simple(const Simple *s_ptr) {
|
||||
return s_ptr->field;
|
||||
}
|
||||
|
||||
/* Test: test_access_nested */
|
||||
|
||||
typedef struct Nested {
|
||||
int value;
|
||||
int32_t value;
|
||||
struct Nested *next;
|
||||
} Nested;
|
||||
|
||||
// Returns the innermost/last value of a Nested pointer chain.
|
||||
EXPORT int access_nested(const Nested *n_ptr) {
|
||||
EXPORT int32_t access_nested(const Nested *n_ptr) {
|
||||
// Edge case: `n_ptr == NULL` (i.e. first Nested is None).
|
||||
if (!n_ptr) { return 0; }
|
||||
|
||||
|
|
@ -41,10 +42,10 @@ EXPORT int access_nested(const Nested *n_ptr) {
|
|||
/* Test: test_access_static */
|
||||
|
||||
typedef struct Static {
|
||||
int value;
|
||||
int32_t value;
|
||||
struct Static *recurse;
|
||||
} Static;
|
||||
|
||||
EXPORT int access_static(const Static *s_ptr) {
|
||||
EXPORT int32_t access_static(const Static *s_ptr) {
|
||||
return s_ptr->recurse->recurse->value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,24 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// See comments in build_native_lib()
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
/* Test: test_increment_int */
|
||||
|
||||
EXPORT void increment_int(int *ptr) {
|
||||
EXPORT void increment_int(int32_t *ptr) {
|
||||
*ptr += 1;
|
||||
}
|
||||
|
||||
/* Test: test_init_int */
|
||||
|
||||
EXPORT void init_int(int *ptr, int val) {
|
||||
EXPORT void init_int(int32_t *ptr, int32_t val) {
|
||||
*ptr = val;
|
||||
}
|
||||
|
||||
/* Test: test_init_array */
|
||||
|
||||
EXPORT void init_array(int *array, size_t len, int val) {
|
||||
EXPORT void init_array(int32_t *array, size_t len, int32_t val) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
array[i] = val;
|
||||
}
|
||||
|
|
@ -26,28 +27,28 @@ EXPORT void init_array(int *array, size_t len, int val) {
|
|||
/* Test: test_init_static_inner */
|
||||
|
||||
typedef struct SyncPtr {
|
||||
int *ptr;
|
||||
int32_t *ptr;
|
||||
} SyncPtr;
|
||||
|
||||
EXPORT void init_static_inner(const SyncPtr *s_ptr, int val) {
|
||||
EXPORT void init_static_inner(const SyncPtr *s_ptr, int32_t val) {
|
||||
*(s_ptr->ptr) = val;
|
||||
}
|
||||
|
||||
/* Tests: test_exposed, test_pass_dangling */
|
||||
|
||||
EXPORT void ignore_ptr(__attribute__((unused)) const int *ptr) {
|
||||
EXPORT void ignore_ptr(__attribute__((unused)) const int32_t *ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test: test_expose_int */
|
||||
EXPORT void expose_int(const int *int_ptr, const int **pptr) {
|
||||
EXPORT void expose_int(const int32_t *int_ptr, const int32_t **pptr) {
|
||||
*pptr = int_ptr;
|
||||
}
|
||||
|
||||
/* Test: test_swap_ptr */
|
||||
|
||||
EXPORT void swap_ptr(const int **pptr0, const int **pptr1) {
|
||||
const int *tmp = *pptr0;
|
||||
EXPORT void swap_ptr(const int32_t **pptr0, const int32_t **pptr1) {
|
||||
const int32_t *tmp = *pptr0;
|
||||
*pptr0 = *pptr1;
|
||||
*pptr1 = tmp;
|
||||
}
|
||||
|
|
@ -55,36 +56,54 @@ EXPORT void swap_ptr(const int **pptr0, const int **pptr1) {
|
|||
/* Test: test_swap_ptr_tuple */
|
||||
|
||||
typedef struct Tuple {
|
||||
int *ptr0;
|
||||
int *ptr1;
|
||||
int32_t *ptr0;
|
||||
int32_t *ptr1;
|
||||
} Tuple;
|
||||
|
||||
EXPORT void swap_ptr_tuple(Tuple *t_ptr) {
|
||||
int *tmp = t_ptr->ptr0;
|
||||
int32_t *tmp = t_ptr->ptr0;
|
||||
t_ptr->ptr0 = t_ptr->ptr1;
|
||||
t_ptr->ptr1 = tmp;
|
||||
}
|
||||
|
||||
/* Test: test_overwrite_dangling */
|
||||
|
||||
EXPORT void overwrite_ptr(const int **pptr) {
|
||||
EXPORT void overwrite_ptr(const int32_t **pptr) {
|
||||
*pptr = NULL;
|
||||
}
|
||||
|
||||
/* Test: test_swap_ptr_triple_dangling */
|
||||
|
||||
typedef struct Triple {
|
||||
int *ptr0;
|
||||
int *ptr1;
|
||||
int *ptr2;
|
||||
int32_t *ptr0;
|
||||
int32_t *ptr1;
|
||||
int32_t *ptr2;
|
||||
} Triple;
|
||||
|
||||
EXPORT void swap_ptr_triple_dangling(Triple *t_ptr) {
|
||||
int *tmp = t_ptr->ptr0;
|
||||
int32_t *tmp = t_ptr->ptr0;
|
||||
t_ptr->ptr0 = t_ptr->ptr2;
|
||||
t_ptr->ptr2 = tmp;
|
||||
}
|
||||
|
||||
EXPORT const int *return_ptr(const int *ptr) {
|
||||
EXPORT const int32_t *return_ptr(const int32_t *ptr) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Test: test_pass_ptr_as_int */
|
||||
|
||||
EXPORT void pass_ptr_as_int(uintptr_t ptr, int32_t set_to_val) {
|
||||
*(int32_t*)ptr = set_to_val;
|
||||
}
|
||||
|
||||
/* Test: test_pass_ptr_via_previously_shared_mem */
|
||||
|
||||
int32_t** shared_place;
|
||||
|
||||
EXPORT void set_shared_mem(int32_t** ptr) {
|
||||
shared_place = ptr;
|
||||
}
|
||||
|
||||
EXPORT void init_ptr_stored_in_shared_mem(int32_t val) {
|
||||
**shared_place = val;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// See comments in build_native_lib()
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
|
||||
EXPORT int add_one_int(int x) {
|
||||
EXPORT int32_t add_one_int(int32_t x) {
|
||||
return 2 + x;
|
||||
}
|
||||
|
||||
|
|
@ -13,23 +14,23 @@ EXPORT void printer(void) {
|
|||
|
||||
// function with many arguments, to test functionality when some args are stored
|
||||
// on the stack
|
||||
EXPORT int test_stack_spill(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) {
|
||||
EXPORT int32_t test_stack_spill(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, int32_t f, int32_t g, int32_t h, int32_t i, int32_t j, int32_t k, int32_t l) {
|
||||
return a+b+c+d+e+f+g+h+i+j+k+l;
|
||||
}
|
||||
|
||||
EXPORT unsigned int get_unsigned_int(void) {
|
||||
EXPORT uint32_t get_unsigned_int(void) {
|
||||
return -10;
|
||||
}
|
||||
|
||||
EXPORT short add_int16(short x) {
|
||||
EXPORT short add_int16(int16_t x) {
|
||||
return x + 3;
|
||||
}
|
||||
|
||||
EXPORT long add_short_to_long(short x, long y) {
|
||||
EXPORT long add_short_to_long(int16_t x, int64_t y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
// To test that functions not marked with EXPORT cannot be called by Miri.
|
||||
int not_exported(void) {
|
||||
int32_t not_exported(void) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2359,6 +2359,21 @@ impl Rewrite for ast::Param {
|
|||
}
|
||||
}
|
||||
|
||||
fn rewrite_opt_lifetime(
|
||||
context: &RewriteContext<'_>,
|
||||
lifetime: Option<ast::Lifetime>,
|
||||
) -> RewriteResult {
|
||||
let Some(l) = lifetime else {
|
||||
return Ok(String::new());
|
||||
};
|
||||
let mut result = l.rewrite_result(
|
||||
context,
|
||||
Shape::legacy(context.config.max_width(), Indent::empty()),
|
||||
)?;
|
||||
result.push(' ');
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn rewrite_explicit_self(
|
||||
context: &RewriteContext<'_>,
|
||||
explicit_self: &ast::ExplicitSelf,
|
||||
|
|
@ -2367,58 +2382,34 @@ fn rewrite_explicit_self(
|
|||
shape: Shape,
|
||||
has_multiple_attr_lines: bool,
|
||||
) -> RewriteResult {
|
||||
match explicit_self.node {
|
||||
let self_str = match explicit_self.node {
|
||||
ast::SelfKind::Region(lt, m) => {
|
||||
let mut_str = format_mutability(m);
|
||||
match lt {
|
||||
Some(ref l) => {
|
||||
let lifetime_str = l.rewrite_result(
|
||||
context,
|
||||
Shape::legacy(context.config.max_width(), Indent::empty()),
|
||||
)?;
|
||||
Ok(combine_strs_with_missing_comments(
|
||||
context,
|
||||
param_attrs,
|
||||
&format!("&{lifetime_str} {mut_str}self"),
|
||||
span,
|
||||
shape,
|
||||
!has_multiple_attr_lines,
|
||||
)?)
|
||||
}
|
||||
None => Ok(combine_strs_with_missing_comments(
|
||||
context,
|
||||
param_attrs,
|
||||
&format!("&{mut_str}self"),
|
||||
span,
|
||||
shape,
|
||||
!has_multiple_attr_lines,
|
||||
)?),
|
||||
}
|
||||
let lifetime_str = rewrite_opt_lifetime(context, lt)?;
|
||||
format!("&{lifetime_str}{mut_str}self")
|
||||
}
|
||||
ast::SelfKind::Pinned(lt, m) => {
|
||||
let mut_str = m.ptr_str();
|
||||
let lifetime_str = rewrite_opt_lifetime(context, lt)?;
|
||||
format!("&{lifetime_str}pin {mut_str} self")
|
||||
}
|
||||
ast::SelfKind::Explicit(ref ty, mutability) => {
|
||||
let type_str = ty.rewrite_result(
|
||||
context,
|
||||
Shape::legacy(context.config.max_width(), Indent::empty()),
|
||||
)?;
|
||||
|
||||
Ok(combine_strs_with_missing_comments(
|
||||
context,
|
||||
param_attrs,
|
||||
&format!("{}self: {}", format_mutability(mutability), type_str),
|
||||
span,
|
||||
shape,
|
||||
!has_multiple_attr_lines,
|
||||
)?)
|
||||
format!("{}self: {}", format_mutability(mutability), type_str)
|
||||
}
|
||||
ast::SelfKind::Value(mutability) => Ok(combine_strs_with_missing_comments(
|
||||
context,
|
||||
param_attrs,
|
||||
&format!("{}self", format_mutability(mutability)),
|
||||
span,
|
||||
shape,
|
||||
!has_multiple_attr_lines,
|
||||
)?),
|
||||
}
|
||||
ast::SelfKind::Value(mutability) => format!("{}self", format_mutability(mutability)),
|
||||
};
|
||||
Ok(combine_strs_with_missing_comments(
|
||||
context,
|
||||
param_attrs,
|
||||
&self_str,
|
||||
span,
|
||||
shape,
|
||||
!has_multiple_attr_lines,
|
||||
)?)
|
||||
}
|
||||
|
||||
pub(crate) fn span_lo_for_param(param: &ast::Param) -> BytePos {
|
||||
|
|
|
|||
|
|
@ -8,3 +8,13 @@ fn g<'a>(x: & 'a pin const i32) {}
|
|||
fn h<'a>(x: & 'a pin
|
||||
mut i32) {}
|
||||
fn i(x: &pin mut i32) {}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn f(&pin const self) {}
|
||||
fn g<'a>(& 'a pin const self) {}
|
||||
fn h<'a>(& 'a pin
|
||||
mut self) {}
|
||||
fn i(&pin mut self) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,3 +7,12 @@ fn f(x: &pin const i32) {}
|
|||
fn g<'a>(x: &'a pin const i32) {}
|
||||
fn h<'a>(x: &'a pin mut i32) {}
|
||||
fn i(x: &pin mut i32) {}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn f(&pin const self) {}
|
||||
fn g<'a>(&'a pin const self) {}
|
||||
fn h<'a>(&'a pin mut self) {}
|
||||
fn i(&pin mut self) {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue