Add test for old compiler ICE when using `Borrow`
The original issue was caused by implementing `Borrow` on a local type and using the tokio-reactor crate which had this impl: https://github.com/tokio-rs/tokio/blob/tokio-0.1.4/tokio-reactor/src/poll_evented.rs#L547-L577
This causes an ICE on Rust 1.27.0:
```console
$ RUSTUP_TOOLCHAIN=1.27.0 rustc src/test/ui/issues/issue-50687-ice-on-borrow.rs
error: internal compiler error: librustc/traits/structural_impls.rs:180: impossible case reached
thread 'main' panicked at 'Box<Any>', librustc_errors/lib.rs:554:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: aborting due to previous error
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.27.0 (3eda71b00 2018-06-19) running on x86_64-apple-darwin
```
Closes#50687
add a lint against references to packed fields
Creating a reference to an insufficiently aligned packed field is UB and should be disallowed, both inside and outside of `unsafe` blocks. However, currently there is no stable alternative (https://github.com/rust-lang/rust/issues/64490) so all we do right now is have a future incompatibility warning when doing this outside `unsafe` (https://github.com/rust-lang/rust/issues/46043).
This adds an allow-by-default lint. @retep998 suggested this can help early adopters avoid issues. It also means we can then do a crater run where this is deny-by-default as suggested by @joshtriplett.
I guess the main thing to bikeshed is the lint name. I am not particularly happy with "packed_references" as it sounds like the packed field has reference type. I chose this because it is similar to "safe_packed_borrows". What about "reference_to_packed" or "unaligned_reference" or so?
Ignore arguments when looking for `IndexMut` for subsequent `mut` obligation
Given code like `v[&field].boo();` where `field: String` and
`.boo(&mut self)`, typeck will have decided that `v` is accessed using
`Index`, but when `boo` adds a new `mut` obligation,
`convert_place_op_to_mutable` is called. When this happens, for *some
reason* the arguments' dereference adjustments are completely ignored
causing an error saying that `IndexMut` is not satisfied:
```
error[E0596]: cannot borrow data in an index of `Indexable` as mutable
--> src/main.rs:30:5
|
30 | v[&field].boo();
| ^^^^^^^^^ cannot borrow as mutable
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Indexable`
```
This is not true, but by changing `try_overloaded_place_op` to retry
when given `Needs::MutPlace` without passing the argument types, the
example successfully compiles.
I believe there might be more appropriate ways to deal with this.
Fix#72002.
Support coercion between (FnDef | Closure) and (FnDef | Closure)
Fixes#46742, fixes#48109
Inject `Closure` into the `FnDef x FnDef` coercion special case, which makes coercion of `(FnDef | Closure) x (FnDef | Closure)` possible, where closures should be **non-capturing**.
Incomplete features can also be unsound
Some incomplete features do not just ICE, they are also currently unsound (e.g. https://github.com/rust-lang/rust/pull/72029, and also `specialization` -- which is not yet marked incomplete but [should be](https://github.com/rust-lang/rust/pull/71420)). This makes the message reflect that.
While at it I also added a link to the tracking issue, which hopefully should explain what is incomplete/unsound about the feature.
Given code like `v[&field].boo();` where `field: String` and
`.boo(&mut self)`, typeck will have decided that `v` is accessed using
`Index`, but when `boo` adds a new `mut` obligation,
`convert_place_op_to_mutable` is called. When this happens, for *some
reason* the arguments' dereference adjustments are completely ignored
causing an error saying that `IndexMut` is not satisfied:
```
error[E0596]: cannot borrow data in an index of `Indexable` as mutable
--> src/main.rs:30:5
|
30 | v[&field].boo();
| ^^^^^^^^^ cannot borrow as mutable
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Indexable`
```
This is not true, but by changing `try_overloaded_place_op` to retry
when given `Needs::MutPlace` without passing the argument types, the
example successfully compiles.
I believe there might be more appropriate ways to deal with this.
Provide suggestions for type parameters missing bounds for associated types
When implementing the binary operator traits it is easy to forget to restrict the `Output` associated type. `rustc` now accounts for different cases to lead users in the right direction to add the necessary restrictions. The structured suggestions in the following output are new:
```
error: equality constraints are not yet supported in `where` clauses
--> $DIR/missing-bounds.rs:37:33
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
= note: see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information
help: if `Output` is an associated type you're trying to set, use the associated type binding syntax
|
LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
| ^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> $DIR/missing-bounds.rs:11:11
|
7 | impl<B> Add for A<B> where B: Add {
| - this type parameter
...
11 | A(self.0 + rhs.0)
| ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type
|
= note: expected type parameter `B`
found associated type `<B as std::ops::Add>::Output`
help: consider further restricting this bound
|
7 | impl<B> Add for A<B> where B: Add + std::ops::Add<Output = B> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0369]: cannot add `B` to `B`
--> $DIR/missing-bounds.rs:31:21
|
31 | Self(self.0 + rhs.0)
| ------ ^ ----- B
| |
| B
|
help: consider restricting type parameter `B`
|
27 | impl<B: std::ops::Add<Output = B>> Add for D<B> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
That output is given for the following cases:
```rust
struct A<B>(B);
impl<B> Add for A<B> where B: Add {
type Output = Self;
fn add(self, rhs: Self) -> Self {
A(self.0 + rhs.0) //~ ERROR mismatched types
}
}
struct D<B>(B);
impl<B> Add for D<B> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0) //~ ERROR cannot add `B` to `B`
}
}
struct E<B>(B);
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}
```
Suggest removing semicolon in last expression only if it's type is known
Fixes#67971
Is there a syntax for explicitly checking if a note doesn't exist in test output? Something like `//~ !NOTE ...`
I believe r? @estebank deals with diagnostics.
On type mismatch involving associated type, suggest constraint
When an associated type is found when a specific type was expected, if
possible provide a structured suggestion constraining the associated
type in a bound.
```
error[E0271]: type mismatch resolving `<T as Foo>::Y == i32`
--> $DIR/associated-types-multiple-types-one-trait.rs:13:5
|
LL | want_y(t);
| ^^^^^^ expected `i32`, found associated type
...
LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
| ----- required by this bound in `want_y`
|
= note: expected type `i32`
found associated type `<T as Foo>::Y`
help: consider constraining the associated type `<T as Foo>::Y` to `i32`
|
LL | fn have_x_want_y<T:Foo<X=u32, Y = i32>>(t: &T)
| ^^^^^^^^^
```
```
error[E0308]: mismatched types
--> $DIR/trait-with-missing-associated-type-restriction.rs:12:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo(x: impl Trait<A = usize>) {
| ^^^^^^^^^^
```
Fix#71035. Related to #70908.
When an associated type is found when a specific type was expected, if
possible provide a structured suggestion constraining the associated
type in a bound.
```
error[E0271]: type mismatch resolving `<T as Foo>::Y == i32`
--> $DIR/associated-types-multiple-types-one-trait.rs:13:5
|
LL | want_y(t);
| ^^^^^^ expected `i32`, found associated type
...
LL | fn want_y<T:Foo<Y=i32>>(t: &T) { }
| ----- required by this bound in `want_y`
|
= note: expected type `i32`
found associated type `<T as Foo>::Y`
help: consider constraining the associated type `<T as Foo>::Y` to `i32`
|
LL | fn have_x_want_y<T:Foo<X=u32, Y = i32>>(t: &T)
| ^^^^^^^^^
```
```
error[E0308]: mismatched types
--> $DIR/trait-with-missing-associated-type-restriction.rs:12:9
|
LL | qux(x.func())
| ^^^^^^^^ expected `usize`, found associated type
|
= note: expected type `usize`
found associated type `<impl Trait as Trait>::A`
help: consider constraining the associated type `<impl Trait as Trait>::A` to `usize`
|
LL | fn foo(x: impl Trait<A = usize>) {
| ^^^^^^^^^^
```
Suggest deref when coercing `ty::Ref` to `ty::RawPtr`
Fixes#32122
Currently we do autoderef when casting `ty::Ref` ->`ty::Ref`, but we don't autoderef when casting `ty::Ref` -> `ty::RawPtr`. This PR make the compiler suggests deref when coercing `ty::Ref` to `ty::RawPtr`