Refactor HIR item-like traversal (part 1)
Issue #95004
- Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems
- use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId
- use tcx.hir_crate_items to introduce a tcx.hir().par_items(impl Fn(hir::ItemId)) to traverse all items in parallel;
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
cc `@cjgillot`
Include Refs in Valtree Creation
This adds references to `const_to_valtree`, which isn't used in the compiler yet, but after the previous changes we made to the thir and mir representations and this change we should be able to finally introduce them in the next PR.
I wasn't able to properly test this code, except indirectly by including a call of `const_to_valtree` in the code that currently creates constants (`turn_into_const_value`).
r? `@lcnr`
cc `@oli-obk` `@RalfJung`
Adding diagnostic data on generators to the crate metadata and using it to provide
a better diagnostic on failure to meet send bound on futures originated from a foreign crate
Rollup of 9 pull requests
Successful merges:
- #93969 (Only add codegen backend to dep info if -Zbinary-dep-depinfo is used)
- #94605 (Add missing links in platform support docs)
- #95372 (make unaligned_references lint deny-by-default)
- #95859 (Improve diagnostics for unterminated nested block comment)
- #95961 (implement SIMD gather/scatter via vector getelementptr)
- #96004 (Consider lifetimes when comparing types for equality in MIR validator)
- #96050 (Remove some now-dead code that was only relevant before deaggregation.)
- #96070 ([test] Add test cases for untested functions for BTreeMap)
- #96099 (MaybeUninit array cleanup)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Implement sym operands for global_asm!
Tracking issue: #93333
This PR is pretty much a complete rewrite of `sym` operand support for inline assembly so that the same implementation can be shared by `asm!` and `global_asm!`. The main changes are:
- At the AST level, `sym` is represented as a special `InlineAsmSym` AST node containing a path instead of an `Expr`.
- At the HIR level, `sym` is split into `SymStatic` and `SymFn` depending on whether the path resolves to a static during AST lowering (defaults to `SynFn` if `get_early_res` fails).
- `SymFn` is just an `AnonConst`. It runs through typeck and we just collect the resulting type at the end. An error is emitted if the type is not a `FnDef`.
- `SymStatic` directly holds a path and the `DefId` of the `static` that it is pointing to.
- The representation at the MIR level is mostly unchanged. There is a minor change to THIR where `SymFn` is a constant instead of an expression.
- At the codegen level we need to apply the target's symbol mangling to the result of `tcx.symbol_name()` depending on the target. This is done by calling the LLVM name mangler, which handles all of the details.
- On Mach-O, all symbols have a leading underscore.
- On x86 Windows, different mangling is used for cdecl, stdcall, fastcall and vectorcall.
- No mangling is needed on other platforms.
r? `@nagisa`
cc `@eddyb`
remove find_use_placement
A more robust solution to finding where to place use suggestions was added in #94584.
The algorithm uses the AST to find the span for the suggestion so we pass this span
down to the HIR during lowering and use it instead of calling `find_use_placement`
Fixes#94941
Check var scope if it exist
Fixes#92893.
Added helper function to check the scope of a variable, if it doesn't have a scope call delay_span_bug, which avoids us trying to get a block/scope that doesn't exist.
Had to increase `ROOT_ENTRY_LIMIT` was getting tidy error
Stabilize `derive_default_enum`
This stabilizes `#![feature(derive_default_enum)]`, as proposed in [RFC 3107](https://github.com/rust-lang/rfcs/pull/3107) and tracked in #87517. In short, it permits you to `#[derive(Default)]` on `enum`s, indicating what the default should be by placing a `#[default]` attribute on the desired variant (which must be a unit variant in the interest of forward compatibility).
```````@rustbot``````` label +S-waiting-on-review +T-lang
Use mir constant in thir instead of ty::Const
This is blocked on https://github.com/rust-lang/rust/pull/94059 (does include its changes, the first two commits in this PR correspond to those changes) and https://github.com/rust-lang/rust/pull/93800 being reinstated (which had to be reverted). Mainly opening since `@lcnr` offered to give some feedback and maybe also for a perf-run (if necessary).
This currently contains a lot of duplication since some of the logic of `ty::Const` had to be copied to `mir::ConstantKind`, but with the introduction of valtrees a lot of that functionality will disappear from `ty::Const`.
Only the last commit contains changes that need to be reviewed here. Did leave some `FIXME` comments regarding future implementation decisions and some things that might be incorrectly implemented.
r? `@oli-obk`
Fix suggestions in case of `T:` bounds
This PR fixes a corner case in `suggest_constraining_type_params` that was causing incorrect suggestions.
For the following functions:
```rust
fn a<T:>(t: T) { [t, t]; }
fn b<T>(t: T) where T: { [t, t]; }
```
We previously suggested the following:
```text
...
help: consider restricting type parameter `T`
|
1 | fn a<T: Copy:>(t: T) { [t, t]; }
| ++++++
...
help: consider further restricting this bound
|
2 | fn b<T>(t: T) where T: + Copy { [t, t]; }
| ++++++
```
Note that neither `T: Copy:` not `where T: + Copy` is a correct bound.
With this commit the suggestions are correct:
```text
...
help: consider restricting type parameter `T`
|
1 | fn a<T: Copy>(t: T) { [t, t]; }
| ++++
...
help: consider further restricting this bound
|
2 | fn b<T>(t: T) where T: Copy { [t, t]; }
| ++++
```
r? `@compiler-errors`
I've tried fixing #95898 here too, but got too confused with how `suggest_traits_to_import` works and what it does 😅
Make def names and HIR names consistent.
The name in the `DefKey` is interned to create the `DefId`, so it does not
require any query to access. This can be leveraged to avoid a few useless
HIR accesses for names.
~In order to achieve that, generic parameters created from universal
impl-trait are given the pretty-printed ast as a name, instead of
`{{opaque}}`.~
~Drive-by: the `TyCtxt::opt_item_name` used a dummy span for non-local
definitions. We have access to `def_ident_span`, so we use it.~
refactor: simplify few string related interactions
Few small optimizations:
check_doc_keyword: don't alloc string for emptiness check
check_doc_alias_value: get argument as Symbol to prevent needless string convertions
check_doc_attrs: don't alloc vec, iterate over slice.
replace as_str() check with symbol check
get_single_str_from_tts: don't prealloc string
trivial string to str replace
LifetimeScopeForPath::NonElided use Vec<Symbol> instead of Vec<String>
AssertModuleSource use FxHashSet<Symbol> instead of BTreeSet<String>
CrateInfo.crate_name replace FxHashMap<CrateNum, String> with FxHashMap<CrateNum, Symbol>
interpret: err instead of ICE on size mismatches in to_bits_or_ptr_internal
We did this a while ago already for `to_i32()` and friends, but missed this one. That became quite annoying when I was debugging an ICE caused by `read_pointer` in a Miri shim where the code was passing an argument at the wrong type.
Having `scalar_to_ptr` be fallible is consistent with all the other `Scalar::to_*` methods being fallible. I added `unwrap` only in code outside the interpreter, which is no worse off than before now in terms of panics.
r? ````@oli-obk````
Cached stable hash cleanups
r? `@nnethercote`
Add a sanity assertion in debug mode to check that the cached hashes are actually the ones we get if we compute the hash each time.
Add a new data structure that bundles all the hash-caching work to make it easier to re-use it for different interned data structures
- Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems
- use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId
- add par_items(impl Fn(hir::ItemId)) to traverse all items in parallel
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
check_doc_alias_value: get argument as Symbol to prevent needless string convertions
check_doc_attrs: don't alloc vec, iterate over slice. Vec introduced in #83149, but no perf run posted on merge
replace as_str() check with symbol check
get_single_str_from_tts: don't prealloc string
trivial string to str replace
LifetimeScopeForPath::NonElided use Vec<Symbol> instead of Vec<String>
AssertModuleSource use BTreeSet<Symbol> instead of BTreeSet<String>
CrateInfo.crate_name replace FxHashMap<CrateNum, String> with FxHashMap<CrateNum, Symbol>
Let CTFE to handle partially uninitialized unions without marking the entire value as uninitialized.
follow up to #94411
To fix https://github.com/rust-lang/rust/issues/69488 and by extension fix https://github.com/rust-lang/rust/issues/94371, we should stop treating types like `MaybeUninit<usize>` as something that the `Scalar` type in the interpreter engine can represent. So we add a new field to `abi::Primitive` that records whether the primitive is nested in a union
cc `@RalfJung`
r? `@ghost`
Non-subdiagnostic fields (i.e. those that don't have `#[label]`
attributes or similar and are just additional context) have to be added
as arguments for Fluent messages to refer them. This commit extends the
`SessionDiagnostic` derive to do this for all fields that do not have
attributes and introduces an `IntoDiagnosticArg` trait that is
implemented on all types that can be converted to a argument for Fluent.
Signed-off-by: David Wood <david.wood@huawei.com>
`MultiSpan` contains labels, which are more complicated with the
introduction of diagnostic translation and will use types from
`rustc_errors` - however, `rustc_errors` depends on `rustc_span` so
`rustc_span` cannot use types like `DiagnosticMessage` without
dependency cycles. Introduce a new `rustc_error_messages` crate that can
contain `DiagnosticMessage` and `MultiSpan`.
Signed-off-by: David Wood <david.wood@huawei.com>
When encountering an unsatisfied trait bound, if there are no other
suggestions, mention all the types that *do* implement that trait:
```
error[E0277]: the trait bound `f32: Foo` is not satisfied
--> $DIR/impl_wf.rs:22:6
|
LL | impl Baz<f32> for f32 { }
| ^^^^^^^^ the trait `Foo` is not implemented for `f32`
|
= help: the following other types implement trait `Foo`:
Option<T>
i32
str
note: required by a bound in `Baz`
--> $DIR/impl_wf.rs:18:31
|
LL | trait Baz<U: ?Sized> where U: Foo { }
| ^^^ required by this bound in `Baz`
```
Mention implementers of traits in `ImplObligation`s.
Do not mention other `impl`s for closures, ranges and `?`.
Do not use `ParamEnv::and` when building a cache key from a param-env and trait eval candidate
Do not use `ParamEnv::and` to cache a param-env with a selection/evaluation candidate.
This is because if the param-env is `RevealAll` mode, and the candidate looks global (i.e. it has erased regions, which can show up when we normalize a projection type under a binder<sup>1</sup>), then when we use `ParamEnv::and` to pair the candidate and the param-env for use as a cache key, we will throw away the param-env's caller bounds, and we'll end up caching a candidate that we inferred from the param-env with a empty param-env, which may cause cache-hit later when we have an empty param-env, and possibly mess with normalization like we see in the referenced issue during codegen.
Not sure how to trigger this with a more structured test, but changing `check-pass` to `build-pass` triggers the case that https://github.com/rust-lang/rust/issues/94903 detected.
<sup>1.</sup> That is, we will replace the late-bound region with a placeholder, which gets canonicalized and turned into an infererence variable, which gets erased during region freshening right before we cache the result. Sorry, it's quite a few steps.
Fixes#94903
r? `@Aaron1011` (or reassign as you see fit)
interpret: make isize::MAX the limit for dynamic value sizes
We are currently enforcing `data_layout.obj_size_bound()` as the maximal dynamic size of a Rust value (including for `size_of_val_raw`), but that does not match the docs.
In particular, Miri currently falsely says that this code has UB:
```rust
#![feature(layout_for_ptr)]
fn main() {
let size = isize::MAX as usize;
// Creating a raw slice of size isize::MAX and asking for its size is okay.
let s = std::ptr::slice_from_raw_parts(1usize as *const u8, size);
assert_eq!(size, unsafe { std::mem::size_of_val_raw(s) });
}
```
Better suggestions for `Fn`-family trait selection errors
1. Suppress suggestions to add `std::ops::Fn{,Mut,Once}` bounds when a type already implements `Fn{,Mut,Once}`
2. Add a note that points out that a type does in fact implement `Fn{,Mut,Once}`, but the arguments vary (either by number or by actual arguments)
3. Add a note that points out that a type does in fact implement `Fn{,Mut,Once}`, but not the right one (e.g. implements `FnMut`, but `Fn` is required).
Fixes#95147
A more robust solution to finding where to place use suggestions was added.
The algorithm uses the AST to find the span for the suggestion so we pass this span
down to the HIR during lowering and use it.
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
Spellchecking compiler comments
This PR cleans up the rest of the spelling mistakes in the compiler comments. This PR does not change any literal or code spelling issues.
Restore `impl Future<Output = Type>` to async blocks
I was sad when I undid some of the code I wrote in #91096 in the PR #95225, so I fixed it here to not print `[async output]`.
This PR "manually" normalizes the associated type `<[generator] as Generator>::Return` type which appears very frequently in `impl Future` types that result from async block desugaring.
Rollup of 6 pull requests
Successful merges:
- #93901 (Stabilize native library modifier syntax and the `whole-archive` modifier specifically)
- #94806 (Fix `cargo run tidy`)
- #94869 (Add the generic_associated_types_extended feature)
- #95011 (async: Give predictable name to binding generated from .await expressions.)
- #95251 (Reduce max hash in raw strings from u16 to u8)
- #95298 (Fix double drop of allocator in IntoIter impl of Vec)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Add the generic_associated_types_extended feature
Right now, this only ignore obligations that reference new placeholders in `poly_project_and_unify_type`. In the future, this might do other things, like allowing object-safe GATs.
**This feature is *incomplete* and quite likely unsound. This is mostly just for testing out potential future APIs using a "relaxed" set of rules until we figure out *proper* rules.**
Also drive by cleanup of adding a `ProjectAndUnifyResult` enum instead of using a `Result<Result<Option>>`.
r? `@nikomatsakis`
Remember mutability in `DefKind::Static`.
This allows to compute the `BodyOwnerKind` from `DefKind` only, and
removes a direct dependency of some MIR queries onto HIR.
As a side effect, it also simplifies metadata, since we don't need 4
flavours of `EntryKind::*Static` any more.
allow arbitrary inherent impls for builtin types in core
Part of https://github.com/rust-lang/compiler-team/issues/487. Slightly adjusted after some talks with `@m-ou-se` about the requirements of `t-libs-api`.
This adds a crate attribute `#![rustc_coherence_is_core]` which allows arbitrary impls for builtin types in core.
For other library crates impls for builtin types should be avoided if possible. We do have to allow the existing stable impls however. To prevent us from accidentally adding more of these in the future, there is a second attribute `#[rustc_allow_incoherent_impl]` which has to be added to **all impl items**. This only supports impls for builtin types but can easily be extended to additional types in a future PR.
This implementation does not check for overlaps in these impls. Perfectly checking that requires us to check the coherence of these incoherent impls in every crate, as two distinct dependencies may add overlapping methods. It should be easy enough to detect if it goes wrong and the attribute is only intended for use inside of std.
The first two commits are mostly unrelated cleanups.
Rollup of 5 pull requests
Successful merges:
- #95294 (Document Linux kernel handoff in std::io::copy and std::fs::copy)
- #95443 (Clarify how `src/tools/x` searches for python)
- #95452 (fix since field version for termination stabilization)
- #95460 (Spellchecking compiler code)
- #95461 (Spellchecking some comments)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Lazy type-alias-impl-trait take two
### user visible change 1: RPIT inference from recursive call sites
Lazy TAIT has an insta-stable change. The following snippet now compiles, because opaque types can now have their hidden type set from wherever the opaque type is mentioned.
```rust
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return 42
}
let x: u32 = bar(false); // this errors on stable
99
}
```
The return type of `bar` stays opaque, you can't do `bar(false) + 42`, you need to actually mention the hidden type.
### user visible change 2: divergence between RPIT and TAIT in return statements
Note that `return` statements and the trailing return expression are special with RPIT (but not TAIT). So
```rust
#![feature(type_alias_impl_trait)]
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
return vec![42];
}
std::iter::empty().collect() //~ ERROR `Foo` cannot be built from an iterator
}
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return vec![42]
}
std::iter::empty().collect() // Works, magic (accidentally stabilized, not intended)
}
```
But when we are working with the return value of a recursive call, the behavior of RPIT and TAIT is the same:
```rust
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
return vec![];
}
let mut x = foo(false);
x = std::iter::empty().collect(); //~ ERROR `Foo` cannot be built from an iterator
vec![]
}
fn bar(b: bool) -> impl std::fmt::Debug {
if b {
return vec![];
}
let mut x = bar(false);
x = std::iter::empty().collect(); //~ ERROR `impl Debug` cannot be built from an iterator
vec![]
}
```
### user visible change 3: TAIT does not merge types across branches
In contrast to RPIT, TAIT does not merge types across branches, so the following does not compile.
```rust
type Foo = impl std::fmt::Debug;
fn foo(b: bool) -> Foo {
if b {
vec![42_i32]
} else {
std::iter::empty().collect()
//~^ ERROR `Foo` cannot be built from an iterator over elements of type `_`
}
}
```
It is easy to support, but we should make an explicit decision to include the additional complexity in the implementation (it's not much, see a721052457cf513487fb4266e3ade65c29b272d2 which needs to be reverted to enable this).
### PR formalities
previous attempt: #92007
This PR also includes #92306 and #93783, as they were reverted along with #92007 in #93893fixes#93411fixes#88236fixes#89312fixes#87340fixes#86800fixes#86719fixes#84073fixes#83919fixes#82139fixes#77987fixes#74282fixes#67830fixes#62742fixes#54895
This allows to compute the `BodyOwnerKind` from `DefKind` only, and
removes a direct dependency of some MIR queries onto HIR.
As a side effect, it also simplifies metadata, since we don't need 4
flavours of `EntryKind::*Static` any more.
parallel_compiler: hide dependencies behind feature
Separate dependencies for `parallel_compiler` feature, so they will not be compiled if feature not selected, reducing number of compiled crates from 238 to 224.
Remove `Session::one_time_diagnostic`
This is untracked mutable state, which modified the behaviour of queries.
It was used for 2 things: some full-blown errors, but mostly for lint declaration notes ("the lint level is defined here" notes).
It is replaced by the diagnostic deduplication infra which already exists in the diagnostic emitter.
A new diagnostic level `OnceNote` is introduced specifically for lint notes, to deduplicate subdiagnostics.
As a drive-by, diagnostic emission takes a `&mut` to allow dropping the `SubDiagnostic`s.
Swap DtorckConstraint to DropckConstraint
This change was made as per suspicion that this struct was never renamed after consistent use of DropCk.
This also clarifies the meaning behind the name of this structure.
Fixes https://github.com/rust-lang/rust/issues/94310
Clarify which kinds of MIR are allowed during which phases.
This enhances documentation with these details and extends the validator to check these requirements more thoroughly. Most of these conditions were already being checked.
There was also some disagreement between the `MirPhase` docs and validator as to what it meant for the `body.phase` field to have a certain value. This PR resolves those disagreements in favor of the `MirPhase` docs (which is what the pass manager implemented), adjusting the validator accordingly. The result is now that the `DropLowering` phase begins with the end of the elaborate drops pass, and lasts until the beginning of the generator lowring pass. This doesn't feel entirely natural to me, but as long as it's documented accurately it should be ok.
r? rust-lang/mir-opt
This change was made as per suspicion that this struct was never renamed after consistent use of DropCk.
This also clarifies the meaning behind the name of this structure.
Change Thir to lazily create constants
To allow `AbstractConst`s to work with the previous thir changes we made and those we want to make, i.e. to avoid problems due to `ValTree` and `ConstValue` conversions, we instead switch to a thir representation for constants that allows us to lazily create constants.
r? `@oli-obk`
Properly track `ImplObligations`
Instead of probing for all possible `impl`s that could have caused an
`ImplObligation`, keep track of its `DefId` and obligation spans for
accurate error reporting.
Follow to #89580. Addresses #89418.
Instead of probing for all possible impls that could have caused an
`ImplObligation`, keep track of its `DefId` and obligation spans for
accurate error reporting.
Follow up to #89580. Addresses #89418.
Remove some unnecessary clones.
Tweak output for auto trait impl obligations.
This enhances documentation with these details and extends the validator to check these requirements
more thoroughly. As a part of this, we add a new `Deaggregated` phase, and rename other phases so
that their names more naturally correspond to what they represent.
There are a few places were we have to construct it, though, and a few
places that are more invasive to change. To do this, we create a
constructor with a long obvious name.
fix typos
Rework of #94603 which got closed as I was trying to unmerge and repush. This is a subset of changes from the original pr as I sed'd whatever typos I remembered from the original PR
thanks to `@cuishuang` for the original PR
Improve `expect` impl and handle `#[expect(unfulfilled_lint_expectations)]` (RFC 2383)
This PR updates unstable `ExpectationIds` in stashed diagnostics and adds some asserts to ensure that the stored expectations are really empty in the end. Additionally, it handles the `#[expect(unfulfilled_lint_expectations)]` case.
According to the [Errors and lints docs](https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-levels) the `error` level should only be used _"when the compiler detects a problem that makes it unable to compile the program"_. As this isn't the case with `#[expect(unfulfilled_lint_expectations)]` I decided to only create a warning. To avoid adding a new lint only for this case, I simply emit a `unfulfilled_lint_expectations` diagnostic with an additional note.
---
r? `@wesleywiser` I'm requesting a review from you since you reviewed the previous PR https://github.com/rust-lang/rust/pull/87835. You are welcome to reassign it if you're busy 🙃
rfc: [RFC-2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html)
tracking issue: https://github.com/rust-lang/rust/issues/85549
cc: `@flip1995` In case you're also interested in this :)
Type params and assoc types have unit metadata if they are sized
Extend the logic in `Pointee` projection to ensure that we can satisfy `<T as Pointee>::Metadata = ()` if `T: Sized`.
cc: `@SimonSapin` and #93959
Return early to fix ICE
This fixes#94627, ICE happens because compiler tries to suggest constraining type parameter but the only constraint is implicit `std::Sized` one, so it gets removed and there is nothing to suggest resulting in ICE.
Improve `AdtDef` interning.
This commit makes `AdtDef` use `Interned`. Much of the commit is tedious
changes to introduce getter functions. The interesting changes are in
`compiler/rustc_middle/src/ty/adt.rs`.
r? `@fee1-dead`
CTFE/Miri: detect out-of-bounds pointers in offset_from
Also I became uneasy with aggressively doing `try_to_int` here -- this will always succeed on Miri, leading to the wrong codepath being taken. We should rather try to convert them both to pointers, and use the integer path as a fallback, so that's what I implemented now.
Hiding whitespaces helps with the diff.
Fixes https://github.com/rust-lang/miri/issues/1950
r? ``@oli-obk``
Change several HashMaps to IndexMap to improve incremental hashing performance
Stable hashing hash maps in incremental mode takes a lot of time, especially for some benchmarks like `clap`. As noted by `@Mark-Simulacrum` [here](https://github.com/rust-lang/rust/pull/89404#issuecomment-950043892), this cost could be reduced by replacing some hash maps by indexmaps.
I gathered some statistics and found several hash maps that took a lot of time to hash and replaced them by indexmaps. However, in order for this to work, we need to make sure that these indexmaps have deterministic insertion order. These three are used only in visitors as far as I can see, which seems deterministic. Can we enforce this somehow? Or should some explaining comment be included for these maps?
This commit makes `AdtDef` use `Interned`. Much the commit is tedious
changes to introduce getter functions. The interesting changes are in
`compiler/rustc_middle/src/ty/adt.rs`.
mir-opt: Replace clone on primitives with copy
We can't do it for everything, but it would be nice to at least stop making calls to clone methods in debug from things like derived-clones.
r? `@ghost`
This updates the standard library's documentation to use the new syntax. The
documentation is worthwhile to update as it should be more idiomatic
(particularly for features like this, which are nice for users to get acquainted
with). The general codebase is likely more hassle than benefit to update: it'll
hurt git blame, and generally updates can be done by folks updating the code if
(and when) that makes things more readable with the new format.
A few places in the compiler and library code are updated (mostly just due to
already having been done when this commit was first authored).
diagnostics: use rustc_on_unimplemented to recommend `[].iter()`
To make this work, the `#[rustc_on_unimplemented]` data needs to be used to
report method resolution errors, which is most of what this commit does.
Fixes#94581
This change is somewhat extensive, since it affects MIR -- since this is called to determine Copy vs Move -- so any test that's `no_core` needs to actually have the normal `impl`s it uses.
Treat constant values as mir::ConstantKind::Val
Another step that is necessary for the introduction of Valtrees: we don't want to treat `ty::Const` instances of kind `ty::ConstKind::Value` as `mir::ConstantKind::Ty` anymore.
r? `@oli-obk`
add `#[rustc_pass_by_value]` to more types
the only interesting changes here should be to `TransitiveRelation`, but I believe to be highly unlikely that we will ever use a non `Copy` type with this type.
To make this work, the `#[rustc_on_unimplemented]` data needs to be used to
report method resolution errors, which is most of what this commit does.
Fixes#94581
Use impl substs in `#[rustc_on_unimplemented]`
We were using the trait-ref substs instead of impl substs in `rustc_on_unimplemented`, even when computing the `rustc_on_unimplemented` attached to an impl block. Let's not do that.
This PR also untangles impl and trait def-ids in the logic in `on_unimplemented` a bit.
Fixes#94675
Clarify `Layout` interning.
`Layout` is another type that is sometimes interned, sometimes not, and
we always use references to refer to it so we can't take any advantage
of the uniqueness properties for hashing or equality checks.
This commit renames `Layout` as `LayoutS`, and then introduces a new
`Layout` that is a newtype around an `Interned<LayoutS>`. It also
interns more layouts than before. Previously layouts within layouts
(via the `variants` field) were never interned, but now they are. Hence
the lifetime on the new `Layout` type.
Unlike other interned types, these ones are in `rustc_target` instead of
`rustc_middle`. This reflects the existing structure of the code, which
does layout-specific stuff in `rustc_target` while `TyAndLayout` is
generic over the `Ty`, allowing the type-specific stuff to occur in
`rustc_middle`.
The commit also adds a `HashStable` impl for `Interned`, which was
needed. It hashes the contents, unlike the `Hash` impl which hashes the
pointer.
r? `@fee1-dead`
`Layout` is another type that is sometimes interned, sometimes not, and
we always use references to refer to it so we can't take any advantage
of the uniqueness properties for hashing or equality checks.
This commit renames `Layout` as `LayoutS`, and then introduces a new
`Layout` that is a newtype around an `Interned<LayoutS>`. It also
interns more layouts than before. Previously layouts within layouts
(via the `variants` field) were never interned, but now they are. Hence
the lifetime on the new `Layout` type.
Unlike other interned types, these ones are in `rustc_target` instead of
`rustc_middle`. This reflects the existing structure of the code, which
does layout-specific stuff in `rustc_target` while `TyAndLayout` is
generic over the `Ty`, allowing the type-specific stuff to occur in
`rustc_middle`.
The commit also adds a `HashStable` impl for `Interned`, which was
needed. It hashes the contents, unlike the `Hash` impl which hashes the
pointer.
Currently some `Allocation`s are interned, some are not, and it's very
hard to tell at a use point which is which.
This commit introduces `ConstAllocation` for the known-interned ones,
which makes the division much clearer. `ConstAllocation::inner()` is
used to get the underlying `Allocation`.
In some places it's natural to use an `Allocation`, in some it's natural
to use a `ConstAllocation`, and in some places there's no clear choice.
I've tried to make things look as nice as possible, while generally
favouring `ConstAllocation`, which is the type that embodies more
information. This does require quite a few calls to `inner()`.
The commit also tweaks how `PartialOrd` works for `Interned`. The
previous code was too clever by half, building on `T: Ord` to make the
code shorter. That caused problems with deriving `PartialOrd` and `Ord`
for `ConstAllocation`, so I changed it to build on `T: PartialOrd`,
which is slightly more verbose but much more standard and avoided the
problems.
Ensure stability directives are checked in all cases
Split off #93017
Stability and deprecation were not checked in all cases, for instance if a type error happened.
This PR moves the check earlier in the pipeline to ensure the errors are emitted in all cases.
r? `@lcnr`
improve comments for `simplify_type`
Should now correctly describe what's going on. Experimented with checking the invariant for projections
but that ended up requiring fairly involved changes. I assume that it is not possible to get unsoundness here,
at least for now and I can pretty much guarantee that it's impossible to trigger it by accident.
r? `````@nikomatsakis````` cc #92721
Implementation of the `expect` attribute (RFC 2383)
This is an implementation of the `expect` attribute as described in [RFC-2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html). The attribute allows the suppression of lint message by expecting them. Unfulfilled lint expectations (meaning no expected lint was caught) will emit the `unfulfilled_lint_expectations` lint at the `expect` attribute.
### Example
#### input
```rs
// required feature flag
#![feature(lint_reasons)]
#[expect(unused_mut)] // Will warn about an unfulfilled expectation
#[expect(unused_variables)] // Will be fulfilled by x
fn main() {
let x = 0;
}
```
#### output
```txt
warning: this lint expectation is unfulfilled
--> $DIR/trigger_lint.rs:3:1
|
LL | #[expect(unused_mut)] // Will warn about an unfulfilled expectation
| ^^^^^^^^^^
|
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
```
### Implementation
This implementation introduces `Expect` as a new lint level for diagnostics, which have been expected. All lint expectations marked via the `expect` attribute are collected in the [`LintLevelsBuilder`] and assigned an ID that is stored in the new lint level. The `LintLevelsBuilder` stores all found expectations and the data needed to emit the `unfulfilled_lint_expectations` in the [`LintLevelsMap`] which is the result of the [`lint_levels()`] query.
The [`rustc_errors::HandlerInner`] is the central error handler in rustc and handles the emission of all diagnostics. Lint message with the level `Expect` are suppressed during this emission, while the expectation ID is stored in a set which marks them as fulfilled. The last step is then so simply check if all expectations collected by the [`LintLevelsBuilder`] in the [`LintLevelsMap`] have been marked as fulfilled in the [`rustc_errors::HandlerInner`]. Otherwise, a new lint message will be emitted.
The implementation of the `LintExpectationId` required some special handling to make it stable between sessions. Lints can be emitted during [`EarlyLintPass`]es. At this stage, it's not possible to create a stable identifier. The level instead stores an unstable identifier, which is later converted to a stable `LintExpectationId`.
### Followup TO-DOs
All open TO-DOs have been marked with `FIXME` comments in the code. This is the combined list of them:
* [ ] The current implementation doesn't cover cases where the `unfulfilled_lint_expectations` lint is actually expected by another `expect` attribute.
* This should be easily possible, but I wanted to get some feedback before putting more work into this.
* This could also be done in a new PR to not add to much more code to this one
* [ ] Update unstable documentation to reflect this change.
* [ ] Update unstable expectation ids in [`HandlerInner::stashed_diagnostics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.HandlerInner.html#structfield.stashed_diagnostics)
### Open questions
I also have a few open questions where I would like to get feedback on:
1. The RFC discussion included a suggestion to change the `expect` attribute to something else. (Initiated by `@Ixrec` [here](https://github.com/rust-lang/rfcs/pull/2383#issuecomment-378424091), suggestion from `@scottmcm` to use `#[should_lint(...)]` [here](https://github.com/rust-lang/rfcs/pull/2383#issuecomment-378648877)). No real conclusion was drawn on that point from my understanding. Is this still open for discussion, or was this discarded with the merge of the RFC?
2. How should the expect attribute deal with the new `force-warn` lint level?
---
This approach was inspired by a discussion with `@LeSeulArtichaut.`
RFC tracking issue: #54503
Mentoring/Implementation issue: #85549
[`LintLevelsBuilder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/levels/struct.LintLevelsBuilder.html
[`LintLevelsMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/struct.LintLevelMap.html
[`lint_levels()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.lint_levels
[`rustc_errors::HandlerInner`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.HandlerInner.html
[`EarlyLintPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html
Miri/CTFE: properly treat overflow in (signed) division/rem as UB
To my surprise, it looks like LLVM treats overflow of signed div/rem as UB. From what I can tell, MIR `Div`/`Rem` directly lowers to the corresponding LLVM operation, so to make that correct we also have to consider these overflows UB in the CTFE/Miri interpreter engine.
r? `@oli-obk`
Restore the local filter on mono item sorting
In `CodegenUnit::items_in_deterministic_order`, there's a comment that
only local HirIds should be taken into account, but #90408 removed the
`as_local` call that sets others to None. Restoring that check fixes the
s390x hangs seen in [RHBZ 2058803].
[RHBZ 2058803]: https://bugzilla.redhat.com/show_bug.cgi?id=2058803
Adt copy suggestions
Previously we've only suggested adding `Copy` bounds when the type being moved/copied is a type parameter (generic). With this PR we also suggest adding bounds when a type
- Can be copy
- All predicates that need to be satisfied for that are based on type params
i.e. we will suggest `T: Copy` for `Option<T>`, but won't suggest anything for `Option<String>`.
An example:
```rust
fn duplicate<T>(t: Option<T>) -> (Option<T>, Option<T>) {
(t, t)
}
```
New error (current compiler doesn't provide `help`:):
```text
error[E0382]: use of moved value: `t`
--> t.rs:2:9
|
1 | fn duplicate<T>(t: Option<T>) -> (Option<T>, Option<T>) {
| - move occurs because `t` has type `Option<T>`, which does not implement the `Copy` trait
2 | (t, t)
| - ^ value used here after move
| |
| value moved here
|
help: consider restricting type parameter `T`
|
1 | fn duplicate<T: Copy>(t: Option<T>) -> (Option<T>, Option<T>) {
| ++++++
```
Fixes#93623
r? ``````````@estebank``````````
``````````@rustbot`````````` label +A-diagnostics +A-suggestion-diagnostics +C-enhancement
----
I'm not at all sure if this is the right implementation for this kind of suggestion, but it seems to work :')
Direct users towards using Rust target feature names in CLI
This PR consists of a couple of changes on how we handle target features.
In particular there is a bug-fix wherein we avoid passing through features that aren't prefixed by `+` or `-` to LLVM. These appear to be causing LLVM to assert, which is pretty poor a behaviour (and also makes it pretty clear we expect feature names to be prefixed).
The other commit, I anticipate to be somewhat more controversial is outputting a warning when users specify a LLVM-specific, or otherwise unknown, feature name on the CLI. In those situations we request users to either replace it with a known Rust feature name (e.g. `bmi` -> `bmi1`) or file a feature request. I've a couple motivations for this: first of all, if users are specifying these features on the command line, I'm pretty confident there is also a need for these features to be usable via `#[cfg(target_feature)]` machinery. And second, we're growing a fair number of backends recently and having ability to provide some sort of unified-ish interface in this place seems pretty useful to me.
Sponsored by: standard.ai
In `CodegenUnit::items_in_deterministic_order`, there's a comment that
only local HirIds should be taken into account, but #90408 removed the
`as_local` call that sets others to None. Restoring that check fixes the
s390x hangs seen in [RHBZ 2058803].
[RHBZ 2058803]: https://bugzilla.redhat.com/show_bug.cgi?id=2058803
Add `rustc_middle::ty::suggest_constraining_type_params` that suggests
adding multiple constraints.
`suggest_constraining_type_param` now just forwards params to this new
function.
Caching the stable hash of Ty within itself
Instead of computing stable hashes on types as needed, we compute it during interning.
This way we can, when a hash is requested, just hash that hash, which is significantly faster than traversing the type itself.
We only do this for incremental for now, as incremental is the only frequent user of stable hashing.
As a next step we can try out
* moving the hash and TypeFlags to Interner, so projections and regions get the same benefit (tho regions are not nested, so maybe that's not a good idea? Would be nice for dedup tho)
* start comparing types via their stable hash instead of their address?
Apply noundef attribute to all scalar types which do not permit raw init
Beyond `&`/`&mut`/`Box`, this covers `char`, enum discriminants, `NonZero*`, etc.
All such types currently cause a Miri error if left uninitialized,
and an `invalid_value` lint in cases like `mem::uninitialized::<char>()`.
Note that this _does not_ change whether or not it is UB for `u64` (or
other integer types with no invalid values) to be undef.
Fixes (partially) #74378.
r? `@ghost` (blocked on #94127)
`@rustbot` label S-blocked
Avoid query cache sharding code in single-threaded mode
In non-parallel compilers, this is just adding needless overhead at compilation time (since there is only one shard statically anyway). This amounts to roughly ~10 seconds reduction in bootstrap time, with overall neutral (some wins, some losses) performance results.
Parallel compiler performance should be largely unaffected by this PR; sharding is kept there.
Beyond `&`/`&mut`/`Box`, this covers `char`, discriminants, `NonZero*`, etc.
All such types currently cause a Miri error if left uninitialized,
and an `invalid_value` lint in cases like `mem::uninitialized::<char>()`
Note that this _does not_ change whether or not it is UB for `u64` (or
other integer types with no invalid values) to be undef.
fix a message
implement a rustfix-applicable suggestion
implement `suggest_floating_point_literal`
add `ObligationCauseCode::BinOp`
remove duplicate code
fix function names in uitests
use `Diagnostic` instead of `DiagnosticBuilder`
Print `ParamTy` and `ParamConst` instead of displaying them
Display for `ParamTy` and `ParamConst` is implemented in terms of print.
Using print avoids creating a new `FmtPrinter` just to display the
parameter name.
r? `@Mark-Simulacrum`
Remove in band lifetimes
As discussed in t-lang backlog bonanza, the `in_band_lifetimes` FCP closed in favor for the feature not being stabilized. This PR removes `#![feature(in_band_lifetimes)]` in its entirety.
Let me know if this PR is too hasty, and if we should instead do something intermediate for deprecate the feature first.
r? `@scottmcm` (or feel free to reassign, just saw your last comment on #44524)
Closes#44524