Skip to content

Commit 7e40efc

Browse files
authored
Rollup merge of #152688 - fmease:implied-preds-default-bounds, r=jackh726
Trait aliases: Also imply default trait bounds on type params other than `Self` Trait aliases already correctly imply default trait bounds on `Self` type params. However, due to an oversight, they didn't do that for normal type params. Fixes #152687.
2 parents 2a0b534 + 9d627dd commit 7e40efc

5 files changed

Lines changed: 230 additions & 0 deletions

File tree

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,32 @@ impl<'tcx> ItemCtxt<'tcx> {
979979
) -> Vec<(ty::Clause<'tcx>, Span)> {
980980
let mut bounds = Vec::new();
981981

982+
if let PredicateFilter::All = filter {
983+
for param in hir_generics.params {
984+
match param.kind {
985+
hir::GenericParamKind::Type { .. } => {
986+
let param_ty = self.lowerer().lower_ty_param(param.hir_id);
987+
self.lowerer().add_implicit_sizedness_bounds(
988+
&mut bounds,
989+
param_ty,
990+
&[],
991+
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
992+
param.span,
993+
);
994+
self.lowerer().add_default_traits(
995+
&mut bounds,
996+
param_ty,
997+
&[],
998+
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
999+
param.span,
1000+
);
1001+
}
1002+
hir::GenericParamKind::Lifetime { .. }
1003+
| hir::GenericParamKind::Const { .. } => {}
1004+
}
1005+
}
1006+
}
1007+
9821008
for predicate in hir_generics.predicates {
9831009
let hir_id = predicate.hir_id;
9841010
let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error[E0277]: the size for values of type `str` cannot be known at compilation time
2+
--> $DIR/default-trait-bounds.rs:26:34
3+
|
4+
LL | #[cfg(fail)] fn a1_fail() { a1::<str>; }
5+
| ^^^ doesn't have a size known at compile-time
6+
|
7+
= help: the trait `Sized` is not implemented for `str`
8+
= note: required for `()` to implement `A1<str>`
9+
note: required by a bound in `a1`
10+
--> $DIR/default-trait-bounds.rs:25:30
11+
|
12+
LL | fn a1<T: ?Sized>() where (): A1<T> { ensure_is_sized::<T>; }
13+
| ^^^^^ required by this bound in `a1`
14+
15+
error[E0277]: the size for values of type `ExternTy` cannot be known
16+
--> $DIR/default-trait-bounds.rs:49:34
17+
|
18+
LL | #[cfg(fail)] fn b1_fail() { b1::<ExternTy>; }
19+
| ^^^^^^^^ doesn't have a known size
20+
|
21+
= help: the nightly-only, unstable trait `MetaSized` is not implemented for `ExternTy`
22+
= note: required for `()` to implement `B1<ExternTy>`
23+
note: required by a bound in `b1`
24+
--> $DIR/default-trait-bounds.rs:47:36
25+
|
26+
LL | fn b1<T: PointeeSized>() where (): B1<T> { ensure_is_meta_sized::<T>(); }
27+
| ^^^^^ required by this bound in `b1`
28+
29+
error[E0277]: the trait bound `ExternTy: C1` is not satisfied
30+
--> $DIR/default-trait-bounds.rs:65:34
31+
|
32+
LL | #[cfg(fail)] fn c1_fail() { c1::<ExternTy>; }
33+
| ^^^^^^^^ the nightly-only, unstable trait `MetaSized` is not implemented for `ExternTy`
34+
|
35+
= note: required for `ExternTy` to implement `C1`
36+
note: required by a bound in `c1`
37+
--> $DIR/default-trait-bounds.rs:63:35
38+
|
39+
LL | fn c1<T: PointeeSized>() where T: C1 { ensure_is_meta_sized::<T>; }
40+
| ^^ required by this bound in `c1`
41+
42+
error: aborting due to 3 previous errors
43+
44+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Check that trait alias bounds also imply default trait bounds to ensure that
2+
// default and user-written bounds behave the same wrt. trait solving.
3+
//
4+
// Previously, we would only imply default trait bounds on
5+
// *`Self`* type params, not on regular type params however.
6+
// issue: <https://github.com/rust-lang/rust/issues/152687>
7+
//
8+
//@ revisions: pass fail
9+
//@[pass] check-pass
10+
11+
#![feature(trait_alias)]
12+
#![feature(sized_hierarchy, extern_types)] // only used for the `MetaSized` test cases
13+
14+
//------------------------- `Sized`
15+
16+
trait A0<T: Sized> =; // has a user-written `T: Sized` boun
17+
18+
// `(): A0<T>` requires+implies `T: Sized`
19+
fn a0<T: ?Sized>() where (): A0<T> { ensure_is_sized::<T>; }
20+
21+
22+
trait A1<T> =; // has a default `T: Sized` bound
23+
24+
// `(): A1<T>` requires+implies `T: Sized`
25+
fn a1<T: ?Sized>() where (): A1<T> { ensure_is_sized::<T>; }
26+
#[cfg(fail)] fn a1_fail() { a1::<str>; }
27+
//[fail]~^ ERROR the size for values of type `str` cannot be known at compilation time
28+
29+
30+
fn ensure_is_sized<T: Sized>() {}
31+
32+
//------------------------- `MetaSized`
33+
34+
use std::marker::{MetaSized, PointeeSized};
35+
unsafe extern "C" { type ExternTy; }
36+
37+
38+
trait B0<T: MetaSized> =; // has a user-written `T: MetaSized` bounds
39+
40+
// `(): B0<T>` requires+implies `T: MetaSized`
41+
fn b0<T: PointeeSized>() where (): B0<T> { ensure_is_meta_sized::<T>(); }
42+
43+
44+
trait B1<T: ?Sized> =; // has a default `T: MetaSized` bound
45+
46+
// `(): B1<T>` requires+implies `T: MetaSized`
47+
fn b1<T: PointeeSized>() where (): B1<T> { ensure_is_meta_sized::<T>(); }
48+
49+
#[cfg(fail)] fn b1_fail() { b1::<ExternTy>; }
50+
//[fail]~^ ERROR the size for values of type `ExternTy` cannot be known
51+
52+
// For completeness, let's also check default trait bounds on `Self`.
53+
54+
trait C0 = MetaSized; // has a user-written `Self: MetaSized` bound
55+
56+
// `T: C0` requires+implies `T: MetaSized`
57+
fn c0<T: PointeeSized>() where T: C0 { ensure_is_meta_sized::<T>; }
58+
59+
60+
trait C1 =; // has a default `Self: MetaSized` bound
61+
62+
// `T: C1` requires+implies `T: MetaSized`
63+
fn c1<T: PointeeSized>() where T: C1 { ensure_is_meta_sized::<T>; }
64+
65+
#[cfg(fail)] fn c1_fail() { c1::<ExternTy>; }
66+
//[fail]~^ ERROR the trait bound `ExternTy: C1` is not satisfied
67+
68+
69+
fn ensure_is_meta_sized<T: MetaSized>() {}
70+
71+
fn main() {}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0277]: the trait bound `Unmarked: Mark` is not satisfied
2+
--> $DIR/more-default-trait-bounds.rs:27:34
3+
|
4+
LL | #[cfg(fail)] fn a1_fail() { a1::<Unmarked>; }
5+
| ^^^^^^^^ unsatisfied trait bound
6+
|
7+
help: the trait `Mark` is not implemented for `Unmarked`
8+
--> $DIR/more-default-trait-bounds.rs:47:1
9+
|
10+
LL | enum Unmarked {}
11+
| ^^^^^^^^^^^^^
12+
= note: required for `()` to implement `A1<Unmarked>`
13+
note: required by a bound in `a1`
14+
--> $DIR/more-default-trait-bounds.rs:25:29
15+
|
16+
LL | fn a1<T: ?Mark>() where (): A1<T> { ensure_has_mark::<T>; }
17+
| ^^^^^ required by this bound in `a1`
18+
19+
error[E0277]: the trait bound `Unmarked: B1` is not satisfied
20+
--> $DIR/more-default-trait-bounds.rs:41:34
21+
|
22+
LL | #[cfg(fail)] fn b1_fail() { b1::<Unmarked>; }
23+
| ^^^^^^^^ unsatisfied trait bound
24+
|
25+
help: the trait `Mark` is not implemented for `Unmarked`
26+
--> $DIR/more-default-trait-bounds.rs:47:1
27+
|
28+
LL | enum Unmarked {}
29+
| ^^^^^^^^^^^^^
30+
= note: required for `Unmarked` to implement `B1`
31+
note: required by a bound in `b1`
32+
--> $DIR/more-default-trait-bounds.rs:39:28
33+
|
34+
LL | fn b1<T: ?Mark>() where T: B1 { ensure_has_mark::<T>; }
35+
| ^^ required by this bound in `b1`
36+
37+
error: aborting due to 2 previous errors
38+
39+
For more information about this error, try `rustc --explain E0277`.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Check that trait alias bounds also imply default trait bounds to ensure_has_mark that
2+
// default and user-written bounds behave the same wrt. trait solving.
3+
//
4+
// Previously, we would only imply default trait bounds on
5+
// *`Self`* type params, not on regular type params however.
6+
// issue: <https://github.com/rust-lang/rust/issues/152687>
7+
//
8+
//@ revisions: pass fail
9+
//@ compile-flags: -Zexperimental-default-bounds
10+
//@[pass] check-pass
11+
12+
#![feature(trait_alias, more_maybe_bounds, lang_items, auto_traits, negative_impls)]
13+
14+
#[lang = "default_trait1"]
15+
auto trait Mark {}
16+
17+
18+
trait A0<T: Mark> = ?Mark; // has a user-written `T: Mark` bound
19+
20+
fn a0<T: ?Mark>() where (): A0<T> { ensure_has_mark::<T>; }
21+
22+
23+
trait A1<T> = ?Mark; // has a default `T: Mark` bound
24+
25+
fn a1<T: ?Mark>() where (): A1<T> { ensure_has_mark::<T>; }
26+
27+
#[cfg(fail)] fn a1_fail() { a1::<Unmarked>; }
28+
//[fail]~^ ERROR the trait bound `Unmarked: Mark` is not satisfied
29+
30+
// For completeness, let's also check default trait bounds on `Self`.
31+
32+
trait B0 = Mark; // has a user-written `Self: Mark` bound
33+
34+
fn b0<T: ?Mark>() where T: B0 { ensure_has_mark::<T>; }
35+
36+
37+
trait B1 =; // has a default `Self: Mark` bound
38+
39+
fn b1<T: ?Mark>() where T: B1 { ensure_has_mark::<T>; }
40+
41+
#[cfg(fail)] fn b1_fail() { b1::<Unmarked>; }
42+
//[fail]~^ ERROR the trait bound `Unmarked: B1` is not satisfied
43+
44+
45+
fn ensure_has_mark<T: Mark>() {}
46+
47+
enum Unmarked {}
48+
impl !Mark for Unmarked {}
49+
50+
fn main() {}

0 commit comments

Comments
 (0)