about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
AgeCommit message (Collapse)AuthorLines
2024-07-15Rollup merge of #124921 - RalfJung:offset-from-same-addr, r=oli-obkMatthias Krüger-15/+18
offset_from: always allow pointers to point to the same address This PR implements the last remaining part of the t-opsem consensus in https://github.com/rust-lang/unsafe-code-guidelines/issues/472: always permits offset_from when both pointers have the same address, no matter how they are computed. This is required to achieve *provenance monotonicity*. Tracking issue: https://github.com/rust-lang/rust/issues/117945 ### What is provenance monotonicity and why does it matter? Provenance monotonicity is the property that adding arbitrary provenance to any no-provenance pointer must never make the program UB. More specifically, in the program state, data in memory is stored as a sequence of [abstract bytes](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#abstract-byte), where each byte can optionally carry provenance. When a pointer is stored in memory, all of the bytes it is stored in carry that provenance. Provenance monotonicity means: if we take some byte that does not have provenance, and give it some arbitrary provenance, then that cannot change program behavior or introduce UB into a UB-free program. We care about provenance monotonicity because we want to allow the optimizer to remove provenance-stripping operations. Removing a provenance-stripping operation effectively means the program after the optimization has provenance where the program before the optimization did not -- since the provenance removal does not happen in the optimized program. IOW, the compiler transformation added provenance to previously provenance-free bytes. This is exactly what provenance monotonicity lets us do. We care about removing provenance-stripping operations because `*ptr = *ptr` is, in general, (likely) a provenance-stripping operation. Specifically, consider `ptr: *mut usize` (or any integer type), and imagine the data at `*ptr` is actually a pointer (i.e., we are type-punning between pointers and integers). Then `*ptr` on the right-hand side evaluates to the data in memory *without* any provenance (because [integers do not have provenance](https://rust-lang.github.io/rfcs/3559-rust-has-provenance.html#integers-do-not-have-provenance)). Storing that back to `*ptr` means that the abstract bytes `ptr` points to are the same as before, except their provenance is now gone. This makes `*ptr = *ptr` a provenance-stripping operation (Here we assume `*ptr` is fully initialized. If it is not initialized, evaluating `*ptr` to a value is UB, so removing `*ptr = *ptr` is trivially correct.) ### What does `offset_from` have to do with provenance monotonicity? With `ptr = without_provenance(N)`, `ptr.offset_from(ptr)` is always well-defined and returns 0. By provenance monotonicity, I can now add provenance to the two arguments of `offset_from` and it must still be well-defined. Crucially, I can add *different* provenance to the two arguments, and it must still be well-defined. In other words, this must always be allowed: `ptr1.with_addr(N).offset_from(ptr2.with_addr(N))` (and it returns 0). But the current spec for `offset_from` says that the two pointers must either both be derived from an integer or both be derived from the same allocation, which is not in general true for arbitrary `ptr1`, `ptr2`. To obtain provenance monotonicity, this PR hence changes the spec for offset_from to say that if both pointers have the same address, the function is always well-defined. ### What further consequences does this have? It means the compiler can no longer transform `end2 = begin.offset(end.offset_from(begin))` into `end2 = end`. However, it can still be transformed into `end2 = begin.with_addr(end.addr())`, which later parts of the backend (when provenance has been erased) can trivially turn into `end2 = end`. The only alternative I am aware of is a fundamentally different handling of zero-sized accesses, where a "no provenance" pointer is not allowed to do zero-sized accesses and instead we have a special provenance that indicates "may be used for zero-sized accesses (and nothing else)". `offset` and `offset_from` would then always be UB on a "no provenance" pointer, and permit zero-sized offsets on a "zero-sized provenance" pointer. This achieves provenance monotonicity. That is, however, a breaking change as it contradicts what we landed in https://github.com/rust-lang/rust/pull/117329. It's also a whole bunch of extra UB, which doesn't seem worth it just to achieve that transformation. ### What about the backend? LLVM currently doesn't have an intrinsic for pointer difference, so we anyway cast to integer and subtract there. That's never UB so it is compatible with any relaxation we may want to apply. If LLVM gets a `ptrsub` in the future, then plausibly it will be consistent with `ptradd` and [consider two equal pointers to be inbounds](https://github.com/rust-lang/rust/pull/124921#issuecomment-2205795829).
2024-07-14Add cache for `allocate_str`Adwin White-1/+13
2024-07-08Move trait selection error reporting to its own top-level moduleMichael Goulet-1/+1
2024-07-08Auto merge of #113128 - WaffleLapkin:become_trully_unuwuable, r=oli-obk,RalfJungbors-83/+262
Support tail calls in mir via `TerminatorKind::TailCall` This is one of the interesting bits in tail call implementation — MIR support. This adds a new `TerminatorKind` which represents a tail call: ```rust TailCall { func: Operand<'tcx>, args: Vec<Operand<'tcx>>, fn_span: Span, }, ``` *Structurally* this is very similar to a normal `Call` but is missing a few fields: - `destination` — tail calls don't write to destination, instead they pass caller's destination to the callee (such that eventual `return` will write to the caller of the function that used tail call) - `target` — similarly to `destination` tail calls pass the caller's return address to the callee, so there is nothing to do - `unwind` — I _think_ this is applicable too, although it's a bit confusing - `call_source` — `become` forbids operators and is not created as a lowering of something else; tail calls always come from HIR (at least for now) It might be helpful to read the interpreter implementation to understand what `TailCall` means exactly, although I've tried documenting it too. ----- There are a few `FIXME`-questions still left, ideally we'd be able to answer them during review ':) ----- r? `@oli-obk` cc `@scottmcm` `@DrMeepster` `@JakobDegen`
2024-07-07Fixup conflict with r-l/r/126567Maybe Lapkin-1/+1
2024-07-07add an assertion that machine hook doesn't return NoCleanupMaybe Lapkin-3/+5
2024-07-07Do renames proposed by reviewMaybe Waffle-9/+9
2024-07-07make `StackPop` field names less confusingMaybe Waffle-27/+35
2024-07-07doc fixups from reviewMaybe Waffle-8/+6
2024-07-07add miri tests and a fixmeMaybe Waffle-0/+4
2024-07-07Refactor & fixup interpreter implementation of tail callsMaybe Waffle-70/+162
2024-07-07Refactor common part of evaluating `Call`&`TailCall` in the interpreterMaybe Waffle-63/+56
2024-07-07Support tail calls in the interpreterMaybe Waffle-1/+71
2024-07-07Support tail calls in mir via `TerminatorKind::TailCall`Maybe Waffle-3/+15
2024-07-06offset_from intrinsic: always allow pointers to point to the same addressRalf Jung-15/+18
2024-07-06Rollup merge of #127275 - RalfJung:offset-from-isize-min, r=AmanieuMatthias Krüger-2/+2
offset_from, offset: clearly separate safety requirements the user needs to prove from corollaries that automatically follow By landing https://github.com/rust-lang/rust/pull/116675 we decided that objects larger than `isize::MAX` cannot exist in the address space of a Rust program, which lets us simplify these rules. For `offset_from`, we can even state that the *absolute* distance fits into an `isize`, and therefore exclude `isize::MIN`. This PR also changes Miri to treat an `isize::MIN` difference like the other isize-overflowing cases.
2024-07-04Auto merge of #123781 - RalfJung:miri-fn-identity, r=oli-obkbors-7/+9
Miri function identity hack: account for possible inlining Having a non-lifetime generic is not the only reason a function can be duplicated. Another possibility is that the function may be eligible for cross-crate inlining. So also take into account the inlining attribute in this Miri hack for function pointer identity. That said, `cross_crate_inlinable` will still sometimes return true even for `inline(never)` functions: - when they are `DefKind::Ctor(..) | DefKind::Closure` -- I assume those cannot be `InlineAttr::Never` anyway? - when `cross_crate_inline_threshold == InliningThreshold::Always` so maybe this is still not quite the right criterion to use for function pointer identity.
2024-07-04offset_from: "the difference must fit in an isize" is a corollaryRalf Jung-2/+2
also, isize::MIN is an impossible distance
2024-07-03Auto merge of #125507 - compiler-errors:type-length-limit, r=lcnrbors-5/+6
Re-implement a type-size based limit r? lcnr This PR reintroduces the type length limit added in #37789, which was accidentally made practically useless by the caching changes to `Ty::walk` in #72412, which caused the `walk` function to no longer walk over identical elements. Hitting this length limit is not fatal unless we are in codegen -- so it shouldn't affect passes like the mir inliner which creates potentially very large types (which we observed, for example, when the new trait solver compiles `itertools` in `--release` mode). This also increases the type length limit from `1048576 == 2 ** 20` to `2 ** 24`, which covers all of the code that can be reached with craterbot-check. Individual crates can increase the length limit further if desired. Perf regression is mild and I think we should accept it -- reinstating this limit is important for the new trait solver and to make sure we don't accidentally hit more type-size related regressions in the future. Fixes #125460
2024-07-02Instance::resolve -> Instance::try_resolve, and other nitsMichael Goulet-2/+2
2024-07-02Fix spansMichael Goulet-1/+2
2024-07-02Give Instance::expect_resolve a spanMichael Goulet-0/+1
2024-07-02Miscellaneous renamingMichael Goulet-3/+2
2024-07-02Miri function identity hack: account for possible inliningRalf Jung-7/+9
2024-07-02chore: remove duplicate wordshattizai-1/+1
2024-06-29Auto merge of #120639 - fee1-dead-contrib:new-effects-desugaring, r=oli-obkbors-4/+1
Implement new effects desugaring cc `@rust-lang/project-const-traits.` Will write down notes once I have finished. * [x] See if we want `T: Tr` to desugar into `T: Tr, T::Effects: Compat<true>` * [x] Fix ICEs on `type Assoc: ~const Tr` and `type Assoc<T: ~const Tr>` * [ ] add types and traits to minicore test * [ ] update rustc-dev-guide Fixes #119717 Fixes #123664 Fixes #124857 Fixes #126148
2024-06-28implement new effects desugaringDeadbeef-4/+1
2024-06-27Enable const casting for `f16` and `f128`Trevor Gross-10/+17
2024-06-22don't ICE when encountering an extern type field during validationRalf Jung-41/+61
2024-06-21Rollup merge of #126811 - compiler-errors:tidy-ftl, r=estebankJubilee-2/+1
Add a tidy rule to check that fluent messages and attrs don't end in `.` This adds a new dependency on `fluent-parse` to `tidy` -- we already rely on it in rustc so I feel like it's not that big of a deal. This PR also adjusts many error messages that currently end in `.`; not all of them since I added an `ALLOWLIST`, excluded `rustc_codegen_*` ftl files, and `.teach_note` attributes. r? ``@estebank`` ``@oli-obk``
2024-06-21Rollup merge of #126787 - Strophox:get-bytes, r=RalfJungJubilee-0/+17
Add direct accessors for memory addresses in `Machine` (for Miri) The purpose of this PR is to enable direct (immutable) access to memory addresses in `Machine`, which will be needed for further extension of Miri. This is done by adding (/completing missings pairs of) accessor functions, with the relevant signatures as follows: ```rust /* rust/compiler/rustc_middle/src/mir/interpret/allocation.rs */ pub trait AllocBytes { // .. fn as_ptr(&self) -> *const u8; /*fn as_mut_ptr(&mut self) -> *mut u8; -- Already in the compiler*/ } impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> { // .. pub fn get_bytes_unchecked_raw(&self) -> *const u8; /*pub fn get_bytes_unchecked_raw_mut(&mut self) -> *mut u8; -- Already in the compiler*/ } ``` ```rust /* rust/compiler/rustc_const_eval/src/interpret/memory.rs */ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // .. pub fn get_alloc_bytes_unchecked_raw(&self, id: AllocId) -> InterpResult<'tcx, *const u8>; pub fn get_alloc_bytes_unchecked_raw_mut(&mut self, id: AllocId) -> InterpResult<'tcx, *mut u8>; } ``` r? ``@RalfJung``
2024-06-21Fix remaining casesMichael Goulet-2/+1
2024-06-21Auto merge of #125853 - tesuji:promote-fail-fast, r=cjgillotbors-6/+6
promote_consts: some clean-up after experimenting This is some clean-up after experimenting in #125916, Prefer to review commit-by-commit.
2024-06-21interpret: use trace to reduce noiceLzu Tao-6/+6
2024-06-21add as_ptr to trait AllocBytes, fix 2 impls; add pub fn ↵Strophox-0/+17
get_bytes_unchecked_raw in allocation.rs; add pub fn get_alloc_bytes_unchecked_raw[_mut] in memory.rs
2024-06-20More GVN for PtrMetadataScott McMurray-1/+1
`PtrMetadata` doesn't care about `*const`/`*mut`/`&`/`&mut`, so GVN away those casts in its argument. This includes updating MIR to allow calling PtrMetadata on references too, not just raw pointers. That means that `[T]::len` can be just `_0 = PtrMetadata(_1)`, for example. # Conflicts: # tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir # tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
2024-06-19`bug!` more uses of these in runtime stuffScott McMurray-3/+1
2024-06-19Rollup merge of #126154 - RalfJung:storage-live, r=compiler-errorsLeón Orell Valerian Liehr-7/+3
StorageLive: refresh storage (instead of UB) when local is already live Blocked on [this FCP](https://github.com/rust-lang/rust/issues/99160#issuecomment-2155924538), which also contains the motivation. Fixes https://github.com/rust-lang/rust/issues/99160 Fixes https://github.com/rust-lang/rust/issues/98896 (by declaring it not-a-bug) Fixes https://github.com/rust-lang/rust/issues/119366 Fixes https://github.com/rust-lang/unsafe-code-guidelines/issues/129
2024-06-19Rollup merge of #126493 - jswrenn:fix-126460, r=compiler-errors许杰友 Jieyou Xu (Joe)-1/+10
safe transmute: support non-ZST, variantful, uninhabited enums Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in #126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by ````@RalfJung```` in his review of #126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes #126460 r? ````@compiler-errors````
2024-06-18Remove redundant argument from `subdiagnostic` methodOli Scherer-1/+1
2024-06-18Use a dedicated type instead of a reference for the diagnostic contextOli Scherer-6/+6
This paves the way for tracking more state (e.g. error tainting) in the diagnostic context handle
2024-06-17Rollup merge of #126567 - compiler-errors:instance-kind, r=oli-obk,lcnrMatthias Krüger-28/+28
Rename `InstanceDef` -> `InstanceKind` Renames `InstanceDef` to `InstanceKind`. The `Def` here is confusing, and makes it hard to distinguish `Instance` and `InstanceDef`. `InstanceKind` makes this more obvious, since it's really just describing what *kind* of instance we have. Not sure if this is large enough to warrant a types team MCP -- it's only 53 files. I don't personally think it does, but happy to write one if anyone disagrees. cc ``@rust-lang/types`` r? types
2024-06-17Remove an unused validation error variantOli Scherer-6/+0
2024-06-16Rename InstanceDef -> InstanceKindMichael Goulet-28/+28
2024-06-15Auto merge of #126518 - matthiaskrgr:rollup-wb70rzq, r=matthiaskrgrbors-6/+15
Rollup of 9 pull requests Successful merges: - #125829 (rustc_span: Add conveniences for working with span formats) - #126361 (Unify intrinsics body handling in StableMIR) - #126417 (Add `f16` and `f128` inline ASM support for `x86` and `x86-64`) - #126424 ( Also sort `crt-static` in `--print target-features` output) - #126428 (Polish `std::path::absolute` documentation.) - #126429 (Add `f16` and `f128` const eval for binary and unary operationations) - #126448 (End support for Python 3.8 in tidy) - #126488 (Use `std::path::absolute` in bootstrap) - #126511 (.mailmap: Associate both my work and my private email with me) r? `@ghost` `@rustbot` modify labels: rollup
2024-06-15Rollup merge of #126429 - tgross35:f16-f128-const-eval, r=RalfJungMatthias Krüger-6/+15
Add `f16` and `f128` const eval for binary and unary operationations Add const evaluation and Miri support for f16 and f128, including unary and binary operations. Casts are not yet included. Fixes https://github.com/rust-lang/rust/issues/124583 r? ``@RalfJung``
2024-06-15Rollup merge of #126469 - RalfJung:mir-shifts, r=scottmcmMatthias Krüger-12/+7
MIR Shl/Shr: the offset can be computed with rem_euclid r? ````@scottmcm````
2024-06-14safe transmute: support non-ZST, variantful, uninhabited enumsJack Wrenn-1/+10
Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple inhabited variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in #126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited, non-ZST enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by RalfJung in his review of #126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes #126460
2024-06-14Use is_lang_item more aggressivelyMichael Goulet-7/+7
2024-06-14Make the unary operator `FloatTy` check exhaustiveTrevor Gross-6/+9
Add a spot that was missed in <https://github.com/rust-lang/rust/pull/121997>.