Go back to checking only the LHS of trait predicates.
This commit is contained in:
parent
d9c336afb7
commit
3b4a06272e
@ -387,7 +387,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||
let d = param_def.def_id;
|
||||
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
|
||||
// Check the clauses are well-formed when the param is substituted by it's default.
|
||||
// In trait definitions, predicates as `Self: Trait` and `Self: Super` are problematic.
|
||||
// In trait definitions, the predicate `Self: Trait` is problematic.
|
||||
// Therefore we skip such predicates. This means we check less than we could.
|
||||
for pred in predicates.predicates.iter().filter(|p| !(is_trait && p.has_self_ty())) {
|
||||
let mut skip = true;
|
||||
@ -418,9 +418,20 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
||||
}
|
||||
}
|
||||
});
|
||||
if !skip {
|
||||
substituted_predicates.push(pred.subst(fcx.tcx, substs));
|
||||
}
|
||||
if skip { continue; }
|
||||
substituted_predicates.push(match pred {
|
||||
// In trait predicates, substitute defaults only for the LHS.
|
||||
ty::Predicate::Trait(trait_pred) => {
|
||||
let t_pred = trait_pred.skip_binder();
|
||||
let self_ty = t_pred.self_ty().subst(fcx.tcx, substs);
|
||||
let mut trait_substs = t_pred.trait_ref.substs.to_vec();
|
||||
trait_substs[0] = self_ty.into();
|
||||
let trait_ref = ty::TraitRef::new(t_pred.def_id(),
|
||||
fcx.tcx.intern_substs(&trait_substs));
|
||||
ty::Predicate::Trait(ty::Binder(trait_ref).to_poly_trait_predicate())
|
||||
}
|
||||
_ => pred.subst(fcx.tcx, substs)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
14
src/test/run-pass/defaults-well-formedness.rs
Normal file
14
src/test/run-pass/defaults-well-formedness.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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>;
|
||||
|
||||
fn main() {}
|
@ -7,7 +7,6 @@
|
||||
// <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.
|
||||
// compile-flags: --error-format=human
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use std::vec::IntoIter;
|
||||
@ -15,24 +14,34 @@ 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 WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
|
||||
//~^ error: the trait bound `A: std::iter::Iterator` 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 SelfBound<T:Copy=Self> {}
|
||||
//~^ error: the trait bound `Self: std::marker::Copy` is not satisfied [E0277]
|
||||
|
||||
trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
||||
//~^ error: the trait bound `i32: std::ops::Add<u8>` is not satisfied [E0277]
|
||||
|
||||
trait Trait {}
|
||||
struct TwoParams<T, U>(T, U);
|
||||
impl Trait for TwoParams<i32, i32> {}
|
||||
// Check that each default is substituted individually in the clauses.
|
||||
struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
//~^ error: the trait bound `TwoParams<i32, U>: Trait` is not satisfied [E0277]
|
||||
//~^^ error: the trait bound `TwoParams<T, i32>: Trait` is not satisfied [E0277]
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:17:19
|
||||
--> $DIR/type-check-defaults.rs:16:19
|
||||
|
|
||||
17 | struct WellFormed<Z = Foo<i32, i32>>(Z);
|
||||
16 | 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`
|
||||
@ -17,69 +17,69 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfi
|
||||
= note: required by `Foo`
|
||||
|
||||
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:20:1
|
||||
--> $DIR/type-check-defaults.rs:21:1
|
||||
|
|
||||
20 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
|
||||
21 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
|
||||
|
|
||||
= help: the trait `std::iter::Iterator` is not implemented for `A`
|
||||
= help: consider adding a `where A: std::iter::Iterator` bound
|
||||
|
||||
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:22:1
|
||||
--> $DIR/type-check-defaults.rs:24:1
|
||||
|
|
||||
22 | struct Bounds<T:Copy=String>(T);
|
||||
24 | 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
|
||||
--> $DIR/type-check-defaults.rs:27:1
|
||||
|
|
||||
24 | struct WhereClause<T=String>(T) where T: Copy;
|
||||
27 | 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:26:1
|
||||
--> $DIR/type-check-defaults.rs:30:1
|
||||
|
|
||||
26 | trait TraitBound<T:Copy=String> {}
|
||||
30 | 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 `Self: std::marker::Copy` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:28:1
|
||||
--> $DIR/type-check-defaults.rs:33:1
|
||||
|
|
||||
28 | trait SelfBound<T:Copy=Self> {}
|
||||
33 | trait SelfBound<T:Copy=Self> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: std::marker::Copy` bound
|
||||
= note: required by `std::marker::Copy`
|
||||
|
||||
error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:30:1
|
||||
--> $DIR/type-check-defaults.rs:36:1
|
||||
|
|
||||
30 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
||||
36 | trait FooTrait<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[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:36:1
|
||||
--> $DIR/type-check-defaults.rs:43:1
|
||||
|
|
||||
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
|
||||
|
|
||||
= help: consider adding a `where TwoParams<i32, U>: Trait` bound
|
||||
= note: required by `Trait`
|
||||
|
||||
error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:36:1
|
||||
--> $DIR/type-check-defaults.rs:43:1
|
||||
|
|
||||
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
|
||||
|
|
||||
= help: consider adding a `where TwoParams<T, i32>: Trait` bound
|
||||
|
Loading…
x
Reference in New Issue
Block a user