From 6b8fba5a42840f0e8b2ea087f8fefdb9b93e1b22 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 26 Aug 2018 00:28:23 +0300 Subject: [PATCH] rustc_typeck: turn `where Type:,` into a WF(Type) predicate, instead of ignoring it. --- src/librustc_typeck/collect.rs | 15 +++++++++++ src/librustdoc/clean/mod.rs | 8 +++++- .../ui/chalkify/lower_trait_where_clause.rs | 10 ++++++- .../chalkify/lower_trait_where_clause.stderr | 3 ++- src/test/ui/wf/wf-fn-where-clause.rs | 5 +++- src/test/ui/wf/wf-fn-where-clause.stderr | 27 ++++++++++++++++--- 6 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a42667ab45fc8..43e44823b90ff 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1796,6 +1796,21 @@ fn explicit_predicates_of<'a, 'tcx>( &hir::WherePredicate::BoundPredicate(ref bound_pred) => { let ty = icx.to_ty(&bound_pred.bounded_ty); + // Keep the type around in a WF predicate, in case of no bounds. + // That way, `where Ty:` is not a complete noop (see #53696). + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.sty { + // This is a `where T:`, which can be in the HIR from the + // transformation that moves `?Sized` to `T`'s declaration. + // We can skip the predicate because type parameters are + // trivially WF, but also we *should*, to avoid exposing + // users who never wrote `where Type:,` themselves, to + // compiler/tooling bugs from not handling WF predicates. + } else { + predicates.push(ty::Predicate::WellFormed(ty)); + } + } + for bound in bound_pred.bounds.iter() { match bound { &hir::GenericBound::Trait(ref poly_trait_ref, _) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5c23d0f6b3990..da18e3e6b91b3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1312,7 +1312,13 @@ impl<'a> Clean for ty::Predicate<'a> { Predicate::RegionOutlives(ref pred) => pred.clean(cx), Predicate::TypeOutlives(ref pred) => pred.clean(cx), Predicate::Projection(ref pred) => pred.clean(cx), - Predicate::WellFormed(_) => panic!("not user writable"), + Predicate::WellFormed(ty) => { + // This comes from `where Ty:` (i.e. no bounds) (see #53696). + WherePredicate::BoundPredicate { + ty: ty.clean(cx), + bounds: vec![], + } + } Predicate::ObjectSafe(_) => panic!("not user writable"), Predicate::ClosureKind(..) => panic!("not user writable"), Predicate::ConstEvaluatable(..) => panic!("not user writable"), diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs index 57e95e39cd996..5305591b84345 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ b/src/test/ui/chalkify/lower_trait_where_clause.rs @@ -14,7 +14,15 @@ use std::fmt::{Debug, Display}; use std::borrow::Borrow; #[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow, U: ?Sized, 'a: 'b, U: 'b { +trait Foo<'a, 'b, S, T, U> +where + S: Debug, + T: Borrow, + U: ?Sized, + 'a: 'b, + U: 'b, + Vec:, // NOTE(#53696) this checks an empty list of bounds. +{ fn s(_: S) -> S; fn t(_: T) -> T; fn u(_: U) -> U; diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr index 5ea397d424b63..ad3546da1a25b 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ b/src/test/ui/chalkify/lower_trait_where_clause.stderr @@ -11,7 +11,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). - = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow), RegionOutlives('a : 'b), TypeOutlives(U : 'b). + = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec). + = note: WellFormed(std::vec::Vec) :- FromEnv(Self: Foo<'a, 'b, S, T, U>). error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.rs b/src/test/ui/wf/wf-fn-where-clause.rs index 3ed9e5d9f1eb5..59bb8326ddbf5 100644 --- a/src/test/ui/wf/wf-fn-where-clause.rs +++ b/src/test/ui/wf/wf-fn-where-clause.rs @@ -10,7 +10,6 @@ // Test that we check where-clauses on fn items. -#![feature(associated_type_defaults)] #![feature(rustc_attrs)] #![allow(dead_code)] @@ -20,5 +19,9 @@ fn foo() where T: ExtraCopy //~ ERROR E0277 { } +fn bar() where Vec:, {} +//~^ ERROR E0277 +//~| ERROR E0038 + #[rustc_error] fn main() { } diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index 5f0f982577ee5..21591419ec856 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied - --> $DIR/wf-fn-where-clause.rs:19:1 + --> $DIR/wf-fn-where-clause.rs:18:1 | LL | / fn foo() where T: ExtraCopy //~ ERROR E0277 LL | | { @@ -8,11 +8,30 @@ LL | | } | = help: consider adding a `where U: std::marker::Copy` bound note: required by `ExtraCopy` - --> $DIR/wf-fn-where-clause.rs:17:1 + --> $DIR/wf-fn-where-clause.rs:16:1 | LL | trait ExtraCopy { } | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time + --> $DIR/wf-fn-where-clause.rs:22:1 + | +LL | fn bar() where Vec:, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)` + = note: to learn more, visit + = note: required by `std::vec::Vec` + +error[E0038]: the trait `std::marker::Copy` cannot be made into an object + --> $DIR/wf-fn-where-clause.rs:22:1 + | +LL | fn bar() where Vec:, {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors occurred: E0038, E0277. +For more information about an error, try `rustc --explain E0038`.