simd_fmin/fmax: make semantics and name consistent with scalar intrinsics
This is the SIMD version of https://github.com/rust-lang/rust/pull/153343: change the documented semantics of the SIMD float min/max intrinsics to that of the scalar intrinsics, and also make the name consistent. The overall semantic change this amounts to is that we restrict the non-determinism: the old semantics effectively mean "when one input is an SNaN, the result non-deterministically is a NaN or the other input"; the new semantics say that in this case the other input must be returned. For all other cases, old and new semantics are equivalent. This means all users of these intrinsics that were correct with the old semantics are still correct: the overall set of possible behaviors has become smaller, no new possible behaviors are being added.
In terms of providers of this API:
- Miri, GCC, and cranelift already implement the new semantics, so no changes are needed.
- LLVM is adjusted to use `minimumnum nsz` instead of `minnum`, thus giving us the new semantics.
In terms of consumers of this API:
- Portable SIMD almost certainly wants to match the scalar behavior, so this is strictly a bugfix here.
- Stdarch mostly stopped using the intrinsic, except on nvptx, where arguably the new semantics are closer to what we actually want than the old semantics (https://github.com/rust-lang/stdarch/issues/2056).
Q: Should there be an `f` in the intrinsic name to indicate that it is for floats? E.g., `simd_fminimum_number_nsz`?
Also see https://github.com/rust-lang/rust/issues/153395.
Merge `fabsf16/32/64/128` into `fabs::<F>`
Following [a small conversation on Zulip](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Float.20intrinsics/with/521501401) (and because I'd be interested in starting to contribute on Rust), I thought I'd give a try at merging the float intrinsics :)
This PR just merges `fabsf16`, `fabsf32`, `fabsf64`, `fabsf128`, as it felt like an easy first target.
Notes:
- I'm opening the PR for one intrinsic as it's probably easier if the shift is done one intrinsic at a time, but let me know if you'd rather I do several at a time to reduce the number of PRs.
- Currently this PR increases LOCs, despite being an attempt at simplifying the intrinsics/compilers. I believe this increase is a one time thing as I had to define new functions and move some things around, and hopefully future PRs/commits will reduce overall LoCs
- `fabsf32` and `fabsf64` are `#[rustc_intrinsic_const_stable_indirect]`, while `fabsf16` and `fabsf128` aren't; because `f32`/`f64` expect the function to be const, the generic version must be made indirectly stable too. We'd need to check with T-lang this change is ok; the only other intrinsics where there is such a mismatch is `minnum`, `maxnum` and `copysign`.
- I haven't touched libm because I'm not familiar with how it works; any guidance would be welcome!
interpreter error reporting: remove arguments that are always the same
This `report` function is called twice and both callers use the same `span` and `get_span_and_frames`... so let's just fix those arguments inside the function, no need to be more generic than this.
miri recursive validation: only check one layer deep
As has been proposed in https://github.com/rust-lang/unsafe-code-guidelines/issues/414, let's see what happens if we make recursive checking in Miri shallow: we treat whatever is behind a reference as if it was inside `MaybeDangling`, which means nested references do not have to be dereferenceable.
This changes the meaning of the original flag -- I don't think it is worth supporting multiple variants of recursive checking (it'd require a bunch of new plumbing), and this seems to be the strictest variant that still has any traction in the discussion.
interpret: when passing an argument fails, point at that argument
For a long time now, we did some contortions so that when something goes wrong while initializing the arguments for a function, we point at the call site rather than the callee. Historically, this had to be done because the "current location" in the callee pointed at the first instruction, which would obviously be nonsense. A while ago we gained the ability in the interpreter for the "current location" to be just a span that we point at for errors, but we never reevaluated the decision for how spans are handled during function calls. (We did use this "just a span" location for [errors during the initial stack frame setup](https://github.com/rust-lang/rust/commit/d21e0118d0eefc8b0073fa47fa16699d37047abf), but not for argument initialization.)
There's no always-great choice for pointing at the caller vs the callee: when they disagree about the type of an argument, either side could be wrong. If We do *two* typed copies in that case, one at the caller type and one at the callee type. Arguably we should point at the one that goes wrong, but we don't have a good way to expose that.
What ultimately pushed me over the edge towards pointing at the callee are two points:
- This provides strictly more information. if we point at the callee, the caller is available in the stacktrace. But if we point at the caller, then it might be impossible to figure out the actual callee if a function pointer or dyn call is involved.
- As part of resolving some long-standing questions around retags I am moving retagging to become part of validation, which means the retag and protector initialization of function arguments will happen during argument initialization. These currently point at the argument inside the callee, which I think is strictly preferable for these errors.
The diff will be much smaller with whitespace changes hidden.
const validity checking: do not recurse to references inside MaybeDangling
This arguably should be allowed, but we currently reject it:
```rust
#![feature(maybe_dangling)]
use std::mem::MaybeDangling;
const X: MaybeDangling<&bool> = unsafe { std::mem::transmute(&5u8) };
```
r? @WaffleLapkin
Simplify find_attr! for HirId usage
Add a `HasAttrs<'tcx, Tcx>` trait to `rustc_hir` that allows `find_attr!` to accept `DefId`, `LocalDefId`, `OwnerId`, and `HirId` directly, instead of requiring callers to manually fetch the attribute slice first.
Before:
`find_attr!(tcx.hir_attrs(hir_id), SomeAttr)`
After:
`find_attr!(tcx, hir_id, SomeAttr)`
The trait is defined in `rustc_hir` with a generic `Tcx` parameter to avoid a dependency cycle (`rustc_hir` cannot depend on `rustc_middle`). The four concrete impls for `TyCtxt` are in `rustc_middle`.
Fixes https://github.com/rust-lang/rust/issues/153103
Add a HasAttrs<'tcx, Tcx> trait to rustc_hir that allows find_attr! to
accept DefId, LocalDefId, OwnerId, and HirId directly, instead of
requiring callers to manually fetch the attribute slice first.
The trait is defined in rustc_hir with a generic Tcx parameter to avoid
a dependency cycle (rustc_hir cannot depend on rustc_middle). The four
concrete impls for TyCtxt are in rustc_middle.
interpret: go back to regular string interpolation for error messages
Using the translatable diagnostic infrastructure adds a whole lot of boilerplate which isn't actually useful for const-eval errors, so let's get rid of it. This effectively reverts https://github.com/rust-lang/rust/pull/111677. That PR effectively added 1000 lines and this PR only removes around 600 -- the difference is caused by (a) keeping some of the types around for validation, where we can use them to share error strings and to trigger the extra help for pointer byte shenanigans during CTFE, and (b) this not being a full revert of rust-lang/rust#111677; I am not touching diagnostics outside the interpreter such as all the const-checking code which also got converted to fluent in the same PR.
The last commit does something similar for `LayoutError`, which also helps deduplicate a bunch of error strings. I can make that into a separate PR if you prefer.
r? @oli-obk
Fixes https://github.com/rust-lang/rust/issues/113117
Fixes https://github.com/rust-lang/rust/issues/116764
Fixes https://github.com/rust-lang/rust/issues/112618
miri: make read_discriminant UB when the tag is not in the validity range of the tag field
Arguably, reading an enum discriminant is an operation that uses the "type" of the discriminant field -- and therefore it should fail when the value in that field isn't valid at that type. Therefore, code like this should be UB:
```rust
fn main() {
unsafe {
let x = 12u8;
let x_ptr: *const u8 = &x;
let cast_ptr = x_ptr as *const Option<bool>;
// Reading the discriminant should fail since the tag value is not in the valid
// range for the tag field.
let _val = matches!(*cast_ptr, None);
//~^ ERROR: invalid tag
}
}
```
However, Miri currently sees no UB here. (MiniRust does see UB.) This is because we never actually check whether the tag we read is in the validity range for its field. So let's add such a check, and a corresponding test.
In fact, we have to do this check, since the codegen backend adds range metadata on the discriminant load, as can be seen in [this example](https://play.rust-lang.org/?version=stable&mode=release&edition=2024&gist=02ef5e80fdfe61540e44198dd827b630). In other words, the above code has UB in LLVM IR but not in Miri, which is a critical Miri bug.
Move `Spanned`.
It's defined in `rustc_span::source_map` which doesn't make any sense because it has nothing to do with source maps. This commit moves it to the crate root, a more sensible spot for something this basic.
r? @JonathanBrouwer
It's defined in `rustc_span::source_map` which doesn't make any sense
because it has nothing to do with source maps. This commit moves it to
the crate root, a more sensible spot for something this basic.
fix ICE in `const_c_variadic` when passing ZSTs
fixes https://github.com/rust-lang/rust/issues/153351
r? RalfJung
There was a mismatch between the caller and callee ABI where the caller does not pass ZST arguments, but the callee does expect them. Because ZSTs don't implement `VaArgSafe` the program must already be invalid if this comes up.
Overhaul `ensure_ok`
The interaction of `ensure_ok` and the `return_result_from_ensure_ok` query modifier is weird and hacky. This PR cleans it up. Details in the individual commits.
r? @Zalathar
`ensure_ok` provides a special, more efficient way of calling a query
when its return value isn't needed. But there is a complication: if the
query is marked with the `return_result_from_ensure_ok` modifier, then
it will return `Result<(), ErrorGuaranteed`. This is clunky and feels
tacked on. It's annoying to have to add a modifier to a query to declare
information present in its return type, and it's confusing that queries
called via `ensure_ok` have different return types depending on the
modifier.
This commit:
- Eliminates the `return_result_from_ensure_ok` modifier. The proc macro
now looks at the return type and detects if it matches `Result<_,
ErrorGuarantee>`. If so, it adds the modifier
`returns_error_guaranteed`. (Aside: We need better terminology to
distinguish modifiers written by the user in a `query` declaration
(e.g. `cycle_delayed_bug`) from modifiers added by the proc macro
(e.g. `cycle_error_handling`.))
- Introduces `ensure_result`, which replaces the use of `ensure_ok` for
queries that return `Result<_, ErrorGuarantee>`. As a result,
`ensure_ok` can now only be used for the "ignore the return value"
case.
Clean up the eager formatting API
For https://github.com/rust-lang/rust/issues/151366#event-22181360642
Previously eager formatting worked by throwing the arguments into a diag, formatting, then removing the args again. This is ugly so instead we now just do the formatting completely separately.
This PR has nice commits, so I recommend reviewing commit by commit.
r? @GuillaumeGomez
Box in `ValTreeKind::Branch(Box<[I::Const]>)` changed to `List`
This is related to trait system refactoring. It fixes the FIXME in `ValTreeKind`
```
// FIXME(mgca): Use a `List` here instead of a boxed slice
Branch(Box<[I::Const]>),
```
It introduces `Interner::Consts`, changes `Branch(Box<[I::Const]>)` to `Branch(I::Consts)`, and updates all relevant places.
r? lcnr
`fn_abi_of_instance` can look at function bodies to deduce codegen
optimization attributes (namely `ArgAttribute::ReadOnly` and
`ArgAttribute::CapturesNone`) of indirectly-passed parameters. This can
lead to cycles when performed during typeck, when such attributes are
irrelevant.
This patch breaks a subquery out from `fn_abi_of_instance`,
`fn_abi_of_instance_no_deduced_attrs`, which returns the ABI before such
parameter attributes are deduced; and that new subquery is used in CTFE
instead.
refactor(mgca): Change `DefKind::Const` and `DefKind::AssocConst` to have a `is_type_const` flag
Addresses rust-lang/rust#152940
- Changed `DefKind::Const` and `DefKind::AssocConst` to have a `is_type_const` flag.
- changed `is_type_const` query to check for this flag
- removed `is_rhs_type_const` query
r? @BoxyUwU
* refactor: add `is_type_const` flag to `DefKind::Const` and `AssocConst`
* refactor(cleanup) remove the `rhs_is_type_const` query
* style: fix formatting
* refactor: refactor stuff in librustdoc for new Const and AssocConst
* refactor: refactor clippy for the changes
* chore: formatting
* fix: fix test
* fix: fix suggestions
* Update context.rs
Co-authored-by: Boxy <rust@boxyuwu.dev>
* changed AssocKind::Const to store data about being a type const
add field representing types
*[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/152730)*
> [!NOTE]
> This is a rewrite of #146307 by using a lang item instead of a custom `TyKind`. We still need a `hir::TyKind::FieldOf` variant, because resolving the field name cannot be done before HIR construction. The advantage of doing it this way is that we don't need to make any changes to types after HIR (including symbol mangling). At the very beginning of this feature implementation, I tried to do it using a lang item, but then quickly abandoned the approach, because at that time I was still intending to support nested fields.
Here is a [range-diff](https://triagebot.infra.rust-lang.org/gh-range-diff/rust-lang/rust/605f49b27444a738ea4032cb77e3bdc4eb811bab..d15f5052095b3549111854a2555dd7026b0a729e/605f49b27444a738ea4032cb77e3bdc4eb811bab..f5f42d1e03495dbaa23671c46b15fccddeb3492f) between the two PRs
---
# Add Field Representing Types (FRTs)
This PR implements the first step of the field projection lang experiment (Tracking Issue: rust-lang/rust#145383). Field representing types (FRTs) are a new kind of type. They can be named through the use of the `field_of!` macro with the first argument being the type and the second the name of the field (or variant and field in the case of an enum). No nested fields are supported.
FRTs natively implement the `Field` trait that's also added in this PR. It exposes information about the field such as the type of the field, the type of the base (i.e. the type that contains the field) and the offset within that base type. Only fields of non-packed structs are supported, fields of enums an unions have unique types for each field, but those do not implement the `Field` trait.
This PR was created in collaboration with @dingxiangfei2009, it wouldn't have been possible without him, so huge thanks for mentoring me!
I updated my library solution for field projections to use the FRTs from `core` instead of creating my own using the hash of the name of the field. See the [Rust-for-Linux/field-projection `lang-experiment` branch](https://github.com/Rust-for-Linux/field-projection/tree/lang-experiment).
## API added to `core::field`
```rust
pub unsafe trait Field {
type Base;
type Type;
const OFFSET: usize;
}
pub macro field_of($Container:ty, $($fields:expr)+ $(,)?);
```
Along with a perma-unstable type that the compiler uses in the expansion of the macro:
```rust
#[unstable(feature = "field_representing_type_raw", issue = "none")]
pub struct FieldRepresentingType<T: ?Sized, const VARIANT: u32, const FIELD: u32> {
_phantom: PhantomData<T>,
}
```
## Explanation of Field Representing Types (FRTs)
FRTs are used for compile-time & trait-level reflection for fields of structs & tuples. Each struct & tuple has a unique compiler-generated type nameable through the `field_of!` macro. This type natively contains information about the field such as the outermost container, type of the field and its offset. Users may implement additional traits on these types in order to record custom information (for example a crate may define a [`PinnableField` trait](https://github.com/Rust-for-Linux/field-projection/blob/lang-experiment/src/marker.rs#L9-L23) that records whether the field is structurally pinned).
They are the foundation of field projections, a general operation that's generic over the fields of a struct. This genericism needs to be expressible in the trait system. FRTs make this possible, since an operation generic over fields can just be a function with a generic parameter `F: Field`.
> [!NOTE]
> The approach of field projections has changed considerably since this PR was opened. In the end we might not need FRTs, so this API is highly experimental.
FRTs should act as though they were defined as `struct MyStruct_my_field<StructGenerics>;` next to the struct. So it should be local to the crate defining the struct so that one can implement any trait for the FRT from that crate. The `Field` traits should be implemented by the compiler & populated with correct information (`unsafe` code needs to be able to rely on them being correct).
## TODOs
There are some `FIXME(FRTs)` scattered around the code:
- Diagnostics for `field_of!` can be improved
- `tests/ui/field_representing_types/nonexistent.rs`
- `tests/ui/field_representing_types/non-struct.rs`
- `tests/ui/field_representing_types/offset.rs`
- `tests/ui/field_representing_types/not-field-if-packed.rs`
- `tests/ui/field_representing_types/invalid.rs`
- Simple type alias already seem to work, but might need some extra work in `compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs`
r? @oli-obk