Skip to content

Commit 3b4a062

Browse files
committed
Go back to checking only the LHS of trait predicates.
1 parent d9c336a commit 3b4a062

File tree

4 files changed

+57
-23
lines changed

4 files changed

+57
-23
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
387387
let d = param_def.def_id;
388388
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
389389
// Check the clauses are well-formed when the param is substituted by it's default.
390-
// In trait definitions, predicates as `Self: Trait` and `Self: Super` are problematic.
390+
// In trait definitions, the predicate `Self: Trait` is problematic.
391391
// Therefore we skip such predicates. This means we check less than we could.
392392
for pred in predicates.predicates.iter().filter(|p| !(is_trait && p.has_self_ty())) {
393393
let mut skip = true;
@@ -418,9 +418,20 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
418418
}
419419
}
420420
});
421-
if !skip {
422-
substituted_predicates.push(pred.subst(fcx.tcx, substs));
423-
}
421+
if skip { continue; }
422+
substituted_predicates.push(match pred {
423+
// In trait predicates, substitute defaults only for the LHS.
424+
ty::Predicate::Trait(trait_pred) => {
425+
let t_pred = trait_pred.skip_binder();
426+
let self_ty = t_pred.self_ty().subst(fcx.tcx, substs);
427+
let mut trait_substs = t_pred.trait_ref.substs.to_vec();
428+
trait_substs[0] = self_ty.into();
429+
let trait_ref = ty::TraitRef::new(t_pred.def_id(),
430+
fcx.tcx.intern_substs(&trait_substs));
431+
ty::Predicate::Trait(ty::Binder(trait_ref).to_poly_trait_predicate())
432+
}
433+
_ => pred.subst(fcx.tcx, substs)
434+
});
424435
}
425436
}
426437

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
trait Trait<T> {}
12+
struct Foo<U, V=i32>(U, V) where U: Trait<V>;
13+
14+
fn main() {}

src/test/ui/type-check-defaults.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,41 @@
77
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
10-
// compile-flags: --error-format=human
1110

1211
use std::iter::FromIterator;
1312
use std::vec::IntoIter;
1413
use std::ops::Add;
1514

1615
struct Foo<T, U: FromIterator<T>>(T, U);
1716
struct WellFormed<Z = Foo<i32, i32>>(Z);
17+
//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
1818
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
19+
//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
1920

2021
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
22+
//~^ error: the trait bound `A: std::iter::Iterator` is not satisfied [E0277]
2123

2224
struct Bounds<T:Copy=String>(T);
25+
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
2326

2427
struct WhereClause<T=String>(T) where T: Copy;
28+
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
2529

2630
trait TraitBound<T:Copy=String> {}
31+
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
2732

2833
trait SelfBound<T:Copy=Self> {}
34+
//~^ error: the trait bound `Self: std::marker::Copy` is not satisfied [E0277]
2935

3036
trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
37+
//~^ error: the trait bound `i32: std::ops::Add<u8>` is not satisfied [E0277]
3138

3239
trait Trait {}
3340
struct TwoParams<T, U>(T, U);
3441
impl Trait for TwoParams<i32, i32> {}
3542
// Check that each default is substituted individually in the clauses.
3643
struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
44+
//~^ error: the trait bound `TwoParams<i32, U>: Trait` is not satisfied [E0277]
45+
//~^^ error: the trait bound `TwoParams<T, i32>: Trait` is not satisfied [E0277]
3746

3847
fn main() { }

src/test/ui/type-check-defaults.stderr

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
2-
--> $DIR/type-check-defaults.rs:17:19
2+
--> $DIR/type-check-defaults.rs:16:19
33
|
4-
17 | struct WellFormed<Z = Foo<i32, i32>>(Z);
4+
16 | struct WellFormed<Z = Foo<i32, i32>>(Z);
55
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
66
|
77
= 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
1717
= note: required by `Foo`
1818

1919
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
20-
--> $DIR/type-check-defaults.rs:20:1
20+
--> $DIR/type-check-defaults.rs:21:1
2121
|
22-
20 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
22+
21 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
2424
|
2525
= help: the trait `std::iter::Iterator` is not implemented for `A`
2626
= help: consider adding a `where A: std::iter::Iterator` bound
2727

2828
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
29-
--> $DIR/type-check-defaults.rs:22:1
29+
--> $DIR/type-check-defaults.rs:24:1
3030
|
31-
22 | struct Bounds<T:Copy=String>(T);
31+
24 | struct Bounds<T:Copy=String>(T);
3232
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
3333
|
3434
= note: required by `std::marker::Copy`
3535

3636
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
37-
--> $DIR/type-check-defaults.rs:24:1
37+
--> $DIR/type-check-defaults.rs:27:1
3838
|
39-
24 | struct WhereClause<T=String>(T) where T: Copy;
39+
27 | struct WhereClause<T=String>(T) where T: Copy;
4040
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
4141
|
4242
= note: required by `std::marker::Copy`
4343

4444
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
45-
--> $DIR/type-check-defaults.rs:26:1
45+
--> $DIR/type-check-defaults.rs:30:1
4646
|
47-
26 | trait TraitBound<T:Copy=String> {}
47+
30 | trait TraitBound<T:Copy=String> {}
4848
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
4949
|
5050
= note: required by `std::marker::Copy`
5151

5252
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
53-
--> $DIR/type-check-defaults.rs:28:1
53+
--> $DIR/type-check-defaults.rs:33:1
5454
|
55-
28 | trait SelfBound<T:Copy=Self> {}
55+
33 | trait SelfBound<T:Copy=Self> {}
5656
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Self`
5757
|
5858
= help: consider adding a `where Self: std::marker::Copy` bound
5959
= note: required by `std::marker::Copy`
6060

6161
error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
62-
--> $DIR/type-check-defaults.rs:30:1
62+
--> $DIR/type-check-defaults.rs:36:1
6363
|
64-
30 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
64+
36 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
6565
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
6666
|
6767
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
6868
= note: required by `std::ops::Add`
6969

7070
error[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
71-
--> $DIR/type-check-defaults.rs:36:1
71+
--> $DIR/type-check-defaults.rs:43:1
7272
|
73-
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
73+
43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
7575
|
7676
= help: consider adding a `where TwoParams<i32, U>: Trait` bound
7777
= note: required by `Trait`
7878

7979
error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
80-
--> $DIR/type-check-defaults.rs:36:1
80+
--> $DIR/type-check-defaults.rs:43:1
8181
|
82-
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
82+
43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
8383
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
8484
|
8585
= help: consider adding a `where TwoParams<T, i32>: Trait` bound

0 commit comments

Comments
 (0)