Disallow ambiguous attributes on expressions
This implements the suggestion in [#15701](https://github.com/rust-lang/rust/issues/15701#issuecomment-2033124217) to disallow ambiguous outer attributes on expressions. This should resolve one of the concerns blocking the stabilization of `stmt_expr_attributes`.
Improve handling of expr->field errors
The current message for "`->` used for field access" is the following:
```rust
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `->`
--> src/main.rs:2:6
|
2 | a->b;
| ^^ expected one of 8 possible tokens
```
([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7f8b6f4433aa7866124123575456f54e))
This PR tries to address this by adding a dedicated error message and recovery. The proposed error message is:
```
error: `->` used for field access or method call
--> ./tiny_test.rs:2:6
|
2 | a->b;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed
```
(feel free to bikeshed it as much as necessary)
The current message for "`->` used for field access" is the following:
```rust
error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `->`
--> src/main.rs:2:6
|
2 | a->b;
| ^^ expected one of 8 possible tokens
```
(playground link[1])
This PR tries to address this by adding a dedicated error message and recovery. The proposed error message is:
```
error: `->` used for field access or method call
--> ./tiny_test.rs:2:6
|
2 | a->b;
| ^^ help: try using `.` instead
|
= help: the `.` operator will dereference the value if needed
```
(feel free to bikeshed it as much as necessary)
[1]: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7f8b6f4433aa7866124123575456f54e
Signed-off-by: Sasha Pourcelot <sasha.pourcelot@protonmail.com>
The suggestion to use `let else` with an uninitialized refutable `let`
statement was erroneous: `let else` cannot be used with deferred
initialization.
Improve diagnostic by suggesting to remove visibility qualifier
Resolves#123529
This PR improve diagnostic by suggesting to remove visibility qualifier.
Suggest associated type bounds on problematic associated equality bounds
Fixes#105056. TL;DR: Suggest `Trait<Ty: Bound>` on `Trait<Ty = Bound>` in Rust >=2021.
~~Blocked on #122055 (stabilization of `associated_type_bounds`), I'd say.~~ (merged)
Validate that we're only matching on unit struct for path pattern
Resolution doesn't validate that we only really take `CtorKind::Unit` in path patterns, since all it sees is `Res::SelfCtor(def_id)`. Check this instead during pattern typeck.
r? petrochenkov
Fixes#122809
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.
Ensure stack before parsing dot-or-call
There are many cases where, due to codegen or a massively unruly codebase, a deeply nested `call(call(call(call(call(call(call(call(call(f())))))))))` can happen. This is a spot where it would be good to grow our stack, so that we can survive to tell the programmer their code is dubiously written.
Closes https://github.com/rust-lang/rust/issues/122715
There are many cases where, due to codegen or a massively unruly codebase,
a deeply nested call(call(call(call(call(call(call(call(call(f())))))))))
can happen. This is a spot where it would be good to grow our stack, so that
we can survive to tell the programmer their code is dubiously written.
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
```
error: `S2<'_>` is forbidden as the type of a const generic parameter
--> $DIR/lifetime-in-const-param.rs:5:23
|
LL | struct S<'a, const N: S2>(&'a ());
| ^^
|
= note: the only supported types are integers, `bool` and `char`
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
LL + #![feature(adt_const_params)]
|
```
Fix#55941.
Eagerly translate `HelpUseLatestEdition` in parser diagnostics
Fixes#122130.
This makes me suspicious of these other two usage of `add_to_diagnostic()`. Would they *also* crash? I haven't attempted to construct test cases for them.
```
compiler/rustc_parse/src/parser/expr.rs
3453: errors::HelpUseLatestEdition::new().add_to_diagnostic(e);
compiler/rustc_hir_typeck/src/expr.rs
2603: HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
```
This also seems like a footgun?
AST validation: Improve handling of inherent impls nested within functions and anon consts
Minimal fix for issue #121607 extracted from PR #120698 for ease of backporting and since I'd like to improve PR #120698 in such a way that it makes AST validator truly robust against such sort of regressions (AST validator is generally *beyond* footgun-y atm). The current version of PR #120698 sort of does that already but there's still room for improvement.
Fixes#89342.
Fixes [after beta-backport] #121607.
Partially addresses #119924 (#120698 aims to fully fix it).
---
### Explainer
The last commit of PR #119505 regressed issue #121607.
Previously we would reject visibilities on associated items with `visibility_not_permitted` if we were in a trait (by checking the parameter `ctxt` of `visit_assoc_item` which was 100% accurate) or if we were in a trait impl (by checking a flag called `in_trait_impl` tracked in `AstValidator` which was/is only accurate if the visitor methods correctly updated it which isn't actually the case giving rise to the old open issue #89342).
In PR #119505, I moved even more state into the `AstValidator` by generalizing the flag `in_trait_impl` to `trait_or_trait_impl` to be able to report more precise diagnostics (modeling *Trait | TraitImpl*). However since we/I didn't update `trait_or_trait_impl` in all places to reflect reality (similar to us not updating `in_trait_impl` before), this lead to https://github.com/rust-lang/rust/issues/121607#issuecomment-1963084636 getting wrongfully rejected. Since PR #119505 we reject visibilities if the “globally tracked” (wrt. to `AstValidator`) `outer_trait_or_trait_impl` is `Some`.
Crucially, when visiting an inherent impl, I never reset `outer_trait_or_trait_impl` back to `None` leading us to believe that `bar` in the stack [`trait Foo` > `fn foo` > `impl Bar` > `pub fn bar`] (from the MCVE) was an inherent associated item (we saw `trait Foo` but not `impl Bar` before it).
The old open issue #89342 is caused by the aforementioned issue of us never updating `in_trait_impl` prior to my PR #119505 / `outer_trait_or_trait` after my PR. Stack: [`impl Default for Foo` > `{` > `impl Foo` > `pub const X`] (we only saw `impl Default for Foo` but not the `impl Foo` before it).
---
This PR is only meant to be a *hot fix*. I plan on completely *rewriting* `AstValidator` from the ground up to not rely on “globally tracked” state like this or at least make it close to impossible to forget updating it when descending into nested items (etc.). Other visitors do a way better job at that (e.g. AST lowering). I actually plan on experimenting with moving more and more logic from `AstValidator` into the AST lowering pass/stage/visitor to follow the [Parse, don't validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) “pattern”.
---
r? `@compiler-errors`
Detect more cases of `=` to `:` typo
When a `Local` is fully parsed, but not followed by a `;`, keep the `:` span arround and mention it. If the type could continue being parsed as an expression, suggest replacing the `:` with a `=`.
```
error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.`
--> file.rs:2:32
|
2 | let _: std::env::temp_dir().join("foo");
| - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=`
| |
| while parsing the type for `_`
| help: use `=` if you meant to assign
```
Fix#119665.
Add stubs in IR and ABI for `f16` and `f128`
This is the very first step toward the changes in https://github.com/rust-lang/rust/pull/114607 and the [`f16` and `f128` RFC](https://rust-lang.github.io/rfcs/3453-f16-and-f128.html). It adds the types to `rustc_type_ir::FloatTy` and `rustc_abi::Primitive`, and just propagates those out as `unimplemented!` stubs where necessary.
These types do not parse yet so there is no feature gate, and it should be okay to use `unimplemented!`.
The next steps will probably be AST support with parsing and the feature gate.
r? `@compiler-errors`
cc `@Nilstrieb` suggested breaking the PR up in https://github.com/rust-lang/rust/pull/120645#issuecomment-1925900572
When a `Local` is fully parsed, but not followed by a `;`, keep the `:` span
arround and mention it. If the type could continue being parsed as an
expression, suggest replacing the `:` with a `=`.
```
error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.`
--> file.rs:2:32
|
2 | let _: std::env::temp_dir().join("foo");
| - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=`
| |
| while parsing the type for `_`
| help: use `=` if you meant to assign
```
Fix#119665.
- Put every literal in its own braces, rather than just some of them,
for maximal error recovery.
- Add a blank line between every case, for readability.