Skip to content

rustc_typeck: turn where Type:, into a WF(Type) predicate, instead of ignoring it. #53707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, _) => {
Expand Down
8 changes: 7 additions & 1 deletion src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1312,7 +1312,13 @@ impl<'a> Clean<WherePredicate> 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"),
Expand Down
10 changes: 9 additions & 1 deletion src/test/ui/chalkify/lower_trait_where_clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>, U: ?Sized, 'a: 'b, U: 'b {
trait Foo<'a, 'b, S, T, U>
where
S: Debug,
T: Borrow<U>,
U: ?Sized,
'a: 'b,
U: 'b,
Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
{
fn s(_: S) -> S;
fn t(_: T) -> T;
fn u(_: U) -> U;
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/chalkify/lower_trait_where_clause.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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<U>), 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<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec<T>).
= note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).

error: aborting due to previous error

5 changes: 4 additions & 1 deletion src/test/ui/wf/wf-fn-where-clause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

// Test that we check where-clauses on fn items.

#![feature(associated_type_defaults)]
#![feature(rustc_attrs)]
#![allow(dead_code)]

Expand All @@ -20,5 +19,9 @@ fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
{
}

fn bar() where Vec<dyn Copy>:, {}
//~^ ERROR E0277
//~| ERROR E0038

#[rustc_error]
fn main() { }
27 changes: 23 additions & 4 deletions src/test/ui/wf/wf-fn-where-clause.stderr
Original file line number Diff line number Diff line change
@@ -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<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
LL | | {
Expand All @@ -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<T:Copy> { }
| ^^^^^^^^^^^^^^^^^^^^^^^

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<dyn Copy>:, {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= 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<dyn Copy>:, {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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`.