Commit Graph

553 Commits

Author SHA1 Message Date
Boxy Uwu 6722805cdc Make ValTree recurse through ty::Const 2025-12-23 13:54:59 +00:00
Camille Gillot fab64de727 Improve comments. 2025-12-14 17:25:53 +00:00
Camille Gillot 6319bee585 Introduce Operand::RuntimeChecks. 2025-12-14 17:25:53 +00:00
Urgau 8cbfb26383 Overhaul filename handling for cross-compiler consistency
This commit refactors `SourceMap` and most importantly `RealFileName` to
make it self-contained in order to achieve cross-compiler consistency.

This is achieved:
 - by making `RealFileName` immutable
 - by only having `SourceMap::to_real_filename` create `RealFileName`
 - by also making `RealFileName` holds it's working directory,
   it's embeddable name and the remapped scopes
 - by making most `FileName` and `RealFileName` methods take a scope as
   an argument

In order for `SourceMap::to_real_filename` to know which scopes to apply
`FilePathMapping` now takes the current remapping scopes to apply, which
makes `FileNameDisplayPreference` and company useless and are removed.

The scopes type `RemapPathScopeComponents` was moved from
`rustc_session::config` to `rustc_span`.

The previous system for scoping the local/remapped filenames
`RemapFileNameExt::for_scope` is no longer useful as it's replaced by
methods on `FileName` and `RealFileName`.
2025-12-12 07:33:09 +01:00
Deadbeef cf91330b6b collapse constness query match logic
We already have the HIR node data, so no need for asking `def_kind` again.
2025-11-29 20:00:40 -05:00
Oli Scherer ababa26251 Collect const_conditions for inherent impls 2025-11-18 16:00:18 +00:00
Oli Scherer 939afab37e Treat inherent methods in const impl blocks as const 2025-11-18 16:00:18 +00:00
bors 4b53279854 Auto merge of #148040 - saethlin:trivial-consts, r=oli-obk
Add a fast path for lowering trivial consts

The objective of this PR is to improve compilation performance for crates that define a lot of trivial consts. This is a flamegraph of a build of a library crate that is just 100,000 trivial consts, taken from a nightly compiler:
<img width="842" height="280" alt="2025-10-25-164005_842x280_scrot" src="https://github.com/user-attachments/assets/e5400aaf-03bd-4461-b905-054aa82ca60f" />
My objective is to target all of the cycles in `eval_to_const_value_raw` that are not part of `mir_built`, because if you look at the `mir_built` for a trivial const, we already have the value available.

In this PR, the definition of a trivial const is this:
```rust
const A: usize = 0;
```
Specifically, we look for if the `mir_built` body is a single basic block containing one assign statement and a return terminator, where the assign statement assigns an `Operand::Constant(Const::Val)`. The MIR dumps for these look like:
```
const A: usize = {
    let mut _0: usize;

    bb0: {
        _0 = const 0_usize;
        return;
    }
}
```

The implementation is built around a new query, `trivial_const(LocalDefId) -> Option<(ConstValue, Ty)>` which returns the contents of the `Const::Val` in the `mir_built` if the `LocalDefId` is a trivial const.

Then I added _debug_ assertions to the beginning of `mir_for_ctfe` and `mir_promoted` to prevent trying to get the body of a trivial const, because that would defeat the optimization here. But these are deliberately _debug_ assertions because the consequence of failing the assertion is that compilation is slow, not corrupt. If we made these hard assertions, I'm sure there are obscure scenarios people will run into where the compiler would ICE instead of continuing on compilation, just a bit slower. I'd like to know about those, but I do not think serving up an ICE is worth it.

With the assertions in place, I just added logic around all the places they were hit, to skip over trying to analyze the bodies of trivial consts.

In the future, I'd like to see this work extended by:
* Pushing detection of trivial consts before MIR building
* Including DefKind::Static and DefKind::InlineConst
* Including consts like `_1 = const 0_usize; _0 = &_1`, which would make a lot of promoteds into trivial consts
* Handling less-trivial consts like `const A: usize = B`, which have `Operand::Constant(Const::Unevaluated)`
2025-10-27 11:02:41 +00:00
Ben Kimock 775da711c6 Add a fast path for lowering trivial consts 2025-10-25 16:59:53 -04:00
Camille Gillot 5dfbf67f94 Replace NullOp::SizeOf and NullOp::AlignOf by lang items. 2025-10-23 00:38:28 +00:00
Cameron Steffen b323f567d9 Remove Option from impl_trait_header 2025-10-17 08:36:34 -05:00
yukang 1654cce210 prefer to use repeat_n over repeat and take 2025-10-09 01:24:55 +08:00
Tawan Muadmuenwai 6912631d3e Add span for struct tail recursion limit error 2025-09-16 23:04:59 +07:00
Stuart Cook e011dd47ee Rollup merge of #144885 - zachs18:ptr_guaranteed_cmp_more, r=RalfJung
Implement some more checks in `ptr_guaranteed_cmp`.

* Pointers with different residues modulo their allocations' least common alignment are never equal.
* Pointers to the same static allocation are equal if and only if they have the same offset.
* Pointers to different non-zero-sized static allocations are unequal if both point within their allocation, and not on opposite ends.

Tracking issue for `const_raw_ptr_comparison`: <https://github.com/rust-lang/rust/issues/53020>

This should not affect `is_null`, the only usage of this intrinsic on stable.

Closes https://github.com/rust-lang/rust/issues/144584
2025-08-26 14:19:16 +10:00
Zachary S 10fde9eafe Implement some more checks for ptr_guaranteed_cmp in consteval:
Pointers with different residues modulo their least common allocation alignment are never equal.
Pointers to the same static allocation are equal if and only if they have the same offset.
Strictly in-bounds (in-bounds and not one-past-the-end) pointers to different static allocations are always unequal.
A pointer cannot be equal to an integer if `ptr-int` cannot be null.

Also adds more tests for `ptr_guaranteed_cmp`.

Co-authored-by: Ralf Jung <post@ralfj.de>
2025-08-23 12:09:07 -05:00
bors 99ba556567 Auto merge of #144081 - RalfJung:const-ptr-fragments, r=oli-obk
const-eval: full support for pointer fragments

This fixes https://github.com/rust-lang/const-eval/issues/72 and makes `swap_nonoverlapping` fully work in const-eval by enhancing per-byte provenance tracking with tracking of *which* of the bytes of the pointer this one is. Later, if we see all the same bytes in the exact same order, we can treat it like a whole pointer again without ever risking a leak of the data bytes (that encode the offset into the allocation). This lifts the limitation that was discussed quite a bit in https://github.com/rust-lang/rust/pull/137280.

For a concrete piece of code that used to fail and now works properly consider this example doing a byte-for-byte memcpy in const without using intrinsics:
```rust
use std::{mem::{self, MaybeUninit}, ptr};

type Byte = MaybeUninit<u8>;

const unsafe fn memcpy(dst: *mut Byte, src: *const Byte, n: usize) {
    let mut i = 0;
    while i < n {
        *dst.add(i) = *src.add(i);
        i += 1;
    }
}

const _MEMCPY: () = unsafe {
    let ptr = &42;
    let mut ptr2 = ptr::null::<i32>();
    // Copy from ptr to ptr2.
    memcpy(&mut ptr2 as *mut _ as *mut _, &ptr as *const _ as *const _, mem::size_of::<&i32>());
    assert!(*ptr2 == 42);
};
```
What makes this code tricky is that pointers are "opaque blobs" in const-eval, we cannot just let people look at the individual bytes since *we don't know what those bytes look like* -- that depends on the absolute address the pointed-to object will be placed at. The code above "breaks apart" a pointer into individual bytes, and then puts them back together in the same order elsewhere. This PR implements the logic to properly track how those individual bytes relate to the original pointer, and to recognize when they are in the right order again.

We still reject constants where the final value contains a not-fully-put-together pointer: I have no idea how one could construct an LLVM global where one byte is defined as "the 3rd byte of a pointer to that other global over there" -- and even if LLVM supports this somehow, we can leave implementing that to a future PR. It seems unlikely to me anyone would even want this, but who knows.^^

This also changes the behavior of Miri, by tracking the order of bytes with provenance and only considering a pointer to have valid provenance if all bytes are in the original order again. This is related to https://github.com/rust-lang/unsafe-code-guidelines/issues/558. It means one cannot implement XOR linked lists with strict provenance any more, which is however only of theoretical interest. Practically I am curious if anyone will show up with any code that Miri now complains about - that would be interesting data. Cc `@rust-lang/opsem`
2025-08-17 04:33:31 +00:00
Mara Bos 08acba3071 Revert "Partially outline code inside the panic! macro".
Without any tests/benchmarks that show some improvement, it's hard to
know whether the change had any positive effect at all. (And if it did,
whether that effect is still achieved today.)
2025-08-12 12:52:39 +02:00
Ralf Jung ba5b6b9ec4 const-eval: full support for pointer fragments 2025-07-30 08:13:58 +02:00
Camille GILLOT 0460c92d52 Remove useless lifetime parameter. 2025-07-23 23:54:37 +00:00
Camille GILLOT 9ff071219b Give an AllocId to ConstValue::Slice. 2025-07-23 23:54:37 +00:00
Ralf Jung 3f9be406a6 fix handling of base address for TypeId allocations 2025-07-20 22:14:27 +02:00
Oli Scherer 652ba279ec Show the memory of uninit reads 2025-07-18 07:47:08 +00:00
Deadbeef 69326878ee parse const trait Trait 2025-07-17 18:06:26 +08:00
Ralf Jung 0bf0860a0e simplfy memory kind handling during interning 2025-07-16 15:29:52 +02:00
Ralf Jung 8f854d9cb2 const heap: fix ICE on forgotten make_global 2025-07-16 15:29:52 +02:00
Deadbeef fd48b7b8dd Comment more code and make tests clearer
Co-Authored-By: Ralf Jung <post@ralfj.de>
2025-07-16 00:50:20 +08:00
Deadbeef 44b38ca45e format pointer later instead of eagerly converting to string 2025-07-16 00:32:12 +08:00
Deadbeef 3f2dc2bd1a add const_make_global; err for const_allocate ptrs if didn't call
Co-Authored-By: Ralf Jung <post@ralfj.de>
Co-Authored-By: Oli Scherer <github333195615777966@oli-obk.de>
2025-07-16 00:32:12 +08:00
Matthias Krüger 42b105eb21 Rollup merge of #143584 - fee1-dead-contrib:push-skswvrwsrmll, r=RalfJung
make `Machine::load_mir` infallible

it doesn't need to return an `InterpResult`.
2025-07-07 19:55:36 +02:00
Deadbeef be6cd11d1b make Machine::load_mir infallible
it doesn't need to return an `InterpResult`.
2025-07-07 19:57:04 +08:00
Ralf Jung 7775166528 interpret: rename StackPopCleanup 2025-07-06 16:07:35 +02:00
Michael Goulet 8eb9f70979 Stop using Key trait randomly 2025-07-05 18:37:11 +00:00
Ralf Jung 8362508989 miri: improve errors for type validity assertion failures 2025-07-02 17:47:46 +02:00
Matthias Krüger 8292936d74 Rollup merge of #143140 - RalfJung:ptr-into-parts, r=oli-obk
give Pointer::into_parts a more scary name and offer a safer alternative

`into_parts` is a bit too innocent of a name for a somewhat subtle operation.
r? `@oli-obk`
2025-06-30 20:49:41 +02:00
Oli Scherer d37a04d09d Remove the nullary intrinsic const eval logic and treat them like other intrinsics 2025-06-30 08:04:40 +00:00
Ralf Jung 58dce8ca86 give Pointer::into_parts a more scary name and offer a safer alternative 2025-06-29 00:16:19 +02:00
bors b63223c152 Auto merge of #141759 - 1c3t3a:discriminants-query, r=saethlin
Insert checks for enum discriminants when debug assertions are enabled

Similar to the existing null-pointer and alignment checks, this checks for valid enum discriminants on creation of enums through unsafe transmutes. Essentially this sanitizes patterns like the following:
```rust
let val: MyEnum = unsafe { std::mem::transmute<u32, MyEnum>(42) };
```

An extension of this check will be done in a follow-up that explicitly sanitizes for extern enum values that come into Rust from e.g. C/C++.

This check is similar to Miri's capabilities of checking for valid construction of enum values.

This PR is inspired by saethlin@'s PR
https://github.com/rust-lang/rust/pull/104862. Thank you so much for keeping this code up and the detailed comments!

I also pair-programmed large parts of this together with vabr-g@.

r? `@saethlin`
2025-06-28 10:25:00 +00:00
Matthias Krüger 994ed31a96 Rollup merge of #143096 - RalfJung:tag_for_variant, r=compiler-errors
tag_for_variant: properly pass TypingEnv

Hard-coding `fully_monomorphized` here does not seem right...

This came up [on Zulip](https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20VariantId.3DDiscriminant.20when.20tag.20is.20niche.20encoded.3F/with/526103956).
2025-06-27 22:13:06 +02:00
Ralf Jung 5af79242ac tag_for_variant: properly pass TypingEnv 2025-06-27 17:04:33 +02:00
Guillaume Gomez 0bbeeffe57 Rollup merge of #143084 - RalfJung:const-eval-recursive-static-write, r=oli-obk
const-eval: error when initializing a static writes to that static

Fixes https://github.com/rust-lang/rust/issues/142404 by also calling the relevant hook for writes, not just reads. To avoid erroring during the actual write of the initial value, we neuter the hook when popping the final stack frame.

Calling the hook during writes requires changing its signature since we cannot pass in the entire interpreter any more.

While doing this I also realized a gap in https://github.com/rust-lang/rust/pull/142575 for zero-sized copies on the read side, so I fixed that and added a test.

r? `@oli-obk`
2025-06-27 15:04:57 +02:00
Ralf Jung ed4f01ed2e const-eval: error when initializing a static writes to that static 2025-06-27 14:39:35 +02:00
Stypox 708dc15cf1 Add InterpCx::layout_of with tracing, shadowing LayoutOf 2025-06-27 11:49:22 +02:00
Bastian Kersting 1087042e22 Insert checks for enum discriminants when debug assertions are enabled
Similar to the existing nullpointer and alignment checks, this checks
for valid enum discriminants on creation of enums through unsafe
transmutes. Essentially this sanitizes patterns like the following:
```rust
let val: MyEnum = unsafe { std::mem::transmute<u32, MyEnum>(42) };
```
An extension of this check will be done in a follow-up that explicitly
sanitizes for extern enum values that come into Rust from e.g. C/C++.

This check is similar to Miri's capabilities of checking for valid
construction of enum values.

This PR is inspired by saethlin@'s PR
https://github.com/rust-lang/rust/pull/104862. Thank you so much for
keeping this code up and the detailed comments!

I also pair-programmed large parts of this together with vabr-g@.
2025-06-27 09:37:36 +00:00
Ralf Jung 492526548d const-eval: allow constants to refer to mutable/external memory, but reject such constants as patterns 2025-06-26 18:09:47 +02:00
Ralf Jung 17946c22b1 const-eval error: always say in which item the error occurred
also adjust the wording a little so that we don't say "the error occurred here" for two different spans
2025-06-07 13:42:30 +02:00
Guillaume Gomez 3a6f1b0375 Rollup merge of #142103 - scottmcm:fieldidx-in-interp, r=oli-obk
Update `InterpCx::project_field` to take `FieldIdx`

As suggested by Ralf in https://github.com/rust-lang/rust/pull/142005#discussion_r2125839015
2025-06-06 23:53:18 +02:00
Scott McMurray 8bce2255e8 Update InterpCx::project_field to take FieldIdx
As suggested by Ralf in 142005.
2025-06-05 19:15:56 -07:00
Matthias Krüger c1d1f7a16f Rollup merge of #142012 - oli-obk:no-optional-spans, r=fee1-dead
Replace some `Option<Span>` with `Span` and use DUMMY_SP instead of None

Turns out many locations actually have a span available that we could use, so I used it
2025-06-06 00:58:44 +02:00
Oli Scherer fd3da4bebd Replace some Option<Span> with Span and use DUMMY_SP instead of None 2025-06-05 14:14:59 +00:00
Oli Scherer 64172481da Report the actual item that evaluation failed for 2025-06-04 15:13:25 +00:00