Make `InferCtxtExt::could_impl_trait` more precise, less ICEy
The implementation for `InferCtxtExt::could_impl_trait` was very wrong. Along with being pretty poorly named, way too specific to ADTs, it was also doing impl substitution wrong -- this caused an ICE (#119915).
This PR generalizes that code, gives it a clearer name, makes it stop using the new trait solver (lol), and fixes some fallout bad suggestions that are made worse with the code fix.
Fixes#119915
`Diagnostic::code` has the type `DiagnosticId`, which has `Error` and
`Lint` variants. Plus `Diagnostic::is_lint` is a bool, which should be
redundant w.r.t. `Diagnostic::code`.
Seems simple. Except it's possible for a lint to have an error code, in
which case its `code` field is recorded as `Error`, and `is_lint` is
required to indicate that it's a lint. This is what happens with
`derive(LintDiagnostic)` lints. Which means those lints don't have a
lint name or a `has_future_breakage` field because those are stored in
the `DiagnosticId::Lint`.
It's all a bit messy and confused and seems unintentional.
This commit:
- removes `DiagnosticId`;
- changes `Diagnostic::code` to `Option<String>`, which means both
errors and lints can straightforwardly have an error code;
- changes `Diagnostic::is_lint` to `Option<IsLint>`, where `IsLint` is a
new type containing a lint name and a `has_future_breakage` bool, so
all lints can have those, error code or not.
This also switches from `split_off(0)` to `std::mem::take` when emptying the
accumulated list of blocks, because `split_off(0)` handles capacity in a way
that is unintuitive when used in a loop.
The old loop had two separate places where it would flush the acumulated list
of straight-line blocks into a new BCB. One occurred at the start of the loop
body when the current block couldn't be chained into, and the other occurred at
the end of the loop body when the current block couldn't be chained from.
The latter check can be hoisted to the start of the loop body by making it
examine the previous block (which has added itself to the list) instead of the
current block. With that done, we can combine the two separate flushes into one
flush with two possible trigger conditions.
Filtering out unreachable successors is only needed by the main graph traversal
loop, so we can move the filtering step into that loop instead, eliminating the
need to pass the MIR body into `bcb_filtered_successors`.
store the segment name when resolution fails
Fixes#112672
The `find_cfg_stripped` does indeed get executed within `smart_resolve_report_errors`. However, this error is not reported as it is subsequently overridden by `parent_err`. (See: https://github.com/rust-lang/rust/blob/master/compiler/rustc_resolve/src/late.rs#L3760)
This PR changes `last_segment` to `segment`, which stores the name of the failed resolution, and ensures that the result of `find_cfg_stripped` is also included in `parent_err`.
r? ```@Nilstrieb```
Suggest Upgrading Compiler for Gated Features
This PR addresses #117318
I have a few questions:
1. Do we want to specify the current version and release date of the compiler? I have added this in via environment variables, which I found in the code for the rustc cli where it handles the `--version` flag
a. How can I handle the changing message in the tests?
3. Do we want to only show this message when the compiler is old?
a. How can we determine when the compiler is old?
I'll wait until we figure out the message to bless the tests
Move platform modules into `sys::pal`
This is the initial step of #117276. `sys` just re-exports everything from the current `sys` for now, I'll move the implementations for the individual features one-by-one after this PR merges.
Taint `_` placeholder types in trait impl method signatures
We report an error right below for them, but that kind of broken type can cause subsequent ICEs.
fixes#119867
Allow `~const` on associated type bounds again
This follows from [this Zulip discussion](https://rust-lang.zulipchat.com/#narrow/stream/419616-t-compiler.2Fproject-const-traits/topic/projections.20on.20.28~.29const.20Trait.20.26.20.28~.29const.20assoc.20ty.20bounds).
Basically in my opinion, it makes sense to allow `~const` on associated type bounds again since they're quite useful even though we haven't implemented the proposed syntax `<Ty as ~const Trait>::Proj`/`<Ty as const Trait>::Proj` yet; that can happen as a follow-up.
This already allows more code to compile since `T::Assoc` where `T` is a type parameter and where the predicate `<T as ~const Trait>` is in the environment gets elaborated to (pseudo) `<T as ~const Trait>::Assoc`.
```rs
#[const_trait]
trait Trait {
type Assoc: ~const Trait;
fn func() -> i32;
}
const fn function<T: ~const Trait>() -> i32 {
T::Assoc::func()
}
```
`~const` associated type bounds also work together with `const` bounds:
```rs
struct Type<const N: i32>;
fn procedure<T: const Trait>() -> Type<{ T::Assoc::func() }> { // `Trait` comes from above
Type
}
```
NB: This PR also starts allowing `~const` bounds in the generics and the where-clause of trait associated types since it's trivial to support them. However, I don't know if those bounds are actually useful. Maybe we should continue to reject them?
For reference, it wouldn't make any sense to allow `~const Trait` in GACs (generic associated constants, `generic_const_items`) because they'd be absolutely useless (contrary to `const Trait`).
~~[``@]rustbot`` ping project-const-traits~~
r? project-const-traits
Varargs support for system ABI
This PR allows functions with the `system` ABI to be variadic (under the `extended_varargs_abi_support` feature tracked in #100189). On x86 windows, the `system` ABI is equivalent to `C` for variadic functions. On other platforms, `system` is already equivalent to `C`.
Fixes#110505
Overhaul `-Ztreat-err-as-bug`
It's current behaviour is surprising, in a bad way. This also makes the implementation more complex than it needs to be.
r? `@oli-obk`
Add explicit `none()` value variant in check-cfg
This PR adds an explicit none value variant in check-cfg values: `values(none())`.
Currently the only way to define the none variant is with an empty `values()` which means that if someone has a cfg that takes none and strings they need to use two invocations: `--check-cfg=cfg(foo) --check-cfg=cfg(foo, values("bar"))`.
Which would now be `--check-cfg=cfg(foo, values(none(),"bar"))`, this is simpler and easier to understand.
`--check-cfg=cfg(foo)`, `--check-cfg=cfg(foo, values())` and `--check-cfg=cfg(foo, values(none()))` would be equivalent.
*Another motivation for doing this is to make empty `values()` actually means no-values, but this is orthogonal to this PR and adding `none()` is sufficient in it-self.*
`@rustbot` label +F-check-cfg
r? `@petrochenkov`
`-Ztreat-err-as-bug` treats normal errors and delayed bugs equally,
which can lead to some really surprising results.
This commit changes `-Ztreat-err-as-bug` so it ignores delayed bugs,
unless they get promoted to proper bugs and are printed.
This feels to me much simpler and more logical. And it simplifies the
implementation:
- The `-Ztreat-err-as-bug` check is removed from in
`DiagCtxt::{delayed_bug,span_delayed_bug}`.
- `treat_err_as_bug` doesn't need to count delayed bugs.
- The `-Ztreat-err-as-bug` panic message is simpler, because it doesn't
have to mention delayed bugs.
Output of delayed bugs is now more consistent. They're always printed
the same way. Previously when they triggered `-Ztreat-err-as-bug` they
would be printed slightly differently, via `span_bug` in
`span_delayed_bug` or `delayed_bug`.
A minor behaviour change: the "no errors encountered even though
`span_delayed_bug` issued" printed before delayed bugs is now a note
rather than a bug. This is done so it doesn't get counted as an error
that might trigger `-Ztreat-err-as-bug`, which would be silly.
This means that if you use `-Ztreat-err-as-bug=1` and there are no
normal errors but there are delayed bugs, the first delayed bug will be
shown (and the panic will happen after it's printed).
Also, I have added a second note saying "those delayed bugs will now be
shown as internal compiler errors". I think this makes it clearer what
is happening, because the whole concept of delayed bugs is non-obvious.
There are some test changes.
- equality-in-canonical-query.rs: Minor output changes, and the error
count reduces by one because the "no errors encountered even though
`span_delayed_bug` issued" message is no longer counted as an error.
- rpit_tait_equality_in_canonical_query.rs: Ditto.
- storage-live.rs: The query stack disappears because these delayed bugs
are now printed at the end, rather than when they are created.
- storage-return.rs, span_delayed_bug.rs: now need
`-Zeagerly-emit-delayed-bugs` because they need the delayed bugs
emitted immediately to preserve behaviour.
Fix unused_parens issue when cast is followed LT
Fixes#117142
The original check only checks `a as (i32) < 0`, this fix extends it to handle `b + a as (i32) < 0`.
A better way is maybe we suggest `(a as i32) < 0` instead of suppressing the warning, maybe following PR could improve it.
Add more information to `visit_projection_elem`
Without the starting place, it's hard to retrieve any useful information from visiting a projection.
Note: I still need to add a test.
Give me a way to emit all the delayed bugs as errors (add `-Zeagerly-emit-delayed-bugs`)
This is probably a *better* way to inspect all the delayed bugs in a program that what exists currently (and therefore makes it very easy to choose the right number `N` with `-Zemit-err-as-bug=N`, though I guess the naming is a bit ironic when you pair both of the flags together, but that feels like naming bikeshed more than anything).
This pacifies my only concern with https://github.com/rust-lang/rust/pull/119871#issuecomment-1888170259, because (afaict?) that PR doesn't allow you to intercept a delayed bug's stack trace anymore, which as someone who debugs the compiler a lot, is something that I can *promise* that I do.
r? `@nnethercote` or `@oli-obk`
Remove special-casing around `AliasKind::Opaque` when structurally resolving in new solver
This fixes a few inconsistencies around where we don't eagerly resolve opaques to their (locally-defined) hidden types in the new solver. It essentially allows this code to work:
```rust
fn main() {
type Tait = impl Sized;
struct S {
i: i32,
}
let x: Tait = S { i: 0 };
println!("{}", x.i);
}
```
Since `Tait` is defined in `main`, we are able to poke through the type of `x` with deref.
r? lcnr
Exhaustiveness: track overlapping ranges precisely
The `overlapping_range_endpoints` lint has false positives, e.g. https://github.com/rust-lang/rust/issues/117648. I expected that removing these false positives would have too much of a perf impact but never measured it. This PR is an experiment to see if the perf loss is manageable.
r? `@ghost`
Register even erroneous impls
Otherwise the specialization graph fails to pick it up, even though other code assumes that all impl blocks have an entry in the specialization graph.
also includes an unrelated cleanup of the specialization graph query
fixes #119827
Set `c_str_literals` stabilization version back to `CURRENT_RUSTC_VERSION`
`c_str_literals`'s stabilization has been delayed to 1.77 (https://github.com/rust-lang/rust/pull/119528).
next solver: provisional cache
this adds the cache removed in #115843. However, it should now correctly track whether a provisional result depends on an inductive or coinductive stack.
While working on this, I was using the following doc: https://hackmd.io/VsQPjW3wSTGUSlmgwrDKOA. I don't think it's too helpful to understanding this, but am somewhat hopeful that the inline comments are more useful.
There are quite a few future perf improvements here. Given that this is already very involved I don't believe it is worth it (for now). While working on this PR one of my few attempts to significantly improve perf ended up being unsound again because I was not careful enough ✨
r? `@compiler-errors`
By making it an `EscapeError` instead of a `LitError`. This makes it
like the other errors produced when checking string literals contents,
e.g. for invalid escape sequences or bare CR chars.
NOTE: this means these errors are issued earlier, before expansion,
which changes behaviour. It will be possible to move the check back to
the later point if desired. If that happens, it's likely that all the
string literal contents checks will be delayed together.
One nice thing about this: the old approach had some code in
`report_lit_error` to calculate the span of the nul char from a range.
This code used a hardwired `+2` to account for the `c"` at the start of
a C string literal, but this should have changed to a `+3` for raw C
string literals to account for the `cr"`, which meant that the caret in
`cr"` nul error messages was one short of where it should have been. The
new approach doesn't need any of this and avoids the off-by-one error.
There are two places that handle normal delayed bugs. This commit
factors out some repeated code.
Also, we can use `std::mem::take` instead of `std::mem::replace`.
coverage: Add enums to accommodate other kinds of coverage mappings
Extracted from #118305.
LLVM supports several different kinds of coverage mapping regions, but currently we only ever emit ordinary “code” regions. This PR performs the plumbing required to add other kinds of regions as enum variants, but does not add any specific variants other than `Code`.
The main motivation for this change is branch coverage, but it will also allow separate experimentation with gap regions and skipped regions, which might help in producing more accurate and useful coverage reports.
---
``@rustbot`` label +A-code-coverage
Remove `DiagnosticBuilder::buffer`
`DiagnosticBuilder::buffer` doesn't do much, and part of what it does (for `-Ztreat-err-as-bug`) it shouldn't.
This PR strips it back, replaces its uses, and finally removes it, making a few cleanups in the vicinity along the way.
r? ``@oli-obk``
Silence some follow-up errors [2/x]
this is one piece of the requested cleanups from https://github.com/rust-lang/rust/pull/117449
the `type_of` query frequently uses astconv to convert a `hir::Ty` to a `ty::Ty`. This process is infallible, but may produce errors as it goes. All the error reporting sites that had access to the `ItemCtxt` are now tainting it, causing `type_of` to return a `ty::Error` instead of anything else.
annotate-snippets: update to 0.10
Ports `annotate-snippets` to 0.10, temporary dupes versions; other crates left that depends on 0.9 is `ui_test` and `rustfmt`.
Remove a large amount of leb128-coded integers
This removes ~41%[^1] of the leb128-encoded integers serialized during libcore compilation by changing enum tags to opportunistically use `u8` where feasible instead of the leb128 coding via `usize`.
This should have effectively zero impact on metadata file sizes, since almost all or all enum tags fit into the 7 bits available in leb128 for single-byte encodings. Perf results indicate this is basically neutral across the board except for an improvement in bootstrap time.
[^1]: More than half the remaining integers still fit into <= 128, so the leb128 coding still makes sense. 32% are zero, and 46% are <= 4.
One consequence is that errors returned by
`maybe_new_parser_from_source_str` now must be consumed, so a bunch of
places that previously ignored those errors now cancel them. (Most of
them explicitly dropped the errors before. I guess that was to indicate
"we are explicitly ignoring these", though I'm not 100% sure.)
Stop mentioning internal lang items in no_std binary errors
When writing a no_std binary, you'll be greeted with nonsensical errors mentioning lang items like eh_personality and start. That's pretty bad because it makes you think that you need to define them somewhere! But oh no, now you're getting the `internal_features` lint telling you that you shouldn't use them! But you need a no_std binary! What now?
No problem! Writing a no_std binary is super easy. Just use panic=abort and supply your own platform specific entrypoint symbol (like `main`) and you're good to go. Would be nice if the compiler told you that, right?
This makes it so that it does do that.
I don't _love_ the new messages yet, but they're decent I think. They can probably be improved, please suggest improvements.
Two different lifetimes are conflated. This doesn't matter right now,
but needs to be fixed for the next commit to work. And the more
descriptive lifetime names make the code easier to read.
But we can't easily switch from `Vec<Diagnostic>` to
`Vec<DiagnosticBuilder<G>>` because there's a mix of errors and warnings
which result in different `G` types. So we must make
`DiagnosticBuilder::into_diagnostic` public, but that's ok, and it will
get more use in subsequent commits.
Each of these has a single call site: `source_file_to_parser`,
`try_file_to_source_file`, `file_to_source_file`. Having them separate
just makes the code longer and harder to read.
Also, `maybe_file_to_stream` doesn't need to be `pub`.
It seems very wrong to have a `-Ztreat-err-as-bug` check here before the
error is even emitted.
Once that's done:
- `into_diagnostic` is infallible, so its return type doesn't need the
`Option`;
- the `&'a DiagCtxt` also isn't needed, because only one callsite uses
it, and it already have access to it via `self.dcx`;
- the comments about dcx disabling buffering are no longer true, this is
unconditional now;
- and the `debug!` seems unnecessary... the comment greatly overstates
its importance because few diagnostics come through `into_diagnostic`,
and `-Ztrack-diagnostics` exists anyway.
Errors in `DiagCtxtInner::emit_diagnostic` are never set to
`Level::Bug`, because the condition never succeeds, because
`self.treat_err_as_bug()` is called *before* the error counts are
incremented.
This commit switches to `self.treat_next_err_as_bug()`, fixing the
problem. This changes the error message output to actually say "internal
compiler error".
This is less elegant in some ways, since we no longer visit a BCB's spans as a
batch, but will make it much easier to add support for other kinds of coverage
mapping regions (e.g. branch regions or gap regions).
Reorder early post-inlining passes.
`RemoveZsts`, `RemoveUnneededDrops` and `UninhabitedEnumBranching` only depend on types, so they should be executed together early after MIR inlining introduces those types.
This does not change the end-result, but this makes the pipeline a bit more consistent.
Rollup of 11 pull requests
Successful merges:
- #115046 (Use version-sorting for all sorting)
- #118915 (Add some comments, add `can_define_opaque_ty` check to `try_normalize_ty_recur`)
- #119006 (Fix is_global special address handling)
- #119637 (Pass LLVM error message back to pass wrapper.)
- #119715 (Exhaustiveness: abort on type error)
- #119763 (Cleanup things in and around `Diagnostic`)
- #119788 (change function name in comments)
- #119790 (Fix all_trait* methods to return all traits available in StableMIR)
- #119803 (Silence some follow-up errors [1/x])
- #119804 (Stabilize mutex_unpoison feature)
- #119832 (Meta: Add project const traits to triagebot config)
r? `@ghost`
`@rustbot` modify labels: rollup
Silence some follow-up errors [1/x]
this is one piece of the requested cleanups from https://github.com/rust-lang/rust/pull/117449
When we use `-> impl SomeTrait<_>` as a return type, we are both using the "infer return type suggestion" code path, and the infer opaque type code path within the same function. That can lead to confusing diagnostics, so silence all opaque type diagnostics in that case.
Cleanup things in and around `Diagnostic`
These changes all arose when I was looking closely at how to simplify `DiagCtxtInner::emit_diagnostic`.
r? `@compiler-errors`
Pass LLVM error message back to pass wrapper.
When rustc fails to load a plugin, it should provide more detailed error message. Before this PR, rustc prints:
```
error: failed to run LLVM passes: Failed to load pass pluginPLUGIN_NAME.so
```
This PR passes LLVM errors back to rustc. After this PR, rustc prints:
```
error: failed to run LLVM passes: Could not load library 'PLUGIN_NAME.so': PLUGIN_NAME.so: undefined symbol: _ZN4llvm9DebugFlagE
```
This PR only contains usability improvements and does not change any functionality. Thus, no new unit test is implemented.
Exhaustiveness: use an `Option` instead of allocating fictitious patterns
In the process of exhaustiveness checking, `Matrix` stores a 2D array of patterns. Those are subpatterns of the patterns we were provided as input, _except_ sometimes we allocate some extra wildcard patterns to fill a hole during specialization.
Morally though, we could store `Option<&'p DeconstructedPat>` in the matrix, where `None` signifies a wildcard. That way we'd only have "real" patterns in the matrix and we wouldn't need the arena to allocate these wildcards. This is what this PR does.
This is part of me splitting up https://github.com/rust-lang/rust/pull/119581 for ease of review.
r? `@compiler-errors`
Of the error levels satisfying `is_error`, `Level::Error` is the only
one that can be a lint, so there's no need to check for it.
(And even if it wasn't, it would make more sense to include
non-`Error`-but-`is_error` lints under `lint_err_count` than under
`err_count`.)
There are four functions that adjust error and warning counts:
- `stash_diagnostic` (increment)
- `steal_diagnostic` (decrement)
- `emit_stashed_diagnostics) (decrement)
- `emit_diagnostic` (increment)
The first three all behave similarly, and only update `warn_count` for
forced warnings. But the last one updates `warn_count` for both forced
and non-forced warnings.
Seems like a bug. How should it be fixed? Well, `warn_count` is only
used in one place: `DiagCtxtInner::drop`, where it's part of the
condition relating to the printing of `good_path_delayed_bugs`. The
intention of that condition seems to be "have any errors been printed?"
so this commit replaces `warn_count` with `has_printed`, which is set
when printing occurs. This is simpler than all the ahead-of-time
incrementing and decrementing.
`is_force_warn` is only possible for diagnostics with `Level::Warning`,
but it is currently stored in `Diagnostic::code`, which every diagnostic
has.
This commit:
- removes the boolean `DiagnosticId::Lint::is_force_warn` field;
- adds a `ForceWarning` variant to `Level`.
Benefits:
- The common `Level::Warning` case now has no arguments, replacing
lots of `Warning(None)` occurrences.
- `rustc_session::lint::Level` and `rustc_errors::Level` are more
similar, both having `ForceWarning` and `Warning`.
When writing a no_std binary, you'll be greeted with nonsensical errors
mentioning lang items like eh_personality and start. That's pretty bad
because it makes you think that you need to define them somewhere! But
oh no, now you're getting the `internal_features` lint telling you that
you shouldn't use them! But you need a no_std binary! What now?
No problem! Writing a no_std binary is super easy. Just use panic=abort
and supply your own platform specific entrypoint symbol (like `main`)
and you're good to go. Would be nice if the compiler told you that,
right?
This makes it so that it does do that.
Diagnostic API fixes
Some improvements to diagnostic APIs: improve some naming, use shortcuts in more places, and add a couple of missing methods.
r? `@compiler-errors`
This removes emit_enum_variant and the emit_usize calls that resulted
in. In libcore this eliminates 17% of leb128, taking us from 8964488 to
7383842 leb128's serialized.
100% of the serialized enums during libcore compilation fit into the
smaller tag, and this eliminates hitting the leb128 code for
coding/decoding when we can statically guarantee that's not required.
30% of all leb128 integers serialized in libcore (12981183 total) come
from the usize's removed here.
Avoid silencing relevant follow-up errors
r? `@matthewjasper`
This PR only adds new errors to tests that are already failing and fixes one ICE.
Several tests were changed to not emit new errors. I believe all of them were faulty tests, and not explicitly testing for the code that had new errors.
This lets us avoid the use of `DiagnosticBuilder::into_diagnostic` in
miri, when then means that `DiagnosticBuilder::into_diagnostic` can
become private, being now only used by `stash` and `buffer`.
In #119606 I added them and used a `_mv` suffix, but that wasn't great.
A `with_` prefix has three different existing uses.
- Constructors, e.g. `Vec::with_capacity`.
- Wrappers that provide an environment to execute some code, e.g.
`with_session_globals`.
- Consuming chaining methods, e.g. `Span::with_{lo,hi,ctxt}`.
The third case is exactly what we want, so this commit changes
`DiagnosticBuilder::foo_mv` to `DiagnosticBuilder::with_foo`.
Thanks to @compiler-errors for the suggestion.