Remove `TypeVariableOriginKind` and `ConstVariableOriginKind`
It's annoying to have to import `TypeVariableOriginKind` just to fill it with `MiscVariable` for almost every use. Every other usage other than `TypeParameterDefinition` wasn't even used -- I can see how it may have been useful once for debugging, but I do quite a lot of typeck debugging and I've never really needed it.
So let's just remove it, and keep around the only useful thing which is the `DefId` of the param for `var_for_def`.
This is based on #123006, which removed the special use of `TypeVariableOriginKind::OpaqueInference`, which I'm pretty sure I was the one that added.
r? lcnr or re-roll to types
Use `fn` ptr signature instead of `{closure@..}` in infer error
When suggesting a type on inference error, do not use `{closure@..}`. Instead, replace with an appropriate `fn` ptr.
On the error message, use `short_ty_string` and write long types to disk.
```
error[E0284]: type annotations needed for `Select<{closure@lib.rs:2782:13}, _, Expression<'_>, _>`
--> crates/lang/src/parser.rs:41:13
|
41 | let lit = select! {
| ^^^
42 | Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
| ---- type must be known at this point
|
= note: the full type name has been written to '/home/gh-estebank/iowo/target/debug/deps/lang-e2d6e25819442273.long-type-4587393693885174369.txt'
= note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
|
41 | let lit: Select<for<'a, 'b> fn(tokens::Token<'_>, &'a mut MapExtra<'_, 'b, _, _>) -> Option<Expression<'_>>, _, Expression<'_>, _> = select! {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
instead of
```
error[E0284]: type annotations needed for `Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _>`
--> crates/lang/src/parser.rs:41:13
|
41 | let lit = select! {
| ^^^
42 | Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
| ---- type must be known at this point
|
= note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
|
41 | let lit: Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _> = select! {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
Address #123630 (test missing).
When suggesting a type on inference error, do not use `{closure@..}`.
Instead, replace with an appropriate `fn` ptr.
On the error message, use `short_ty_string` and write long types to
disk.
```
error[E0284]: type annotations needed for `Select<{closure@lib.rs:2782:13}, _, Expression<'_>, _>`
--> crates/lang/src/parser.rs:41:13
|
41 | let lit = select! {
| ^^^
42 | Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
| ---- type must be known at this point
|
= note: the full type name has been written to '/home/gh-estebank/iowo/target/debug/deps/lang-e2d6e25819442273.long-type-4587393693885174369.txt'
= note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
|
41 | let lit: Select<for<'a, 'b> fn(tokens::Token<'_>, &'a mut MapExtra<'_, 'b, _, _>) -> Option<Expression<'_>>, _, Expression<'_>, _> = select! {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
instead of
```
error[E0284]: type annotations needed for `Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _>`
--> crates/lang/src/parser.rs:41:13
|
41 | let lit = select! {
| ^^^
42 | Token::Int(i) = e => Expression::new(Expr::Lit(ast::Lit::Int(i.parse().unwrap())), e.span()),
| ---- type must be known at this point
|
= note: cannot satisfy `<_ as chumsky::input::Input<'_>>::Span == SimpleSpan`
help: consider giving `lit` an explicit type, where the type for type parameter `I` is specified
|
41 | let lit: Select<{closure@/home/gh-estebank/.cargo/registry/src/index.crates.io-6f17d22bba15001f/chumsky-1.0.0-alpha.6/src/lib.rs:2782:13: 2782:28}, _, Expression<'_>, _> = select! {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
```
Fix#123630.
Pass list of defineable opaque types into canonical queries
This eliminates `DefiningAnchor::Bubble` for good and brings the old solver closer to the new one wrt cycles and nested obligations. At that point the difference between `DefiningAnchor::Bind([])` and `DefiningAnchor::Error` was academic. We only used the difference for some sanity checks, which actually had to be worked around in places, so I just removed `DefiningAnchor` entirely and just stored the list of opaques that may be defined.
fixes#108498
fixes https://github.com/rust-lang/rust/issues/116877
* [x] run crater
- https://github.com/rust-lang/rust/pull/122077#issuecomment-2013293931
compiler: fix few unused_peekable and needless_pass_by_ref_mut clippy lints
This fixes few instances of `unused_peekable` and `needless_pass_by_ref_mut`. While i expected to fix more warnings, `needless_pass_by_ref_mut` produced too much for one PR, so i stopped here.
Better reviewed commit by commit, as fixes splitted by chunks.
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_session\src\config.rs:2013:16
|
2013 | early_dcx: &mut EarlyDiagCtxt,
| ^^^^^^^^^^^^^^^^^^ help: consider changing to: `&EarlyDiagCtxt`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_ast_passes\src\ast_validation.rs:1555:11
|
1555 | this: &mut AstValidator<'_>,
| ^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&AstValidator<'_>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_infer\src\infer\snapshot\fudge.rs:16:12
|
16 | table: &mut UnificationTable<'_, 'tcx, T>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&UnificationTable<'_, 'tcx, T>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
warning: this argument is a mutable reference, but not used mutably
--> compiler\rustc_expand\src\expand.rs:961:13
|
961 | parser: &mut Parser<'a>,
| ^^^^^^^^^^^^^^^ help: consider changing to: `&Parser<'a>`
|
= warning: changing this function will impact semver compatibility
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_ref_mut
Handle str literals written with `'` lexed as lifetime
Given `'hello world'` and `'1 str', provide a structured suggestion for a valid string literal:
```
error[E0762]: unterminated character literal
--> $DIR/lex-bad-str-literal-as-char-3.rs:2:26
|
LL | println!('hello world');
| ^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | println!("hello world");
| ~ ~
```
```
error[E0762]: unterminated character literal
--> $DIR/lex-bad-str-literal-as-char-1.rs:2:20
|
LL | println!('1 + 1');
| ^^^^
|
help: if you meant to write a `str` literal, use double quotes
|
LL | println!("1 + 1");
| ~ ~
```
Fix#119685.
Rename `hir::Local` into `hir::LetStmt`
Follow-up of #122776.
As discussed on [zulip](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Improve.20naming.20of.20.60ExprKind.3A.3ALet.60.3F).
I made this change into a separate PR because I'm less sure about this change as is. For example, we have `visit_local` and `LocalSource` items. Is it fine to keep these two as is (I supposed it is but I prefer to ask) or not? Having `Node::Local(LetStmt)` makes things more explicit but is it going too far?
r? ```@oli-obk```
Split an item bounds and an item's super predicates
This is the moral equivalent of #107614, but instead for predicates this applies to **item bounds**. This PR splits out the item bounds (i.e. *all* predicates that are assumed to hold for the alias) from the item *super predicates*, which are the subset of item bounds which share the same self type as the alias.
## Why?
Much like #107614, there are places in the compiler where we *only* care about super-predicates, and considering predicates that possibly don't have anything to do with the alias is problematic. This includes things like closure signature inference (which is at its core searching for `Self: Fn(..)` style bounds), but also lints like `#[must_use]`, error reporting for aliases, computing type outlives predicates.
Even in cases where considering all of the `item_bounds` doesn't lead to bugs, unnecessarily considering irrelevant bounds does lead to a regression (#121121) due to doing extra work in the solver.
## Example 1 - Trait Aliases
This is best explored via an example:
```
type TAIT<T> = impl TraitAlias<T>;
trait TraitAlias<T> = A + B where T: C;
```
The item bounds list for `Tait<T>` will include:
* `Tait<T>: A`
* `Tait<T>: B`
* `T: C`
While `item_super_predicates` query will include just the first two predicates.
Side-note: You may wonder why `T: C` is included in the item bounds for `TAIT`? This is because when we elaborate `TraitAlias<T>`, we will also elaborate all the predicates on the trait.
## Example 2 - Associated Type Bounds
```
type TAIT<T> = impl Iterator<Item: A>;
```
The `item_bounds` list for `TAIT<T>` will include:
* `Tait<T>: Iterator`
* `<Tait<T> as Iterator>::Item: A`
But the `item_super_predicates` will just include the first bound, since that's the only bound that is relevant to the *alias* itself.
## So what
This leads to some diagnostics duplication just like #107614, but none of it will be user-facing. We only see it in the UI test suite because we explicitly disable diagnostic deduplication.
Regarding naming, I went with `super_predicates` kind of arbitrarily; this can easily be changed, but I'd consider better names as long as we don't block this PR in perpetuity.
Fix bad span for explicit lifetime suggestions
Fixes#121267
Current explicit lifetime suggestions are not showing correct spans for some lifetimes - e.g. elided lifetime generic parameters;
This should be done correctly regarding elided lifetime kind like the following code
43fdd4916d/compiler/rustc_resolve/src/late/diagnostics.rs (L3015-L3044)
Rollup of 10 pull requests
Successful merges:
- #122435 (Don't trigger `unused_qualifications` on global paths)
- #122556 (Extend format arg help for simple tuple index access expression)
- #122634 (compiletest: Add support for `//@ aux-bin: foo.rs`)
- #122677 (Fix incorrect mutable suggestion information for binding in ref pattern.)
- #122691 (Fix ICE: `global_asm!()` Don't Panic When Unable to Evaluate Constant)
- #122695 (Change only_local to a enum type.)
- #122717 (Ensure stack before parsing dot-or-call)
- #122719 (Ensure nested statics have a HIR node to prevent various queries from ICEing)
- #122720 ([doc]:fix error code example)
- #122724 (add test for casting pointer to union with unsized tail)
r? `@ghost`
`@rustbot` modify labels: rollup
misc cleanups from debugging something
rename `instantiate_canonical_with_fresh_inference_vars` to `instantiate_canonical` the substs for the canonical are not solely infer vars as that would be wildly wrong and it is rather confusing to see this method called and think that the entire canonicalization setup is completely broken when it is not 👍
also update region debug printing to be more like the custom impls for Ty/Const, right now regions in debug output are horribly verbose and make it incredibly hard to read but with this atleast boundvars and placeholders when debugging the new solver do not take up excessive amounts of space.
r? `@lcnr`
Stabilize associated type bounds (RFC 2289)
This PR stabilizes associated type bounds, which were laid out in [RFC 2289]. This gives us a shorthand to express nested type bounds that would otherwise need to be expressed with nested `impl Trait` or broken into several `where` clauses.
### What are we stabilizing?
We're stabilizing the associated item bounds syntax, which allows us to put bounds in associated type position within other bounds, i.e. `T: Trait<Assoc: Bounds...>`. See [RFC 2289] for motivation.
In all position, the associated type bound syntax expands into a set of two (or more) bounds, and never anything else (see "How does this differ[...]" section for more info).
Associated type bounds are stabilized in four positions:
* **`where` clauses (and APIT)** - This is equivalent to breaking up the bound into two (or more) `where` clauses. For example, `where T: Trait<Assoc: Bound>` is equivalent to `where T: Trait, <T as Trait>::Assoc: Bound`.
* **Supertraits** - Similar to above, `trait CopyIterator: Iterator<Item: Copy> {}`. This is almost equivalent to breaking up the bound into two (or more) `where` clauses; however, the bound on the associated item is implied whenever the trait is used. See #112573/#112629.
* **Associated type item bounds** - This allows constraining the *nested* rigid projections that are associated with a trait's associated types. e.g. `trait Trait { type Assoc: Trait2<Assoc2: Copy>; }`.
* **opaque item bounds (RPIT, TAIT)** - This allows constraining associated types that are associated with the opaque without having to *name* the opaque. For example, `impl Iterator<Item: Copy>` defines an iterator whose item is `Copy` without having to actually name that item bound.
The latter three are not expressible in surface Rust (though for associated type item bounds, this will change in #120752, which I don't believe should block this PR), so this does represent a slight expansion of what can be expressed in trait bounds.
### How does this differ from the RFC?
Compared to the RFC, the current implementation *always* desugars associated type bounds to sets of `ty::Clause`s internally. Specifically, it does *not* introduce a position-dependent desugaring as laid out in [RFC 2289], and in particular:
* It does *not* desugar to anonymous associated items in associated type item bounds.
* It does *not* desugar to nested RPITs in RPIT bounds, nor nested TAITs in TAIT bounds.
This position-dependent desugaring laid out in the RFC existed simply to side-step limitations of the trait solver, which have mostly been fixed in #120584. The desugaring laid out in the RFC also added unnecessary complication to the design of the feature, and introduces its own limitations to, for example:
* Conditionally lowering to nested `impl Trait` in certain positions such as RPIT and TAIT means that we inherit the limitations of RPIT/TAIT, namely lack of support for higher-ranked opaque inference. See this code example: https://github.com/rust-lang/rust/pull/120752#issuecomment-1979412531.
* Introducing anonymous associated types makes traits no longer object safe, since anonymous associated types are not nameable, and all associated types must be named in `dyn` types.
This last point motivates why this PR is *not* stabilizing support for associated type bounds in `dyn` types, e.g, `dyn Assoc<Item: Bound>`. Why? Because `dyn` types need to have *concrete* types for all associated items, this would necessitate a distinct lowering for associated type bounds, which seems both complicated and unnecessary compared to just requiring the user to write `impl Trait` themselves. See #120719.
### Implementation history:
Limited to the significant behavioral changes and fixes and relevant PRs, ping me if I left something out--
* #57428
* #108063
* #110512
* #112629
* #120719
* #120584Closes#52662
[RFC 2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html
hir: Remove `opt_local_def_id_to_hir_id` and `opt_hir_node_by_def_id`
Also replace a few `hir_node()` calls with `hir_node_by_def_id()`.
Follow up to https://github.com/rust-lang/rust/pull/120943.
Add a tidy check that checks whether the fluent slugs only appear once
As ``````@Nilstrieb`````` said in https://github.com/rust-lang/rust/pull/121828#issuecomment-1972622855:
> Might make sense to have a tidy check that checks whether the fluent slugs only appear once in the source code and lint for that
there's a tidy check already for sorting
We can get the tidy check error:
```
tidy check
tidy error: /path/to/rust/compiler/rustc_const_eval/messages.ftl: message `const_eval_invalid_align` is not used
tidy error: /path/to/rust/compiler/rustc_lint/messages.ftl: message `lint_trivial_untranslatable_diag` is not used
tidy error: /path/to/rust/compiler/rustc_parse/messages.ftl: message `parse_invalid_literal_suffix` is not used
tidy error: /path/to/rust/compiler/rustc_infer/messages.ftl: message `infer_need_type_info_in_coroutine` is not used
tidy error: /path/to/rust/compiler/rustc_passes/messages.ftl: message `passes_expr_not_allowed_in_context` is not used
tidy error: /path/to/rust/compiler/rustc_passes/messages.ftl: message `passes_layout` is not used
tidy error: /path/to/rust/compiler/rustc_parse/messages.ftl: message `parse_not_supported` is not used
```
r? ``````@Nilstrieb``````
Use `ControlFlow` in visitors.
Follow up to #121256
This does have a few small behaviour changes in some diagnostic output where the visitor will now find the first match rather than the last match. The change in `find_anon_types.rs` has the only affected test. I don't see this being an issue as the last occurrence isn't any better of a choice than the first.
silence mismatched types errors for implied projections
Currently, if a trait bound is not satisfied, then we suppress any errors for the trait's supertraits not being satisfied, but still report errors for super projections not being satisfied.
For example:
```rust
trait Super {
type Assoc;
}
trait Sub: Super<Assoc = ()> {}
```
Before this PR, if `T: Sub` is not satisfied, then errors for `T: Super` are suppressed, but errors for `<T as Super>::Assoc == ()` are still shown. This PR makes it so that errors about super projections not being satisfied are also suppressed.
The errors are only suppressed if the span of the trait obligation matches the span of the super predicate obligation to avoid silencing error that are not related. This PR removes some differences between the spans of supertraits and super projections to make the suppression work correctly.
This PR fixes the majority of the diagnostics fallout when making `Thin` a supertrait of `Sized` (in a future PR).
cc https://github.com/rust-lang/rust/pull/120354#issuecomment-1930585382
cc `@lcnr`
stricter hidden type wf-check [based on #115008]
Original work by `@aliemjay` in #115008. A huge thanks to them for originally figuring out this approach ❤️
Fixes https://github.com/rust-lang/rust/issues/114728
Fixes https://github.com/rust-lang/rust/issues/114572
Instead of adding the `WellFormed` obligations when relating opaque types, we now always emit such an obligation when defining the hidden type.
This causes nested opaque types which aren't wf to error, see the comment below for the described impact. I believe this change to be desirable as it significantly reduces complexity by removing special-cases.
It also caused an issue with RPITIT: in defaulted trait methods, we add a `Projection(synthetic_assoc, rpit_of_trait_method)` clause to the `param_env`. This clause is not added to the `ParamEnv` of the nested coroutines. This caused a normalization failure in `fn check_coroutine_obligations` with the new solver. I fixed that by using the env of the typeck root instead.
r? `@oli-obk`
Rollup of 9 pull requests
Successful merges:
- #121065 (Add basic i18n guidance for `Display`)
- #121744 (Stop using Bubble in coherence and instead emulate it with an intercrate check)
- #121829 (Dummy tweaks (attempt 2))
- #121857 (Implement async closure signature deduction)
- #121894 (const_eval_select: make it safe but be careful with what we expose on stable for now)
- #122014 (Change some attributes to only_local.)
- #122016 (will_wake tests fail on Miri and that is expected)
- #122018 (only set noalias on Box with the global allocator)
- #122028 (Remove some dead code)
r? `@ghost`
`@rustbot` modify labels: rollup
Don't grab variances in `TypeRelating` relation if we're invariant
Since `Invariant.xform(var) = Invariant` always, so just copy what the generalizer relation does.
Fixes#110106
Suggest removing superfluous semicolon when statements used as expression
Fixes#105431
- it's not a pure recursive visitor, so I guess there may be some more complex scenarios not covered.
- moved `consider_removing_semicolon` to `compiler/rustc_infer` for reusing this helper function.
Improve error messages for generics with default parameters
Fixes#120785
Issue: Previously, all type parameters with default types were deliberately ignored to simplify error messages. For example, an error message for Box type would display `Box<T>` instead of `Box<T, _>`. But, this resulted in unclear error message when a concrete type was used instead of the default type.
Fix: This PR fixes it by checking if a concrete type is specified after a default type to display the entire type name or the simplified type name.
change equate for binders to not rely on subtyping
*summary by `@spastorino` and `@lcnr*`
### Context
The following code:
```rust
type One = for<'a> fn(&'a (), &'a ());
type Two = for<'a, 'b> fn(&'a (), &'b ());
mod my_api {
use std::any::Any;
use std::marker::PhantomData;
pub struct Foo<T: 'static> {
a: &'static dyn Any,
_p: PhantomData<*mut T>, // invariant, the type of the `dyn Any`
}
impl<T: 'static> Foo<T> {
pub fn deref(&self) -> &'static T {
match self.a.downcast_ref::<T>() {
None => unsafe { std::hint::unreachable_unchecked() },
Some(a) => a,
}
}
pub fn new(a: T) -> Foo<T> {
Foo::<T> {
a: Box::leak(Box::new(a)),
_p: PhantomData,
}
}
}
}
use my_api::*;
fn main() {
let foo = Foo::<One>::new((|_, _| ()) as One);
foo.deref();
let foo: Foo<Two> = foo;
foo.deref();
}
```
has UB from hitting the `unreachable_unchecked`. This happens because `TypeId::of::<One>()` is not the same as `TypeId::of::<Two>()` despite them being considered the same types by the type checker.
Currently the type checker considers binders to be equal if subtyping succeeds in both directions: `for<'a> T<'a> eq for<'b> U<'b>` holds if `for<'a> exists<'b> T<'b> <: T'<a> AND for<'b> exists<'a> T<'a> <: T<'b>` holds. This results in `for<'a> fn(&'a (), &'a ())` and `for<'a, 'b> fn(&'a (), &'b ())` being equal in the type system.
`TypeId` is computed by looking at the *structure* of a type. Even though these types are semantically equal, they have a different *structure* resulting in them having different `TypeId`. This can break invariants of unsafe code at runtime and is unsound when happening at compile time, e.g. when using const generics.
So as seen in `main`, we can assign a value of type `Foo::<One>` to a binding of type `Foo<Two>` given those are considered the same type but then when we call `deref`, it calls `downcast_ref` that relies on `TypeId` and we would hit the `None` arm as these have different `TypeId`s.
As stated in https://github.com/rust-lang/rust/issues/97156#issuecomment-1879030033, this causes the API of existing crates to be unsound.
## What should we do about this
The same type resulting in different `TypeId`s is a significant footgun, breaking a very reasonable assumptions by authors of unsafe code. It will also be unsound by itself once they are usable in generic contexts with const generics.
There are two options going forward here:
- change how the *structure* of a type is computed before relying on it. i.e. continue considering `for<'a> fn(&'a (), &'a ())` and `for<'a, 'b> fn(&'a (), &'b ())` to be equal, but normalize them to a common representation so that their `TypeId` are also the same.
- change how the semantic equality of binders to match the way we compute the structure of types. i.e. `for<'a> fn(&'a (), &'a ())` and `for<'a, 'b> fn(&'a (), &'b ())` still have different `TypeId`s but are now also considered to not be semantically equal.
---
Advantages of the first approach:
- with the second approach some higher ranked types stop being equal, even though they are subtypes of each other
General thoughts:
- changing the approach in the future will be breaking
- going from first to second may break ordinary type checking, as types which were previously equal are now distinct
- going from second to first may break coherence, because previously disjoint impls overlap as the used types are now equal
- both of these are quite unlikely. This PR did not result in any crater failures, so this should not matter too much
Advantages of the second approach:
- the soundness of the first approach requires more non-local reasoning. We have to make sure that changes to subtyping do not cause the representative computation to diverge from semantic equality
- e.g. we intend to consider higher ranked implied bounds when subtyping to [fix] https://github.com/rust-lang/rust/issues/25860, I don't know how this will interact and don't feel confident making any prediction here.
- computing a representative type is non-trivial and soundness critical, therefore adding complexity to the "core type system"
---
This PR goes with the second approach. A crater run did not result in any regressions. I am personally very hesitant about trying the first approach due to the above reasons. It feels like there are more unknowns when going that route.
### Changing the way we equate binders
Relating bound variables from different depths already results in a universe error in equate. We therefore only need to make sure that there is 1-to-1 correspondence between bound variables when relating binders. This results in concrete types being structurally equal after anonymizing their bound variables.
We implement this by instantiating one of the binder with placeholders and the other with inference variables and then equating the instantiated types. We do so in both directions.
More formally, we change the typing rules as follows:
```
for<'r0, .., 'rn> exists<'l0, .., 'ln> LHS<'l0, .., 'ln> <: RHS<'r0, .., 'rn>
for<'l0, .., 'ln> exists<'r0, .., 'rn> RHS<'r0, .., 'rn> <: LHS<'l0, .., 'ln>
--------------------------------------------------------------------------
for<'l0, .., 'ln> LHS<'l0, .., 'ln> eq for<'r0, .., 'rn> RHS<'r0, .., 'rn>
```
to
```
for<'r0, .., 'rn> exists<'l0, .., 'ln> LHS<'l0, .., 'ln> eq RHS<'r0, .., 'rn>
for<'l0, .., 'ln> exists<'r0, .., 'rn> RHS<'r0, .., 'rn> eq LHS<'l0, .., 'ln>
--------------------------------------------------------------------------
for<'l0, .., 'ln> LHS<'l0, .., 'ln> eq for<'r0, .., 'rn> RHS<'r0, .., 'rn>
```
---
Fixes#97156
r? `@lcnr`
Count stashed errors again
Stashed diagnostics are such a pain. Their "might be emitted, might not" semantics messes with lots of things.
#120828 and #121206 made some big changes to how they work, improving some things, but still leaving some problems, as seen by the issues caused by #121206. This PR aims to fix all of them by restricting them in a way that eliminates the "might be emitted, might not" semantics while still allowing 98% of their benefit. Details in the individual commit logs.
r? `@oli-obk`
Stashed errors used to be counted as errors, but could then be
cancelled, leading to `ErrorGuaranteed` soundness holes. #120828 changed
that, closing the soundness hole. But it introduced other difficulties
because you sometimes have to account for pending stashed errors when
making decisions about whether errors have occured/will occur and it's
easy to overlook these.
This commit aims for a middle ground.
- Stashed errors (not warnings) are counted immediately as emitted
errors, avoiding the possibility of forgetting to consider them.
- The ability to cancel (or downgrade) stashed errors is eliminated, by
disallowing the use of `steal_diagnostic` with errors, and introducing
the more restrictive methods `try_steal_{modify,replace}_and_emit_err`
that can be used instead.
Other things:
- `DiagnosticBuilder::stash` and `DiagCtxt::stash_diagnostic` now both
return `Option<ErrorGuaranteed>`, which enables the removal of two
`delayed_bug` calls and one `Ty::new_error_with_message` call. This is
possible because we store error guarantees in
`DiagCtxt::stashed_diagnostics`.
- Storing the guarantees also saves us having to maintain a counter.
- Calls to the `stashed_err_count` method are no longer necessary
alongside calls to `has_errors`, which is a nice simplification, and
eliminates two more `span_delayed_bug` calls and one FIXME comment.
- Tests are added for three of the four fixed PRs mentioned below.
- `issue-121108.rs`'s output improved slightly, omitting a non-useful
error message.
Fixes#121451.
Fixes#121477.
Fixes#121504.
Fixes#121508.
Opportunistically resolve regions when processing region outlives obligations
Due to the matching in `TypeOutlives` being structural, we should attempt to opportunistically resolve regions before processing region obligations. Thanks ``@lcnr`` for finding this.
r? lcnr
Add `StructurallyRelateAliases` to allow instantiating infer vars with rigid aliases.
Change `instantiate_query_response` to be infallible in the new solver. This requires canonicalization to not hide any information used by the query, so weaken
universe compression. It also modifies `term_is_fully_unconstrained` to allow
region inference variables in a higher universe.
Rollup of 7 pull requests
Successful merges:
- #121435 (Account for RPITIT in E0310 explicit lifetime constraint suggestion)
- #121490 (Rustdoc: include crate name in links for local primitives)
- #121520 (delay cloning of iterator items)
- #121522 (check that simd_insert/extract indices are in-bounds)
- #121531 (Ignore less tests in debug builds)
- #121539 (compiler/rustc_target/src/spec/base/apple/tests.rs: Avoid unnecessary large move)
- #121542 (update stdarch)
r? `@ghost`
`@rustbot` modify labels: rollup
Account for RPITIT in E0310 explicit lifetime constraint suggestion
When given
```rust
trait Original {
fn f() -> impl Fn();
}
trait Erased {
fn f(&self) -> Box<dyn Fn()>;
}
impl<T: Original> Erased for T {
fn f(&self) -> Box<dyn Fn()> {
Box::new(<T as Original>::f())
}
}
```
emit do not emit an invalid suggestion restricting the `Trait::{opaque}` type in a `where` clause:
```
error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
--> $DIR/missing-static-bound-from-impl.rs:11:9
|
LL | Box::new(<T as Original>::f())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
| ...so that the type `impl Fn()` will meet its required lifetime bounds
```
Partially address #119773. Ideally we'd suggest modifying `Erased::f` instead.
r? `@compiler-errors`
region unification: update universe of region vars
necessary for #119106. see inline comment for why this is necessary
r? `@compiler-errors` `@BoxyUwU`
fix generalizer unsoundness
I ended up getting confused while trying to flip the variances when flipping the order. Should be all right now.
This is only exploitable when generalizing if the `ambient_variance` of the relation is `Contravariant`. This can currently only be the case in the NLL generalizer which only rarely generalizes, causing us to miss this regression. Very much an issue with #121462 however.
When given
```rust
trait Original {
fn f() -> impl Fn();
}
trait Erased {
fn f(&self) -> Box<dyn Fn()>;
}
impl<T: Original> Erased for T {
fn f(&self) -> Box<dyn Fn()> {
Box::new(<T as Original>::f())
}
}
```
avoid suggestion to restrict the `Trait::{opaque}` type in a `where` clause:
```
error[E0310]: the associated type `<T as Original>::{opaque#0}` may not live long enough
--> $DIR/missing-static-bound-from-impl.rs:11:9
|
LL | Box::new(<T as Original>::f())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the associated type `<T as Original>::{opaque#0}` must be valid for the static lifetime...
| ...so that the type `impl Fn()` will meet its required lifetime bounds
```
CC #119773.
Without doing so we use the same candidate cache entry
for `?0: Trait<?1>` and `?0: Trait<?0>`. These goals are different
and we must not use the same entry for them.
we don't track them when canonicalizing or when freshening,
resulting in instable caching in the old solver, and issues when
instantiating query responses in the new one.
Top level error handling
The interactions between the following things are surprisingly complicated:
- `emit_stashed_diagnostics`,
- `flush_delayed`,
- normal return vs `abort_if_errors`/`FatalError.raise()` unwinding in the call to the closure in `interface::run_compiler`.
This PR disentangles it all.
r? `@oli-obk`
Currently `has_errors` excludes lint errors. This commit changes it to
include lint errors.
The motivation for this is that for most places it doesn't matter
whether lint errors are included or not. But there are multiple places
where they must be includes, and only one place where they must not be
included. So it makes sense for `has_errors` to do the thing that fits
the most situations, and the new `has_errors_excluding_lint_errors`
method in the one exceptional place.
The same change is made for `err_count`. Annoyingly, this requires the
introduction of `err_count_excluding_lint_errs` for one place, to
preserve existing error printing behaviour. But I still think the change
is worthwhile overall.
Make --verbose imply -Z write-long-types-to-disk=no
When shortening the type it is necessary to take into account the `--verbose` flag, if it is activated, we must always show the entire type and not write it in a file.
Fixes: https://github.com/rust-lang/rust/issues/119130
Convert `delayed_bug`s to `bug`s.
I have a suspicion that quite a few delayed bug paths are impossible to reach, so I did an experiment.
I converted every `delayed_bug` to a `bug`, ran the full test suite, then converted back every `bug` that was hit. A surprising number were never hit.
This is too dangerous to merge. Increased coverage (fuzzing or a crater run) would likely hit more cases. But it might be useful for people to look at and think about which paths are genuinely unreachable.
r? `@ghost`
I have a suspicion that quite a few delayed bug paths are impossible to
reach, so I did an experiment.
I converted every `delayed_bug` to a `bug`, ran the full test suite,
then converted back every `bug` that was hit. A surprising number were
never hit.
The next commit will convert some more back, based on human judgment.
Overhaul `Diagnostic` and `DiagnosticBuilder`
Implements the first part of https://github.com/rust-lang/compiler-team/issues/722, which moves functionality and use away from `Diagnostic`, onto `DiagnosticBuilder`.
Likely follow-ups:
- Move things around, because this PR was written to minimize diff size, so some things end up in sub-optimal places. E.g. `DiagnosticBuilder` has impls in both `diagnostic.rs` and `diagnostic_builder.rs`.
- Rename `Diagnostic` as `DiagInner` and `DiagnosticBuilder` as `Diag`.
r? `@davidtwco`
return `ty::Error` when equating `ty::Error`
This helps iron out a difference in diagnostics between `Sub` and `Equate` relations, which I'm currently trying to unify.
r? oli-obk
Drive-by `DUMMY_SP` -> `Span` and fmt changes
Noticed these while doing something else. There's no practical change, but it's preferable to use `DUMMY_SP` as little as possible, particularly when we have perfectlly useful `Span`s available.
Currently many diagnostic modifier methods are available on both
`Diagnostic` and `DiagnosticBuilder`. This commit removes most of them
from `Diagnostic`. To minimize the diff size, it keeps them within
`diagnostic.rs` but changes the surrounding `impl Diagnostic` block to
`impl DiagnosticBuilder`. (I intend to move things around later, to give
a more sensible code layout.)
`Diagnostic` keeps a few methods that it still needs, like `sub`,
`arg`, and `replace_args`.
The `forward!` macro, which defined two additional methods per call
(e.g. `note` and `with_note`), is replaced by the `with_fn!` macro,
which defines one additional method per call (e.g. `with_note`). It's
now also only used when necessary -- not all modifier methods currently
need a `with_*` form. (New ones can be easily added as necessary.)
All this also requires changing `trait AddToDiagnostic` so its methods
take `DiagnosticBuilder` instead of `Diagnostic`, which leads to many
mechanical changes. `SubdiagnosticMessageOp` gains a type parameter `G`.
There are three subdiagnostics -- `DelayedAtWithoutNewline`,
`DelayedAtWithNewline`, and `InvalidFlushedDelayedDiagnosticLevel` --
that are created within the diagnostics machinery and appended to
external diagnostics. These are handled at the `Diagnostic` level, which
means it's now hard to construct them via `derive(Diagnostic)`, so
instead we construct them by hand. This has no effect on what they look
like when printed.
There are lots of new `allow` markers for `untranslatable_diagnostics`
and `diagnostics_outside_of_impl`. This is because
`#[rustc_lint_diagnostics]` annotations were present on the `Diagnostic`
modifier methods, but missing from the `DiagnosticBuilder` modifier
methods. They're now present.
deduplicate infer var instantiation
Having 3 separate implementations of one of the most subtle parts of our type system is not a good strategy if we want to maintain a sound type system ✨ while working on this I already found some subtle bugs in the existing code, so that's awesome 🎉 cc #121159
This was necessary as I am not confident in my nll changes in #119106, so I am first cleaning this up in a separate PR.
r? `@BoxyUwU`
Noticed these while doing something else. There's no practical change, but it's preferable to use `DUMMY_SP` as little as possible, particularly when we have perfectlly useful `Span`s available.
There are lots of functions that modify a diagnostic. This can be via a
`&mut Diagnostic` or a `&mut DiagnosticBuilder`, because the latter type
wraps the former and impls `DerefMut`.
This commit converts all the `&mut Diagnostic` occurrences to `&mut
DiagnosticBuilder`. This is a step towards greatly simplifying
`Diagnostic`. Some of the relevant function are made generic, because
they deal with both errors and warnings. No function bodies are changed,
because all the modifier methods are available on both `Diagnostic` and
`DiagnosticBuilder`.
fixes#117448
For example unnecessary imports in std::prelude that can be eliminated:
```rust
use std::option::Option::Some;//~ WARNING the item `Some` is imported redundantly
use std::option::Option::None; //~ WARNING the item `None` is imported redundantly
```
errors: only eagerly translate subdiagnostics
Subdiagnostics don't need to be lazily translated, they can always be eagerly translated. Eager translation is slightly more complex as we need to have a `DiagCtxt` available to perform the translation, which involves slightly more threading of that context.
This slight increase in complexity should enable later simplifications - like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages into the diagnostic structs rather than having them in separate files (working on that was what led to this change).
r? ```@nnethercote```
we already use `instantiate_const_var`. This does lose some debugging
info for nll because we stop populating the `reg_var_to_origin` table with
`RegionCtxt::Existential(None)`, I don't think that matters however.
Supporting this adds additional complexity to one of the most involved
parts of the type system, so I really don't think it's worth it.
Implement intrinsics with fallback bodies
fixes#93145 (though we can port many more intrinsics)
cc #63585
The way this works is that the backend logic for generating custom code for intrinsics has been made fallible. The only failure path is "this intrinsic is unknown". The `Instance` (that was `InstanceDef::Intrinsic`) then gets converted to `InstanceDef::Item`, which represents the fallback body. A regular function call to that body is then codegenned. This is currently implemented for
* codegen_ssa (so llvm and gcc)
* codegen_cranelift
other backends will need to adjust, but they can just keep doing what they were doing if they prefer (though adding new intrinsics to the compiler will then require them to implement them, instead of getting the fallback body).
cc `@scottmcm` `@WaffleLapkin`
### todo
* [ ] miri support
* [x] default intrinsic name to name of function instead of requiring it to be specified in attribute
* [x] make sure that the bodies are always available (must be collected for metadata)
Subdiagnostics don't need to be lazily translated, they can always be
eagerly translated. Eager translation is slightly more complex as we need
to have a `DiagCtxt` available to perform the translation, which involves
slightly more threading of that context.
This slight increase in complexity should enable later simplifications -
like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages
into the diagnostic structs rather than having them in separate files
(working on that was what led to this change).
Signed-off-by: David Wood <david@davidtw.co>
For some cases where it's clear that an error has already occurred,
e.g.:
- there's a comment stating exactly that, or
- things like HIR lowering, where we are lowering an error kind
The commit also tweaks some comments around delayed bug sites.
`cargo update`
Run `cargo update`, with some pinning and fixes necessitated by that. This *should* unblock #112865
There's a couple of places where I only pinned a dependency in one location - this seems like a bit of a hack, but better than duplicating the FIXME across all `Cargo.toml` where a dependency is introduced.
cc `@Nilstrieb`
Dejargonize `subst`
In favor of #110793, replace almost every occurence of `subst` and `substitution` from rustc codes, but they still remains in subtrees under `src/tools/` like clippy and test codes (I'd like to replace them after this)
The check within changed from `delay_span_bug` to `delay_good_path_bug`
in #110476, and removing the check altogether was considered. It's a
very weak sanity check and gets in the way of removing good path delayed
bugs altogether, so this PR just removes it.
Allow restricted trait impls under `#[allow_internal_unstable(min_specialization)]`
This is a follow-up to #119963 and a companion to #120866, though it can land independently from the latter.
---
We have several compiler crates that only enable `#[feature(min_specialization)]` because it is required by their expansions of `newtype_index!`, in order to implement traits marked with `#[rustc_specialization_trait]`.
This PR allows those traits to be implemented internally by macros with `#[allow_internal_unstable(min_specialization)]`, without needing specialization to be enabled in the enclosing crate.
Harmonize `AsyncFn` implementations, make async closures conditionally impl `Fn*` traits
This PR implements several changes to the built-in and libcore-provided implementations of `Fn*` and `AsyncFn*` to address two problems:
1. async closures do not implement the `Fn*` family traits, leading to breakage: https://crater-reports.s3.amazonaws.com/pr-120361/index.html
2. *references* to async closures do not implement `AsyncFn*`, as a consequence of the existing blanket impls of the shape `AsyncFn for F where F: Fn, F::Output: Future`.
In order to fix (1.), we implement `Fn` traits appropriately for async closures. It turns out that async closures can:
* always implement `FnOnce`, meaning that they're drop-in compatible with `FnOnce`-bound combinators like `Option::map`.
* conditionally implement `Fn`/`FnMut` if they have no captures, which means that existing usages of async closures should *probably* work without breakage (crater checking this: https://github.com/rust-lang/rust/pull/120712#issuecomment-1930587805).
In order to fix (2.), we make all of the built-in callables implement `AsyncFn*` via built-in impls, and instead adjust the blanket impls for `AsyncFn*` provided by libcore to match the blanket impls for `Fn*`.
These crates all needed specialization for `newtype_index!`, which will no
longer be necessary when the current nightly eventually becomes the next
bootstrap compiler.
Fix `ErrorGuaranteed` unsoundness with stash/steal.
When you stash an error, the error count is incremented. You can then use the non-zero error count to get an `ErrorGuaranteed`. You can then steal the error, which decrements the error count. You can then cancel the error.
Example code:
```
fn unsound(dcx: &DiagCtxt) -> ErrorGuaranteed {
let sp = rustc_span::DUMMY_SP;
let k = rustc_errors::StashKey::Cycle;
dcx.struct_err("bogus").stash(sp, k); // increment error count on stash
let guar = dcx.has_errors().unwrap(); // ErrorGuaranteed from error count > 0
let err = dcx.steal_diagnostic(sp, k).unwrap(); // decrement error count on steal
err.cancel(); // cancel error
guar // ErrorGuaranteed with no error emitted!
}
```
This commit fixes the problem in the simplest way: by not counting stashed errors in `DiagCtxt::{err_count,has_errors}`.
However, just doing this without any other changes leads to over 40 ui test failures. Mostly because of uninteresting extra errors (many saying "type annotations needed" when type inference fails), and in a few cases, due to delayed bugs causing ICEs when no normal errors are printed.
To fix these, this commit adds `DiagCtxt::stashed_err_count`, and uses it in three places alongside `DiagCtxt::{has_errors,err_count}`. It's dodgy to rely on it, because unlike `DiagCtxt::err_count` it can go up and down. But it's needed to preserve existing behaviour, and at least the three places that need it are now obvious.
r? oli-obk
Invert diagnostic lints.
That is, change `diagnostic_outside_of_impl` and `untranslatable_diagnostic` from `allow` to `deny`, because more than half of the compiler has been converted to use translated diagnostics.
This commit removes more `deny` attributes than it adds `allow` attributes, which proves that this change is warranted.
r? ````@davidtwco````
When you stash an error, the error count is incremented. You can then
use the non-zero error count to get an `ErrorGuaranteed`. You can then
steal the error, which decrements the error count. You can then cancel
the error.
Example code:
```
fn unsound(dcx: &DiagCtxt) -> ErrorGuaranteed {
let sp = rustc_span::DUMMY_SP;
let k = rustc_errors::StashKey::Cycle;
dcx.struct_err("bogus").stash(sp, k); // increment error count on stash
let guar = dcx.has_errors().unwrap(); // ErrorGuaranteed from error count > 0
let err = dcx.steal_diagnostic(sp, k).unwrap(); // decrement error count on steal
err.cancel(); // cancel error
guar // ErrorGuaranteed with no error emitted!
}
```
This commit fixes the problem in the simplest way: by not counting
stashed errors in `DiagCtxt::{err_count,has_errors}`.
However, just doing this without any other changes leads to over 40 ui
test failures. Mostly because of uninteresting extra errors (many saying
"type annotations needed" when type inference fails), and in a few
cases, due to delayed bugs causing ICEs when no normal errors are
printed.
To fix these, this commit adds `DiagCtxt::stashed_err_count`, and uses
it in three places alongside `DiagCtxt::{has_errors,err_count}`. It's
dodgy to rely on it, because unlike `DiagCtxt::err_count` it can go up
and down. But it's needed to preserve existing behaviour, and at least
the three places that need it are now obvious.
Remove unused args from functions
`#[instrument]` suppresses the unused arguments from a function, *and* suppresses unused methods too! This PR removes things which are only used via `#[instrument]` calls, and fixes some other errors (privacy?) that I will comment inline.
It's possible that some of these arguments were being passed in for the purposes of being instrumented, but I am unconvinced by most of them.
Introduce `enter_forall` to supercede `instantiate_binder_with_placeholders`
r? `@lcnr`
Long term we'd like to experiment with decrementing the universe count after "exiting" binders so that we do not end up creating infer vars in non-root universes even when they logically reside in the root universe. The fact that we dont do this currently results in a number of issues in the new trait solver where we consider goals to be ambiguous because otherwise it would require lowering the universe of an infer var. i.e. the goal `?x.0 eq <T as Trait<?y.1>>::Assoc` where the alias is rigid would not be able to instantiate `?x` with the alias as there would be a universe error.
This PR is the first-ish sort of step towards being able to implement this as eventually we would want to decrement the universe in `enter_forall`. Unfortunately its Difficult to actually implement decrementing universes nicely so this is a separate step which moves us closer to the long term goal ✨
Normalize type outlives obligations in NLL for new solver
Normalize the type outlives assumptions and obligations in MIR borrowck. This should fix any of the lazy-norm-related MIR borrowck problems.
Also some cleanups from last PR:
1. Normalize obligations in a loop in lexical region resolution
2. Use `deeply_normalize_with_skipped_universes` in lexical resolution since we may have, e.g. `for<'a> Alias<'a>: 'b`.
r? lcnr
That is, change `diagnostic_outside_of_impl` and
`untranslatable_diagnostic` from `allow` to `deny`, because more than
half of the compiler has be converted to use translated diagnostics.
This commit removes more `deny` attributes than it adds `allow`
attributes, which proves that this change is warranted.
- `emitted_at` isn't used outside the crate.
- `code` and `messages` are public fields, so there's no point have
trivial getters/setters for them.
- `suggestions` is public, so the comment about "functionality on
`Diagnostic`" isn't needed.
Normalize region obligation in lexical region resolution with next-gen solver
This normalizes region obligations when we `resolve_regions`, since they may be unnormalized with deferred projection equality.
It's pretty hard to add tests that exercise this without also triggering MIR borrowck errors (because we don't normalize there yet). I've added one test with two revisions that should test that we both 1. normalize region obligations in the param env, and 2. normalize registered region obligations during lexical region resolution.
Remove various `has_errors` or `err_count` uses
follow up to https://github.com/rust-lang/rust/pull/119895
r? `@nnethercote` since you recently did something similar.
There are so many more of these, but I wanted to get a PR out instead of growing the commit list indefinitely. The commits all work on their own and can be reviewed commit by commit.
Because it's almost always static.
This makes `impl IntoDiagnosticArg for DiagnosticArgValue` trivial,
which is nice.
There are a few diagnostics constructed in
`compiler/rustc_mir_build/src/check_unsafety.rs` and
`compiler/rustc_mir_transform/src/errors.rs` that now need symbols
converted to `String` with `to_string` instead of `&str` with `as_str`,
but that' no big deal, and worth it for the simplifications elsewhere.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
When encountering a type mismatch error involving `dyn Trait`, mention
the existence of boxed trait objects if the other type involved
implements `Trait`.
Partially addresses #102629.
Provide structured suggestion to use trait objects in some cases of `if` arm type divergence
```
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:15:9
|
LL | let _ = if true {
| _____________-
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | foo()
| | ^^^^^ expected `Struct`, found `Box<dyn Trait>`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Struct`
found struct `Box<dyn Trait>`
help: `Struct` implements `Trait` so you can box it to coerce to the trait object `Box<dyn Trait>`
|
LL | Box::new(Struct)
| +++++++++ +
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:20:9
|
LL | let _ = if true {
| _____________-
LL | | foo()
| | ----- expected because of this
LL | | } else {
LL | | Struct
| | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Box<dyn Trait>`
found struct `Struct`
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
help: store this in the heap by calling `Box::new`
|
LL | Box::new(Struct)
| +++++++++ +
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:25:9
|
LL | fn bar() -> impl Trait {
| ---------- the found opaque type
...
LL | let _ = if true {
| _____________-
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | bar()
| | ^^^^^ expected `Struct`, found opaque type
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Struct`
found opaque type `impl Trait`
help: `Struct` implements `Trait` so you can box both arms and coerce to the trait object `Box<dyn Trait>`
|
LL ~ Box::new(Struct) as Box<dyn Trait>
LL | } else {
LL ~ Box::new(bar())
|
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:30:9
|
LL | fn bar() -> impl Trait {
| ---------- the expected opaque type
...
LL | let _ = if true {
| _____________-
LL | | bar()
| | ----- expected because of this
LL | | } else {
LL | | Struct
| | ^^^^^^ expected opaque type, found `Struct`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected opaque type `impl Trait`
found struct `Struct`
help: `Struct` implements `Trait` so you can box both arms and coerce to the trait object `Box<dyn Trait>`
|
LL ~ Box::new(bar()) as Box<dyn Trait>
LL | } else {
LL ~ Box::new(Struct)
|
```
Partially address #102629.
When encountering
```rust
let _ = if true {
Struct
} else {
foo() // -> Box<dyn Trait>
};
```
if `Struct` implements `Trait`, suggest boxing the then arm tail expression.
Part of #102629.
We have several methods indicating the presence of errors, lint errors,
and delayed bugs. I find it frustrating that it's very unclear which one
you should use in any particular spot. This commit attempts to instill a
basic principle of "use the least general one possible", because that
reflects reality in practice -- `has_errors` is the least general one
and has by far the most uses (esp. via `abort_if_errors`).
Specifics:
- Add some comments giving some usage guidelines.
- Prefer `has_errors` to comparing `err_count` to zero.
- Remove `has_errors_or_span_delayed_bugs` because it's a weird one: in
the cases where we need to count delayed bugs, we should really be
counting lint errors as well.
- Rename `is_compilation_going_to_fail` as
`has_errors_or_lint_errors_or_span_delayed_bugs`, for consistency with
`has_errors` and `has_errors_or_lint_errors`.
- Change a few other `has_errors_or_lint_errors` calls to `has_errors`,
as per the "least general" principle.
This didn't turn out to be as neat as I hoped when I started, but I
think it's still an improvement.
Expose Obligations created during type inference.
This PR is a first pass at exposing the trait obligations generated and solved for during the type-check progress. Exposing these obligations allows for rustc plugins to use the public interface for proof trees (provided by the next gen trait solver).
The changes proposed track *all* obligations during the type-check process, this is desirable to not only look at the trees of failed obligations, but also those of successfully proved obligations. This feature is placed behind an unstable compiler option `track-trait-obligations` which should be used together with the `next-solver` option. I should note that the main interface is the function `inspect_typeck` made public in `rustc_hir_typeck/src/lib.rs` which allows the caller to provide a callback granting access to the `FnCtxt`.
r? `@lcnr`
Pass each obligation to an fn callback with its respective inference context. This avoids needing to keep around copies of obligations or inference contexts.
Specify usability of inspect_typeck in comment.
Rework how diagnostic lints are stored.
`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.
r? `@oli-obk`
Make sure to instantiate placeholders correctly in old solver
When creating the query substitution guess for an input placeholder type like `!1_T` (in universe 1), we were guessing the response substitution with something like `!0_T`. This failed to unify with `!1_T`, causing an ICE.
This PR reworks the query substitution guess code to work a bit more like the new solver. I'm *pretty* sure this is correct, though I'd really appreciate some scrutiny from someone (*cough* lcnr) who knows a bit more about query instantiation :)
Fixes#119941
r? lcnr
`OutputTypeParameterMismatch` -> `SignatureMismatch`
I'm probably missing something that made this rename more complicated. What did you end up getting stuck on when renaming this selection error, `@lcnr?`
**also** I renamed the `FulfillmentErrorCode` variants. This is just churn but I wanted to do it forever. I can move it out of this PR if desired.
r? lcnr
Silence some follow-up errors [3/x]
this is one piece of the requested cleanups from https://github.com/rust-lang/rust/pull/117449
Keep error types around, even in obligations.
These help silence follow-up errors, as we now figure out that some types (most notably inference variables) are equal to an error type.
But it also allows figuring out more types in the presence of errors, possibly causing more errors.
`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.
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.
We have `span_delayed_bug` and often pass it a `DUMMY_SP`. This commit
adds `delayed_bug`, which matches pairs like `err`/`span_err` and
`warn`/`span_warn`.
Because it takes an error code after the span. This avoids the confusing
overlap with the `DiagCtxt::struct_span_err` method, which doesn't take
an error code.
unify query canonicalization mode
Exclude from canonicalization only the static lifetimes that appear in the param env because of #118965 . Any other occurrence can be canonicalized safely AFAICT.
r? `@lcnr`
The existing uses are replaced in one of three ways.
- In a function that also has calls to `emit`, just rearrange the code
so that exactly one of `delay_as_bug` or `emit` is called on every
path.
- In a function returning a `DiagnosticBuilder`, use
`downgrade_to_delayed_bug`. That's good enough because it will get
emitted later anyway.
- In `unclosed_delim_err`, one set of errors is being replaced with
another set, so just cancel the original errors.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
Use `resolutions(()).effective_visiblities` to avoid cycle errors in `report_object_error`
Inside of `report_object_error`, using the `effective_visibilities` query causes cycles since it calls `type_of`, which itself may call `typeck`, which may end up reporting its own object-safety errors.
Fixes#119346Fixes#119502
Tweak suggestions for bare trait used as a type
```
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/not-on-bare-trait-2021.rs:11:11
|
LL | fn bar(x: Foo) -> Foo {
| ^^^
|
help: use a generic type parameter, constrained by the trait `Foo`
|
LL | fn bar<T: Foo>(x: T) -> Foo {
| ++++++++ ~
help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference
|
LL | fn bar(x: impl Foo) -> Foo {
| ++++
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
|
LL | fn bar(x: &dyn Foo) -> Foo {
| ++++
error[E0782]: trait objects must include the `dyn` keyword
--> $DIR/not-on-bare-trait-2021.rs:11:19
|
LL | fn bar(x: Foo) -> Foo {
| ^^^
|
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
|
LL | fn bar(x: Foo) -> impl Foo {
| ++++
help: alternatively, you can return an owned trait object
|
LL | fn bar(x: Foo) -> Box<dyn Foo> {
| +++++++ +
```
Fix#119525:
```
error[E0038]: the trait `Ord` cannot be made into an object
--> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
|
LL | fn ord_prefer_dot(s: String) -> Ord {
| ^^^ `Ord` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
::: $SRC_DIR/core/src/cmp.rs:LL:COL
|
= note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
|
LL | fn ord_prefer_dot(s: String) -> impl Ord {
| ++++
```
`Diagnostic` has 40 methods that return `&mut Self` and could be
considered setters. Four of them have a `set_` prefix. This doesn't seem
necessary for a type that implements the builder pattern. This commit
removes the `set_` prefixes on those four methods.
Implement constant propagation on top of MIR SSA analysis
This implements the idea I proposed in https://github.com/rust-lang/rust/pull/110719#issuecomment-1718324700
Based on https://github.com/rust-lang/rust/pull/109597
The value numbering "GVN" pass formulates each rvalue that appears in MIR with an abstract form (the `Value` enum), and assigns an integer `VnIndex` to each. This abstract form can be used to deduplicate values, reusing an earlier local that holds the same value instead of recomputing. This part is proposed in #109597.
From this abstract representation, we can perform more involved simplifications, for example in https://github.com/rust-lang/rust/pull/111344.
With the abstract representation `Value`, we can also attempt to evaluate each to a constant using the interpreter. This builds a `VnIndex -> OpTy` map. From this map, we can opportunistically replace an operand or a rvalue with a constant if their value has an associated `OpTy`.
The most relevant commit is [Evaluated computed values to constants.](2767c4912e)"
r? `@oli-obk`
rework `-Zverbose`
implements the changes described in https://github.com/rust-lang/compiler-team/issues/706
the first commit is only a name change from `-Zverbose` to `-Zverbose-internals` and does not change behavior. the second commit changes diagnostics.
possible follow up work:
- `ty::pretty` could print more info with `--verbose` than it does currently. `-Z verbose-internals` shows too much info in a way that's not helpful to users. michael had ideas about this i didn't fully understand: https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/uplift.20some.20-Zverbose.20calls.20and.20rename.20to.E2.80.A6.20compiler-team.23706/near/408984200
- `--verbose` should imply `-Z write-long-types-to-disk=no`. the code in `ty_string_with_limit` should take `--verbose` into account (apparently this affects `Ty::sort_string`, i'm not familiar with this code). writing a file to disk should suggest passing `--verbose`.
r? `@compiler-errors` cc `@estebank`
`IntoDiagnostic` defaults to `ErrorGuaranteed`, because errors are the
most common diagnostic level. It makes sense to do likewise for the
closely-related (and much more widely used) `DiagnosticBuilder` type,
letting us write `DiagnosticBuilder<'a, ErrorGuaranteed>` as just
`DiagnosticBuilder<'a>`. This cuts over 200 lines of code due to many
multi-line things becoming single line things.
subtype_predicate: remove unnecessary probe
There is no reason to probe here. The failure either results in an actual type error, in which cases the probe is useless, or it is used inside of evaluate, in which case we're already inside of the `fn evaluation_probe`, so it is also not necessary.
Yeet unnecessary param envs
We don't need to pass in param-envs around in the lexical region resolution code (or in `MatchAgainstFreshVars` in the solver), since it is only used to eval some consts in `structurally_relate_tys` which I removed.
This is in preparation for normalizing the outlives clauses in `ParamEnv` for the new trait solver.
r? lcnr
This commit replaces this pattern:
```
err.into_diagnostic(dcx)
```
with this pattern:
```
dcx.create_err(err)
```
in a lot of places.
It's a little shorter, makes the error level explicit, avoids some
`IntoDiagnostic` imports, and is a necessary prerequisite for the next
commit which will add a `level` arg to `into_diagnostic`.
This requires adding `track_caller` on `create_err` to avoid mucking up
the output of `tests/ui/track-diagnostics/track4.rs`. It probably should
have been there already.
Collect lang items from AST, get rid of `GenericBound::LangItemTrait`
r? `@cjgillot`
cc #115178
Looking forward, the work to remove `QPath::LangItem` will also be significantly more difficult, but I plan on doing it as well. Specifically, we have to change:
1. A lot of `rustc_ast_lowering` for things like expr `..`
2. A lot of astconv, since we actually instantiate lang and non-lang paths quite differently.
3. A ton of diagnostics and clippy lints that are special-cased via `QPath::LangItem`
Meanwhile, it was pretty easy to remove `GenericBound::LangItemTrait`, so I just did that here.
cache param env canonicalization
Canonicalize ParamEnv only once and store it. Then whenever we try to canonicalize `ParamEnvAnd<'tcx, T>` we only have to canonicalize `T` and then merge the results.
Prelimiary results show ~3-4% savings in diesel and serde benchmarks.
Best to review commits individually. Some commits have a short description.
Initial implementation had a soundness bug (https://github.com/rust-lang/rust/pull/117749#issuecomment-1840453387) due to cache invalidation:
- When canonicalizing `Ty<'?0>` we first try to resolve region variables in the current InferCtxt which may have a constraint `?0 == 'static`. This means that we register `Ty<'?0> => Canonical<Ty<'static>>` in the cache, which is obviously incorrect in another inference context.
- This is fixed by not doing region resolution when canonicalizing the query *input* (vs. response), which is the only place where ParamEnv is used, and then in a later commit we *statically* guard against any form of inference variable resolution of the cached canonical ParamEnv's.
r? `@ghost`
This doesn't change behavior.
It should prevent unintentional resolution of inference variables
during canonicalization, which previously caused a soundness bug.
See PR description for more.
ParamEnv is canonicalized in *queries input* rather than query response.
In such case we don't "preserve universes" of canonical variable.
This means that `universe_map` always has the default value, which is
wasteful to store in the cache.
Renamings:
- find -> opt_hir_node
- get -> hir_node
- find_by_def_id -> opt_hir_node_by_def_id
- get_by_def_id -> hir_node_by_def_id
Fix rebase changes using removed methods
Use `tcx.hir_node_by_def_id()` whenever possible in compiler
Fix clippy errors
Fix compiler
Apply suggestions from code review
Co-authored-by: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Add FIXME for `tcx.hir()` returned type about its removal
Simplify with with `tcx.hir_node_by_def_id`