From 3b4a06272e8453c8b90f282b2b5b0e4c27993ff1 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sat, 23 Dec 2017 11:29:01 -0200 Subject: [PATCH] Go back to checking only the LHS of trait predicates. --- src/librustc_typeck/check/wfcheck.rs | 19 +++++++--- src/test/run-pass/defaults-well-formedness.rs | 14 ++++++++ src/test/ui/type-check-defaults.rs | 11 +++++- src/test/ui/type-check-defaults.stderr | 36 +++++++++---------- 4 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 src/test/run-pass/defaults-well-formedness.rs diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 0a919eb3b8c..a16b806b6f1 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -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) + }); } } diff --git a/src/test/run-pass/defaults-well-formedness.rs b/src/test/run-pass/defaults-well-formedness.rs new file mode 100644 index 00000000000..92c7f8731ba --- /dev/null +++ b/src/test/run-pass/defaults-well-formedness.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Trait {} +struct Foo(U, V) where U: Trait; + +fn main() {} diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs index a6e475eb1a3..7c379a1f1bc 100644 --- a/src/test/ui/type-check-defaults.rs +++ b/src/test/ui/type-check-defaults.rs @@ -7,7 +7,6 @@ // , 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); struct WellFormed>(Z); +//~^ error: the trait bound `i32: std::iter::FromIterator` is not satisfied [E0277] struct WellFormedNoBounds>(Z); +//~^ error: the trait bound `i32: std::iter::FromIterator` is not satisfied [E0277] struct WellFormedProjection::Item>(A, T); +//~^ error: the trait bound `A: std::iter::Iterator` is not satisfied [E0277] struct Bounds(T); +//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] struct WhereClause(T) where T: Copy; +//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] trait TraitBound {} +//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277] trait SelfBound {} +//~^ error: the trait bound `Self: std::marker::Copy` is not satisfied [E0277] trait FooTrait> where T::Item : Add {} +//~^ error: the trait bound `i32: std::ops::Add` is not satisfied [E0277] trait Trait {} struct TwoParams(T, U); impl Trait for TwoParams {} // Check that each default is substituted individually in the clauses. struct Bogus(TwoParams) where TwoParams: Trait; +//~^ error: the trait bound `TwoParams: Trait` is not satisfied [E0277] +//~^^ error: the trait bound `TwoParams: Trait` is not satisfied [E0277] fn main() { } diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr index cf11282f7d2..3ac6e4c26b4 100644 --- a/src/test/ui/type-check-defaults.stderr +++ b/src/test/ui/type-check-defaults.stderr @@ -1,7 +1,7 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator` is not satisfied - --> $DIR/type-check-defaults.rs:17:19 + --> $DIR/type-check-defaults.rs:16:19 | -17 | struct WellFormed>(Z); +16 | struct WellFormed>(Z); | ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32` | = help: the trait `std::iter::FromIterator` is not implemented for `i32` @@ -17,69 +17,69 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator` 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::Item>(A, T); +21 | struct WellFormedProjection::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); +24 | struct Bounds(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) where T: Copy; +27 | struct WhereClause(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 {} +30 | trait TraitBound {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 {} +33 | trait SelfBound {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` is not satisfied - --> $DIR/type-check-defaults.rs:30:1 + --> $DIR/type-check-defaults.rs:36:1 | -30 | trait FooTrait> where T::Item : Add {} +36 | trait FooTrait> where T::Item : Add {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` | = help: the trait `std::ops::Add` is not implemented for `i32` = note: required by `std::ops::Add` error[E0277]: the trait bound `TwoParams: Trait` is not satisfied - --> $DIR/type-check-defaults.rs:36:1 + --> $DIR/type-check-defaults.rs:43:1 | -36 | struct Bogus(TwoParams) where TwoParams: Trait; +43 | struct Bogus(TwoParams) where TwoParams: Trait; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams` | = help: consider adding a `where TwoParams: Trait` bound = note: required by `Trait` error[E0277]: the trait bound `TwoParams: Trait` is not satisfied - --> $DIR/type-check-defaults.rs:36:1 + --> $DIR/type-check-defaults.rs:43:1 | -36 | struct Bogus(TwoParams) where TwoParams: Trait; +43 | struct Bogus(TwoParams) where TwoParams: Trait; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams` | = help: consider adding a `where TwoParams: Trait` bound