Skip to content

Commit 6b8fba5

Browse files
committed
rustc_typeck: turn where Type:, into a WF(Type) predicate, instead of ignoring it.
1 parent 1114ab6 commit 6b8fba5

File tree

6 files changed

+60
-8
lines changed

6 files changed

+60
-8
lines changed

src/librustc_typeck/collect.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,21 @@ fn explicit_predicates_of<'a, 'tcx>(
17961796
&hir::WherePredicate::BoundPredicate(ref bound_pred) => {
17971797
let ty = icx.to_ty(&bound_pred.bounded_ty);
17981798

1799+
// Keep the type around in a WF predicate, in case of no bounds.
1800+
// That way, `where Ty:` is not a complete noop (see #53696).
1801+
if bound_pred.bounds.is_empty() {
1802+
if let ty::Param(_) = ty.sty {
1803+
// This is a `where T:`, which can be in the HIR from the
1804+
// transformation that moves `?Sized` to `T`'s declaration.
1805+
// We can skip the predicate because type parameters are
1806+
// trivially WF, but also we *should*, to avoid exposing
1807+
// users who never wrote `where Type:,` themselves, to
1808+
// compiler/tooling bugs from not handling WF predicates.
1809+
} else {
1810+
predicates.push(ty::Predicate::WellFormed(ty));
1811+
}
1812+
}
1813+
17991814
for bound in bound_pred.bounds.iter() {
18001815
match bound {
18011816
&hir::GenericBound::Trait(ref poly_trait_ref, _) => {

src/librustdoc/clean/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,13 @@ impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
13121312
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
13131313
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
13141314
Predicate::Projection(ref pred) => pred.clean(cx),
1315-
Predicate::WellFormed(_) => panic!("not user writable"),
1315+
Predicate::WellFormed(ty) => {
1316+
// This comes from `where Ty:` (i.e. no bounds) (see #53696).
1317+
WherePredicate::BoundPredicate {
1318+
ty: ty.clean(cx),
1319+
bounds: vec![],
1320+
}
1321+
}
13161322
Predicate::ObjectSafe(_) => panic!("not user writable"),
13171323
Predicate::ClosureKind(..) => panic!("not user writable"),
13181324
Predicate::ConstEvaluatable(..) => panic!("not user writable"),

src/test/ui/chalkify/lower_trait_where_clause.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ use std::fmt::{Debug, Display};
1414
use std::borrow::Borrow;
1515

1616
#[rustc_dump_program_clauses] //~ ERROR program clause dump
17-
trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
17+
trait Foo<'a, 'b, S, T, U>
18+
where
19+
S: Debug,
20+
T: Borrow<U>,
21+
U: ?Sized,
22+
'a: 'b,
23+
U: 'b,
24+
Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
25+
{
1826
fn s(_: S) -> S;
1927
fn t(_: T) -> T;
2028
fn u(_: U) -> U;

src/test/ui/chalkify/lower_trait_where_clause.stderr

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
1111
= note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
1212
= note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
1313
= note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
14-
= 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).
14+
= 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>).
15+
= note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
1516

1617
error: aborting due to previous error
1718

src/test/ui/wf/wf-fn-where-clause.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

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

13-
#![feature(associated_type_defaults)]
1413
#![feature(rustc_attrs)]
1514
#![allow(dead_code)]
1615

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

22+
fn bar() where Vec<dyn Copy>:, {}
23+
//~^ ERROR E0277
24+
//~| ERROR E0038
25+
2326
#[rustc_error]
2427
fn main() { }
+23-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
2-
--> $DIR/wf-fn-where-clause.rs:19:1
2+
--> $DIR/wf-fn-where-clause.rs:18:1
33
|
44
LL | / fn foo<T,U>() where T: ExtraCopy<U> //~ ERROR E0277
55
LL | | {
@@ -8,11 +8,30 @@ LL | | }
88
|
99
= help: consider adding a `where U: std::marker::Copy` bound
1010
note: required by `ExtraCopy`
11-
--> $DIR/wf-fn-where-clause.rs:17:1
11+
--> $DIR/wf-fn-where-clause.rs:16:1
1212
|
1313
LL | trait ExtraCopy<T:Copy> { }
1414
| ^^^^^^^^^^^^^^^^^^^^^^^
1515

16-
error: aborting due to previous error
16+
error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time
17+
--> $DIR/wf-fn-where-clause.rs:22:1
18+
|
19+
LL | fn bar() where Vec<dyn Copy>:, {}
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
21+
|
22+
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::marker::Copy + 'static)`
23+
= 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>
24+
= note: required by `std::vec::Vec`
25+
26+
error[E0038]: the trait `std::marker::Copy` cannot be made into an object
27+
--> $DIR/wf-fn-where-clause.rs:22:1
28+
|
29+
LL | fn bar() where Vec<dyn Copy>:, {}
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` cannot be made into an object
31+
|
32+
= note: the trait cannot require that `Self : Sized`
33+
34+
error: aborting due to 3 previous errors
1735

18-
For more information about this error, try `rustc --explain E0277`.
36+
Some errors occurred: E0038, E0277.
37+
For more information about an error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)