-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #46785 - leodasvacas:type-check-defaults-at-declaration…
…, r=nikomatsakis [Underspecified semantics] Type check defaults at declaration. Fixes #46669. See the test for code that compiles on stable but will no longer compile. This falls under a "Underspecified language semantics" fix. **Needs crater**. On type and trait declarations, we currently allow anything that name checks as a type parameter default. That allows the user to write a default that can never be applied, or even a default that may conditionally be applied depending on the type of another parameter. Mostly this just defers the error to use sites, but also allows clever hacks such as `Foo<T, U = <T as Iterator>::Item>` where `U` will be able to apply it's default only when `T: Iterator`. Maybe that means this bug is a feature, but it's a fiddly behaviour that seems undesirable. This PR validates defaults at declaration sites by ensuring all predicates on the parameter are valid for the default. With the exception of `Self: Sized` which we don't want to check to allow things like `trait Add<RHS = Self>`.
- Loading branch information
Showing
5 changed files
with
231 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
trait Trait<T> {} | ||
struct Foo<U, V=i32>(U, V) where U: Trait<V>; | ||
|
||
trait Marker {} | ||
struct TwoParams<T, U>(T, U); | ||
impl Marker for TwoParams<i32, i32> {} | ||
|
||
// Clauses with more than 1 param are not checked. | ||
struct IndividuallyBogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Marker; | ||
struct BogusTogether<T = u32, U = i32>(T, U) where TwoParams<T, U>: Marker; | ||
// Clauses with non-defaulted params are not checked. | ||
struct NonDefaultedInClause<T, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Marker; | ||
struct DefaultedLhs<U, V=i32>(U, V) where V: Trait<U>; | ||
// Dependent defaults are not checked. | ||
struct Dependent<T, U = T>(T, U) where U: Copy; | ||
trait SelfBound<T: Copy=Self> {} | ||
// Not even for well-formedness. | ||
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T); | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,4 @@ fn issue_36540() { | |
} | ||
|
||
trait Trait<T> {} | ||
impl Trait<i32> for i32 {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use std::iter::FromIterator; | ||
use std::vec::IntoIter; | ||
use std::ops::Add; | ||
|
||
struct Foo<T, U: FromIterator<T>>(T, U); | ||
struct WellFormed<Z = Foo<i32, i32>>(Z); | ||
//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277] | ||
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z); | ||
//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277] | ||
|
||
struct Bounds<T:Copy=String>(T); | ||
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] | ||
|
||
struct WhereClause<T=String>(T) where T: Copy; | ||
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] | ||
|
||
trait TraitBound<T:Copy=String> {} | ||
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] | ||
|
||
trait Super<T: Copy> { } | ||
trait Base<T = String>: Super<T> { } | ||
//~^ error: the trait bound `T: std::marker::Copy` is not satisfied [E0277] | ||
|
||
trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} | ||
//~^ error: cannot add `u8` to `i32` [E0277] | ||
|
||
fn main() { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied | ||
--> $DIR/type-check-defaults.rs:16:19 | ||
| | ||
LL | struct WellFormed<Z = Foo<i32, i32>>(Z); | ||
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32` | ||
| | ||
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32` | ||
note: required by `Foo` | ||
--> $DIR/type-check-defaults.rs:15:1 | ||
| | ||
LL | struct Foo<T, U: FromIterator<T>>(T, U); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied | ||
--> $DIR/type-check-defaults.rs:18:27 | ||
| | ||
LL | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z); | ||
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32` | ||
| | ||
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32` | ||
note: required by `Foo` | ||
--> $DIR/type-check-defaults.rs:15:1 | ||
| | ||
LL | struct Foo<T, U: FromIterator<T>>(T, U); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied | ||
--> $DIR/type-check-defaults.rs:21:1 | ||
| | ||
LL | struct Bounds<T:Copy=String>(T); | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | ||
| | ||
= note: required by `std::marker::Copy` | ||
|
||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied | ||
--> $DIR/type-check-defaults.rs:24:1 | ||
| | ||
LL | struct WhereClause<T=String>(T) where T: Copy; | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | ||
| | ||
= note: required by `std::marker::Copy` | ||
|
||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied | ||
--> $DIR/type-check-defaults.rs:27:1 | ||
| | ||
LL | trait TraitBound<T:Copy=String> {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | ||
| | ||
= note: required by `std::marker::Copy` | ||
|
||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied | ||
--> $DIR/type-check-defaults.rs:31:1 | ||
| | ||
LL | trait Base<T = String>: Super<T> { } | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` | ||
| | ||
= help: consider adding a `where T: std::marker::Copy` bound | ||
note: required by `Super` | ||
--> $DIR/type-check-defaults.rs:30:1 | ||
| | ||
LL | trait Super<T: Copy> { } | ||
| ^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0277]: cannot add `u8` to `i32` | ||
--> $DIR/type-check-defaults.rs:34:1 | ||
| | ||
LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` | ||
| | ||
= help: the trait `std::ops::Add<u8>` is not implemented for `i32` | ||
= note: required by `std::ops::Add` | ||
|
||
error: aborting due to 7 previous errors | ||
|
||
If you want more information on this error, try using "rustc --explain E0277" |