Fix ICE: When Trying to check visibility of a #[type_const], check RHS instead.
This PR fixes https://github.com/rust-lang/rust/issues/150956 for min_const_generic_args https://github.com/rust-lang/rust/issues/132980.
The first part of this PR checks in `reachable.rs` if we have a type const use `visit_const_item_rhs(init);` instead of calling `const_eval_poly_to_alloc()`
The second part is I noticed that if `const_eval_poly_to_alloc()` returns a `ErrorHandled::TooGeneric` then switches to `visit_const_item_rhs()`. So further up `const_eval_poly_to_alloc()` call order it eventual gets to `eval_in_interpreter()`. So I added a debug_assert in `eval_in_interpreter()` if we happen to try and run CTFE on a `type_const`.
The other bit is just a test case, and some duplicated code I noticed.
While the PR does get rid of the ICE for a type_const with `pub` visibility. If I try using the const though it will ICE with the following:
```
error: internal compiler error: /home/keith/GitHub/rust_kc/compiler/rustc_const_eval/src/check_consts/qualifs.rs:355:13: expected ConstKind::Param or ConstKind::Value here, found UnevaluatedConst { def: DefId(20:4 ~ colorkit[c783]::TYPE_CONST), args: [] }
thread 'rustc' (819687) panicked at /home/keith/GitHub/rust_kc/compiler/rustc_const_eval/src/check_consts/qualifs.rs:355:13:
```
I suspect it is a similar issue to inherent associated consts. Since if I apply the same fix I had here:
https://github.com/rust-lang/rust/pull/150799#discussion_r2676504639
I then can use the const internally and in external crates without any issues.
Although, did not include that fix since if it is a similar issue it would need to be addressed elsewhere.
r? @BoxyUwU
@rustbot label +F-associated_const_equality +F-min_generic_const_args
We want to evaluate the rhs of a type_const.
Also added an early return/guard in eval_in_interpreter which is used in functions like `eval_to_allocation_raw_provider`
Lastly add a debug assert to `thir_body()` if we have gotten there with a type_const something as gone wrong.
Get rid of a call to is_type_const() and instead use a match arm.
Change this is_type_const() check to a debug_assert!()
Change to use an if else statment instead.
Update type_const-pub.rs
Fix formatting.
Noticed that this is the same check as is_type_const() centralize it.
Add test case for pub type_const.
Support primitives in type info reflection
Tracking issue: rust-lang/rust#146922 `#![feature(type_info)]`
This PR supports {`bool`,`char`,`int`,`uint`,`float`,`str`} primitive types for feature `type_info` reflection.
r? @oli-obk
Remove `Deref`/`DerefMut` impl for `Providers`.
It's described as a "backwards compatibility hack to keep the diff small". Removing it requires only a modest amount of churn, and the resulting code is clearer without the invisible derefs.
r? @oli-obk
It's described as a "backwards compatibility hack to keep the diff
small". Removing it requires only a modest amount of churn, and the
resulting code is clearer without the invisible derefs.
Because these folders only change regions.
Note: `BottomUpFolder` folds all regions, while `fold_regions` skips
some bound regions. But that's ok because these two folders only modify
`ReVar`s.
Fix ICE: can't type-check body of DefId for issue #148729
This commit fixes https://github.com/rust-lang/rust/issues/148729 for min_const_generic_args https://github.com/rust-lang/rust/issues/132980.
It's pretty small PR. The first commit makes sure that the `type_const`s are made into normal consts in const expressions.
The next one just handles the case https://github.com/rust-lang/rust/issues/148729 of where the type of the const was omitted at which point it was trying to treat a `type_const` again as a regular const. That obviously will fail since a type_const does not have a body.
@rustbot label +F-associated_const_equality +F-min_generic_const_args +I-ICE
Handling for inherent associated consts is missing elsewhere, remove so it can be handled later in that handling.
Diagnostic not always be emitted on associated constant
Add a test case and Fix for a different ICE I encountered.
I noticed when trying various permuations of the test case code to see if I could find anymore ICEs. I did, but not one that I expected. So in the instances of the a named const not having any args, insantiate it directly. Since it is likely an inherent assocaiated const.
Added tests.
Centralize the is_type_const() logic.
I also noticed basically the exact same check in other part the code.
Const blocks can't be a type_const, therefore this check is uneeded.
Fix comment spelling error.
get_all_attrs is not valid to call for all DefIds it seems.
Make sure that if the type is omitted for a type_const that we don't ICE.
Co-Authored-By: Boxy <rust@boxyuwu.dev>
Don't use `matches!` when `==` suffices
In the codebase we sometimes use `matches!` for values that can actually just be compared. Replace them with `==`.
Subset of rust-lang/rust#149933.
interpreter/visitor: always iterate in in-memory order
Now that this is directly available in the type, there's no reason to ever iterate in any other order.
Replace Rvalue::NullaryOp by a variant in mir::Operand.
Based on https://github.com/rust-lang/rust/pull/148151
This PR fully removes the MIR `Rvalue::NullaryOp`. After rust-lang/rust#148151, it was only useful for runtime checks like `ub_checks`, `contract_checks` and `overflow_checks`.
These are "runtime" checks, boolean constants that may only be `true` in codegen. It depends on a rustc flag passed to codegen, so we need to represent those flags cross-crate.
This PR replaces those runtime checks by special variants in MIR `ConstValue`. This allows code that expects constants to manipulate those as such, even if we may not always be able to evaluate them to actual scalars.
miri genmc: fix exit() handling
In genmc mode, Miri does not want to stop execution when `exit` is called. Instead we want to continue running other threads to ensure we covered all possible concurrent behaviors (including the ones where the exiting thread was delayed so the other threads took their turns first). However, the core interpreter has a sanity check that prevents us from just doing nothing in `exit`. This leaves us in a pickle: there's nowhere we can jump to (exit has return type `!` so there's no next block), but if we don't jump anywhere we ICE.
The first commit fixes that by disabling the sanity check when there is no block to jump to. That still catches the mistake of forgetting to jump for the vast majority of shims.
We currently don't build Miri's genmc integration in rustc CI so I had to hack the feature into the bootstrap miri integration. That turned out to use the wrong Miri binary, which is fixed by the second commit: we can just rely on CARGO_BIN_EXE_miri, there's no need for a MIRI environment variable.
r? ``@oli-obk``
All usages of `memory_index` start by calling `invert_bijective_mapping`, so
storing the inverted mapping directly saves some work and simplifies the code.
Introduces `BackendRepr::ScalableVector` corresponding to scalable
vector types annotated with `repr(scalable)` which lowers to a scalable
vector type in LLVM.
Co-authored-by: Jamie Cunliffe <Jamie.Cunliffe@arm.com>
Overhaul filename handling for cross-compiler consistency
This PR overhauls the way we handle filenames in the compiler and `rmeta` in order to achieve achieve cross-compiler consistency (ie. having the same path no matter if the filename was created in the current compiler session or is coming from `rmeta`).
This is required as some parts of the compiler rely on consistent paths for the soundness of generated code (see rust-lang/rust#148328).
In order to achieved consistency multiple steps are being taken by this PR:
- by making `RealFileName` immutable
- by only having `SourceMap::to_real_filename` create `RealFileName`
- currently `RealFileName` can be created from any `Path` and are remapped afterwards, which creates consistency issue
- by also making `RealFileName` holds it's working directory, embeddable name and the remapped scopes
- this removes the need for a `Session`, to know the current(!) scopes and cwd, which is invalid as they may not be equal to the scopes used when creating the filename
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.
This PR is split-up in multiple commits (unfortunately not atomic), but should help review the changes.
Unblocks https://github.com/rust-lang/rust/pull/147611
Fixes https://github.com/rust-lang/rust/issues/148328
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`.
interpret: test SNaN handling of float min/max and update comments
Also see https://github.com/rust-lang/rust/pull/149563.
I also renamed these enum variants so they are not almost identical.
misc coercion cleanups and handle safety correctly
r? lcnr
### "remove normalize call"
Fixesrust-lang/rust#132765
If the normalization fails we would sometimes get a `TypeError` containing inference variables created inside of the probe used by coercion. These would then get leaked out causing ICEs in diagnostics logic
### "leak check and lub for closure<->closure coerce-lubs of same defids"
Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/233
```rust
fn peculiar() -> impl Fn(u8) -> u8 {
return |x| x + 1
}
```
the `|x| x + 1` expr has a type of `Closure(?31t)` which we wind up inferring the RPIT to. The `CoerceMany` `ret_coercion` for the whole `peculiar` typeck has an expected type of `RPIT` (unnormalized). When we type check the `return |x| x + 1` expr we go from the never type to `Closure(?31t)` which then participates in the `ret_coercion` giving us a `coerce-lub(RPIT, Closure(?31t))`.
Normalizing `RPIT` gives us some `Closure(?50t)` where `?31t` and `?50t` have been unified with `?31t` as the root var. `resolve_vars_if_possible` doesn't resolve infer vars to their roots so these wind up with different structural identities so the fast path doesn't apply and we fall back to coercing to a `fn` ptr. cc rust-lang/rust#147193 which also fixes this
New solver probably just gets more inference variables here because canonicalization + generally different approach to normalization of opaques. Idk :3
### FCP worthy stuffy
there are some other FCP worthy things but they're in my FCP comment which also contains some analysis of the breaking nature of the previously listed changes in this PR: https://github.com/rust-lang/rust/pull/148602#issuecomment-3503497467
const validation: remove check for mutable refs in final value of const
This check rejects code that is not necessarily UB, e.g. a mutable ref to a `static mut` that is very carefully used correctly. That led to us having to describe it in the Reference, which uncovered just how ad-hoc this check is (https://github.com/rust-lang/reference/issues/2074).
Even without this check, we still reject things like
```rust
const C: &mut i32 = &mut 0;
```
This is rejected by const checking -- the part of the frontend that looks at the source code and says whether it is allowed in const context. In the Reference, this restriction is explained [here](https://doc.rust-lang.org/nightly/reference/const_eval.html#r-const-eval.const-expr.borrows).
So, the check during validation is just a safety net. And it is already a safety net with gaping holes since we only check `&mut T`, not `&UnsafeCell<T>`, due to the fact that we promote some immutable values that have `!Freeze` type so `&!Freeze` actually can occur in the final value of a const.
So... it may be time for me to acknowledge that the "mutable ref in final value of const" check is a cure that's worth than the disease. Nobody asked for that check, I just added it because I was worried about soundness issues when we allow mutable references in constants. Originally it was much stricter, but I had to slowly relax it to its current form to prevent t from firing on code we intend to allow. In the end there are only 3 tests left that trigger this error, and they are all just constants containing references to mutable statics -- not the safest code in the world, but also not so bad that we have to spend a lot of time devising a core language limitation and associated Reference wording to prevent it from ever happening.
So... `@rust-lang/wg-const-eval` `@rust-lang/lang` I propose that we allow code like this
```rust
static mut S: i32 = 3;
const C2: &'static mut i32 = unsafe { &mut * &raw mut S };
```
`@theemathas` would be great if you could try to poke a hole into this. ;)
clarify float min/max behavios for NaNs and signed zeros
The first comment is internal, it only documents the intrinsics to more clearly say what they do.
This makes the currently implemented semantics more explicit, so one does not have to go look for the publicly exposed version of the operation to figure out what exactly should happen.
The second commit adds a NaN test to the doc comment for `min`/`max`, which matches what we already have for `minimum`/`maximum`.
Fix MaybeUninit codegen using GVN
This is an alternative to https://github.com/rust-lang/rust/pull/142837, based on https://github.com/rust-lang/rust/pull/146355#discussion_r2421651968.
The general approach I took here is to aggressively propagate anything that is entirely uninitialized. GVN generally takes the approach of only synthesizing small types, but we need to generate large consts to fix the codegen issue.
I also added a special case to MIR dumps for this where now an entirely uninit const is printed as `const <uninit>`, because otherwise we end up with extremely verbose dumps of the new consts.
After GVN though, we still end up with a lot of MIR that looks like this:
```
StorageLive(_1);
_1 = const <uninit>;
_2 = &raw mut _1;
```
Which will break tests/codegen-llvm/maybeuninit-rvo.rs with the naive lowering. I think the ideal fix here is to somehow omit these `_1 = const <uninit>` assignments that come directly after a StorageLive, but I'm not sure how to do that. For now at least, ignoring such assignments (even if they don't come right after a StorageLive) in codegen seems to work.
Note that since GVN is based on synthesizing a `ConstValue` which has a defined layout, this scenario still gets deoptimized by LLVM.
```rust
#![feature(rustc_attrs)]
#![crate_type = "lib"]
use std::mem::MaybeUninit;
#[unsafe(no_mangle)]
pub fn oof() -> [[MaybeUninit<u8>; 8]; 8] {
#[rustc_no_mir_inline]
pub fn inner<T: Copy>() -> [[MaybeUninit<T>; 8]; 8] {
[[MaybeUninit::uninit(); 8]; 8]
}
inner()
}
```
This case can be handled correctly if enough inlining has happened, or it could be handled by post-mono GVN. Synthesizing `UnevaluatedConst` or some other special kind of const seems dubious.