Use parenthetical notation for `Fn` traits
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.
Address #67100:
```
error[E0277]: expected a `Fn()` closure, found `F`
--> file.rs:6:13
|
6 | call_fn(f)
| ------- ^ expected an `Fn()` closure, found `F`
| |
| required by a bound introduced by this call
|
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
--> file.rs:1:15
|
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
| ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
|
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
| ++++++
```
Rename HIR `TypeBinding` to `AssocItemConstraint` and related cleanup
Rename `hir::TypeBinding` and `ast::AssocConstraint` to `AssocItemConstraint` and update all items and locals using the old terminology.
Motivation: The terminology *type binding* is extremely outdated. "Type bindings" not only include constraints on associated *types* but also on associated *constants* (feature `associated_const_equality`) and on RPITITs of associated *functions* (feature `return_type_notation`). Hence the word *item* in the new name. Furthermore, the word *binding* commonly refers to a mapping from a binder/identifier to a "value" for some definition of "value". Its use in "type binding" made sense when equality constraints (e.g., `AssocTy = Ty`) were the only kind of associated item constraint. Nowadays however, we also have *associated type bounds* (e.g., `AssocTy: Bound`) for which the term *binding* doesn't make sense.
---
Old terminology (HIR, rustdoc):
```
`TypeBinding`: (associated) type binding
├── `Constraint`: associated type bound
└── `Equality`: (associated) equality constraint (?)
├── `Ty`: (associated) type binding
└── `Const`: associated const equality (constraint)
```
Old terminology (AST, abbrev.):
```
`AssocConstraint`
├── `Bound`
└── `Equality`
├── `Ty`
└── `Const`
```
New terminology (AST, HIR, rustdoc):
```
`AssocItemConstraint`: associated item constraint
├── `Bound`: associated type bound
└── `Equality`: associated item equality constraint OR associated item binding (for short)
├── `Ty`: associated type equality constraint OR associated type binding (for short)
└── `Const`: associated const equality constraint OR associated const binding (for short)
```
r? compiler-errors
Always use the `Fn(T) -> R` format when printing closure traits instead of `Fn<(T,), Output = R>`.
Fix#67100:
```
error[E0277]: expected a `Fn()` closure, found `F`
--> file.rs:6:13
|
6 | call_fn(f)
| ------- ^ expected an `Fn()` closure, found `F`
| |
| required by a bound introduced by this call
|
= note: wrap the `F` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `call_fn`
--> file.rs:1:15
|
1 | fn call_fn<F: Fn() -> ()>(f: &F) {
| ^^^^^^^^^^ required by this bound in `call_fn`
help: consider further restricting this bound
|
5 | fn call_any<F: std::any::Any + Fn()>(f: &F) {
| ++++++
```
This adds the `only-apple`/`ignore-apple` compiletest directive, and
uses that basically everywhere instead of `only-macos`/`ignore-macos`.
Some of the updates in `run-make` are a bit redundant, as they use
`ignore-cross-compile` and won't run on iOS - but using Apple in these
is still more correct, so I've made that change anyhow.
Remove suggestion about iteration count in coerce
Fixes#122561
The iteration count-centric suggestion was implemented in PR #100094, but it was based on the wrong assumption that the type mismatch error depends on the number of times the loop iterates. As it turns out, that is not true (see this comment for details: https://github.com/rust-lang/rust/pull/122679#issuecomment-2017432531)
This PR attempts to remedy the situation by changing the suggestion from the one centered on iteration count to a simple suggestion to add a return value.
It should also fix#100285 by simply making it redundant.
and replace it with a simple note suggesting
returning a value.
The type mismatch error was never due to
how many times the loop iterates. It is more
because of the peculiar structure of what the for
loop desugars to. So the note talking about
iteration count didn't make sense
Don't ICE when `codegen_select_candidate` returns ambiguity in new solver
Because we merge identical candidates, we may have >1 impl candidate to in `codegen_select_error` but *not* have a trait error.
r? lcnr
```
error[E0382]: use of moved value: `t`
--> $DIR/use_of_moved_value_copy_suggestions.rs:7:9
|
LL | fn duplicate_t<T>(t: T) -> (T, T) {
| - move occurs because `t` has type `T`, which does not implement the `Copy` trait
...
LL | (t, t)
| - ^ value used here after move
| |
| value moved here
|
help: if `T` implemented `Clone`, you could clone the value
--> $DIR/use_of_moved_value_copy_suggestions.rs:4:16
|
LL | fn duplicate_t<T>(t: T) -> (T, T) {
| ^ consider constraining this type parameter with `Clone`
...
LL | (t, t)
| - you could clone this value
help: consider restricting type parameter `T`
|
LL | fn duplicate_t<T: Copy>(t: T) -> (T, T) {
| ++++++
```
The `help` is new. On ADTs, we also extend the output with span labels:
```
error[E0507]: cannot move out of static item `FOO`
--> $DIR/issue-17718-static-move.rs:6:14
|
LL | let _a = FOO;
| ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
|
note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/issue-17718-static-move.rs:1:1
|
LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type
...
LL | let _a = FOO;
| --- you could clone this value
help: consider borrowing here
|
LL | let _a = &FOO;
| +
```
Use the rustc_private libc less in tests
I started looking into our use of `rustc_private` + `extern crate libc;` in tests because of https://github.com/rust-lang/rust/pull/123938 and it looks like some fraction of the users of libc simply don't need the libc crate anymore.
Detect borrow checker errors where `.clone()` would be an appropriate user action
When a value is moved twice, suggest cloning the earlier move:
```
error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
--> $DIR/union-move.rs:49:18
|
LL | move_out(x.f1_nocopy);
| ^^^^^^^^^^^
| |
| cannot move out of here
| move occurs because `x.f1_nocopy` has type `ManuallyDrop<RefCell<i32>>`, which does not implement the `Copy` trait
|
help: consider cloning the value if the performance cost is acceptable
|
LL | move_out(x.f1_nocopy.clone());
| ++++++++
```
When a value is borrowed by an `fn` call, consider if cloning the result of the call would be reasonable, and suggest cloning that, instead of the argument:
```
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:53:14
|
LL | let a = AffineU32(1);
| - binding `a` declared here
LL | let x = bat(&a);
| -- borrow of `a` occurs here
LL | drop(a);
| ^ move out of `a` occurs here
LL | drop(x);
| - borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL | let x = bat(&a).clone();
| ++++++++
```
otherwise, suggest cloning the argument:
```
error[E0505]: cannot move out of `a` because it is borrowed
--> $DIR/variance-issue-20533.rs:59:14
|
LL | let a = ClonableAffineU32(1);
| - binding `a` declared here
LL | let x = foo(&a);
| -- borrow of `a` occurs here
LL | drop(a);
| ^ move out of `a` occurs here
LL | drop(x);
| - borrow later used here
|
help: consider cloning the value if the performance cost is acceptable
|
LL - let x = foo(&a);
LL + let x = foo(a.clone());
|
```
This suggestion doesn't attempt to square out the types between what's cloned and what the `fn` expects, to allow the user to make a determination on whether to change the `fn` call or `fn` definition themselves.
Special case move errors caused by `FnOnce`:
```
error[E0382]: use of moved value: `blk`
--> $DIR/once-cant-call-twice-on-heap.rs:8:5
|
LL | fn foo<F:FnOnce()>(blk: F) {
| --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
LL | blk();
| ----- `blk` moved due to this call
LL | blk();
| ^^^ value used here after move
|
note: `FnOnce` closures can only be called once
--> $DIR/once-cant-call-twice-on-heap.rs:6:10
|
LL | fn foo<F:FnOnce()>(blk: F) {
| ^^^^^^^^ `F` is made to be an `FnOnce` closure here
LL | blk();
| ----- this value implements `FnOnce`, which causes it to be moved when called
```
Account for redundant `.clone()` calls in resulting suggestions:
```
error[E0507]: cannot move out of dereference of `S`
--> $DIR/needs-clone-through-deref.rs:15:18
|
LL | for _ in self.clone().into_iter() {}
| ^^^^^^^^^^^^ ----------- value moved due to this method call
| |
| move occurs because value has type `Vec<usize>`, which does not implement the `Copy` trait
|
note: `into_iter` takes ownership of the receiver `self`, which moves value
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
help: you can `clone` the value and consume it, but this might not be your desired behavior
|
LL | for _ in <Vec<usize> as Clone>::clone(&self).into_iter() {}
| ++++++++++++++++++++++++++++++ ~
```
We use the presence of `&mut` values in a move error as a proxy for the user caring about side effects, so we don't emit a clone suggestion in that case:
```
error[E0505]: cannot move out of `s` because it is borrowed
--> $DIR/borrowck-overloaded-index-move-index.rs:53:7
|
LL | let mut s = "hello".to_string();
| ----- binding `s` declared here
LL | let rs = &mut s;
| ------ borrow of `s` occurs here
...
LL | f[s] = 10;
| ^ move out of `s` occurs here
...
LL | use_mut(rs);
| -- borrow later used here
```
We properly account for `foo += foo;` errors where we *don't* suggest `foo.clone() += foo;`, instead suggesting `foo += foo.clone();`.
---
Each commit can be reviewed in isolation. There are some "cleanup" commits, but kept them separate in order to show *why* specific changes were being made, and their effect on tests' output.
Fix#49693, CC #64167.
Improve diagnostic by suggesting to remove visibility qualifier
Resolves#123529
This PR improve diagnostic by suggesting to remove visibility qualifier.
```
error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure
--> $DIR/issue-87456-point-to-closure.rs:10:28
|
LL | let val = String::new();
| --- captured outer variable
LL |
LL | take_mut(|| {
| -- captured by this `FnMut` closure
LL |
LL | let _foo: String = val;
| ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
LL | let _foo: String = &val;
| +
help: consider cloning the value if the performance cost is acceptable
|
LL | let _foo: String = val.clone();
| ++++++++
```
```
error[E0507]: cannot move out of `*x` which is behind a shared reference
--> $DIR/borrowck-fn-in-const-a.rs:6:16
|
LL | return *x
| ^^ move occurs because `*x` has type `String`, which does not implement the `Copy` trait
|
help: consider cloning the value if the performance cost is acceptable
|
LL - return *x
LL + return x.clone()
|
```
Tweak value suggestions in `borrowck` and `hir_analysis`
Unify the output of `suggest_assign_value` and `ty_kind_suggestion`.
Ideally we'd make these a single function, but doing so would likely require modify the crate dependency tree.
Rework ptr-to-ref conversion suggestion for method calls
If we have a value `z` of type `*const u8` and try to call `z.to_string()`, the upstream compiler will show you a note suggesting to call `<*const u8>::as_ref` first.
This PR extends that:
- The note will only be shown when the method would exist on the corresponding reference type
- It can now suggest any of `<*const u8>::as_ref`, `<*mut u8>::as_ref` and `<*mut u8>::as_mut`, depending on what the method needs.
I didn't introduce a `help` message because that's not a good idea with `unsafe` functions (and you'd also need to unwrap the `Option<&_>` somehow).
People should check the safety requirements.
For the simplest case
```rust
fn main() {
let x = 8u8;
let z: *const u8 = &x;
// issue #21596
println!("{}", z.to_string()); //~ ERROR E0599
}
```
the output changes like this:
```diff
error[E0599]: `*const u8` doesn't implement `std::fmt::Display`
--> $DIR/suggest-convert-ptr-to-ref.rs:5:22
|
LL | println!("{}", z.to_string());
| ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter
|
- = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
- = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
+note: the method `to_string` exists on the type `&u8`
+ --> $SRC_DIR/alloc/src/string.rs:LL:COL
+ = note: try using the unsafe method `<*const T>::as_ref` to get an optional reference to the value behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
= note: the following trait bounds were not satisfied:
`*const u8: std::fmt::Display`
which is required by `*const u8: ToString`
```
I removed the separate note about the safety requirements because it was incomplete and the linked doc page already has the information you need.
Fixes#83695, but that's more of a side effect. The upstream compiler already suggests the right method name here.
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.
Unify the output of `suggest_assign_value` and `ty_kind_suggestion`.
Ideally we'd make these a single function, but doing so would likely require modify the crate dependency tree.
There is already a workaround in `compiletest` to deal with custom
`CARGO_HOME` using `-Zignore-directory-in-diagnostics-source-blocks={}`.
A similar need exists when dependencies come from the local `vendor`
directory, which distro builds often use, so now we ignore that too.
Also, `issue-21763.rs` was normalizing `hashbrown-` paths, presumably
expecting a version suffix, but the vendored path doesn't include the
version. Now that matches `[\\/]hashbrown` instead.
Do some preparation work for compiletest check-cfg
This PR does several preparation work for having always-on check-cfg in compiletest.
In particular, this PR does two main things:
- It unifies all the *always-false* cfgs under the `FALSE` cfg (as it seems to be the convention under `tests/ui`)
- It also removes some useless conditions
This is done ahead of the introduction of the always-on check-cfg in compiletest to reduce the amount of changes in that follow-up work. I also think that this is useful even without that follow-up work.
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.
Several (doc) comments were super outdated or didn't provide enough context.
Some doc comments shoved everything in a single paragraph without respecting
the fact that the first paragraph should be a single sentence because rustdoc
treats these as item descriptions / synopses on module pages.