Reject relaxed bounds inside trait alias bounds
This commit is contained in:
parent
690a8a6dfd
commit
ce68cd3762
18 changed files with 131 additions and 116 deletions
|
|
@ -426,7 +426,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
this.lower_param_bounds(
|
||||
bounds,
|
||||
RelaxedBoundPolicy::Allowed,
|
||||
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias),
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -296,6 +296,7 @@ enum RelaxedBoundPolicy<'a> {
|
|||
enum RelaxedBoundForbiddenReason {
|
||||
TraitObjectTy,
|
||||
SuperTrait,
|
||||
TraitAlias,
|
||||
AssocTyBounds,
|
||||
LateBoundVarsInScope,
|
||||
}
|
||||
|
|
@ -2132,6 +2133,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
gate("supertrait bounds", "traits");
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::TraitAlias => {
|
||||
gate("trait alias bounds", "trait aliases");
|
||||
return;
|
||||
}
|
||||
RelaxedBoundForbiddenReason::AssocTyBounds
|
||||
| RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -202,9 +202,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// where we are guaranteed to catch *all* bounds like in
|
||||
// `Self::lower_poly_trait_ref`. List of concrete issues:
|
||||
// FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait
|
||||
// bounds or associated type bounds (ATB)!
|
||||
// FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
|
||||
// AST lowering should reject them outright.
|
||||
// bounds, trait alias bounds, assoc type bounds (ATB)!
|
||||
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
|
||||
self.check_and_report_invalid_relaxed_bounds(bounds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait Bar {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block
|
||||
--> $DIR/doc-alias-assoc-const.rs:10:11
|
||||
--> $DIR/doc-alias-assoc-const.rs:8:11
|
||||
|
|
||||
LL | #[doc(alias = "CONST_BAZ")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: --crate-type=lib
|
||||
#![feature(trait_alias)]
|
||||
|
||||
// Checks that `?Sized` in a trait alias doesn't trigger an ICE.
|
||||
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
pub trait SlicePrereq<T> = ?Sized + IndexMut<usize, Output = <[T] as Index<usize>>::Output>;
|
||||
20
tests/ui/traits/alias/effectively-empty-trait-object-type.rs
Normal file
20
tests/ui/traits/alias/effectively-empty-trait-object-type.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Test that we reject trait object types that effectively (i.e., after trait alias expansion)
|
||||
// don't contain any bounds.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Empty0 =;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait Empty1 = Empty0;
|
||||
trait Empty2 = Empty1;
|
||||
|
||||
// Straight list expansion:
|
||||
type Type0 = dyn Empty2; //~ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
// Twice:
|
||||
trait Empty3 = Empty2 + Empty2;
|
||||
|
||||
type Type1 = dyn Empty3; //~ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/effectively-empty-trait-object-type.rs:13:14
|
||||
|
|
||||
LL | trait Empty2 = Empty1;
|
||||
| ------------ this alias does not contain a trait
|
||||
...
|
||||
LL | type Type0 = dyn Empty2;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/effectively-empty-trait-object-type.rs:18:14
|
||||
|
|
||||
LL | trait Empty3 = Empty2 + Empty2;
|
||||
| ------------ this alias does not contain a trait
|
||||
LL |
|
||||
LL | type Type1 = dyn Empty3;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
17
tests/ui/traits/alias/empty.rs
Normal file
17
tests/ui/traits/alias/empty.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Ensure that there are straightforward ways to define "empty" / "trivial" / "unit" trait aliases
|
||||
// which don't impose any constraints when used as a bound (since they expand to nothing).
|
||||
//@ check-pass
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Empty =;
|
||||
|
||||
trait Trivial = where;
|
||||
|
||||
trait Unit = where Self:;
|
||||
|
||||
fn check<T: ?Sized + Empty>() {}
|
||||
|
||||
fn main() {
|
||||
check::<()>(); // OK. "`(): Empty`" is trivially satisfied
|
||||
check::<str>(); // OK. `Empty` is truly empty and isn't implicitly bounded by `Sized`.
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
//@ build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
trait S = ?Sized;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait _0 = S;
|
||||
trait _1 = _0;
|
||||
|
||||
// Straight list expansion:
|
||||
type _T0 = dyn _1 + Foo;
|
||||
|
||||
// In second position:
|
||||
type _T1 = dyn Foo + _1;
|
||||
|
||||
// ... and with an auto trait:
|
||||
type _T2 = dyn Foo + Send + _1;
|
||||
|
||||
// Twice:
|
||||
trait _2 = _1 + _1;
|
||||
|
||||
type _T3 = dyn _2 + Foo;
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just
|
||||
// `?Sized` results from trait alias expansion.
|
||||
|
||||
#![feature(trait_alias)]
|
||||
|
||||
trait S = ?Sized;
|
||||
|
||||
// Nest a couple of levels deep:
|
||||
trait _0 = S;
|
||||
trait _1 = _0;
|
||||
|
||||
// Straight list expansion:
|
||||
type _T0 = dyn _1;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
// Twice:
|
||||
trait _2 = _1 + _1;
|
||||
|
||||
type _T1 = dyn _2;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:13:12
|
||||
|
|
||||
LL | trait _1 = _0;
|
||||
| -------- this alias does not contain a trait
|
||||
...
|
||||
LL | type _T0 = dyn _1;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:19:12
|
||||
|
|
||||
LL | trait _2 = _1 + _1;
|
||||
| -------- this alias does not contain a trait
|
||||
LL |
|
||||
LL | type _T1 = dyn _2;
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
19
tests/ui/traits/alias/relaxed-bounds.rs
Normal file
19
tests/ui/traits/alias/relaxed-bounds.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#![feature(trait_alias)]
|
||||
|
||||
// Ensure that relaxed bounds are not permitted in the `Self` bounds of trait aliases because trait
|
||||
// aliases (like traits) aren't implicitly bounded by `Sized` so there's nothing to relax.
|
||||
|
||||
trait Alias0 = ?Sized; //~ ERROR relaxed bounds are not permitted in trait alias bounds
|
||||
trait Alias1 = where Self: ?Sized; //~ ERROR this relaxed bound is not permitted here
|
||||
|
||||
trait Alias2<T: ?Sized> =; // OK
|
||||
trait Alias3<T> = where T: ?Sized; // OK
|
||||
|
||||
// Make sure that we don't permit "relaxing" trait aliases since we don't want to expand trait
|
||||
// aliases during sized elaboration for simplicity as we'd need to handle relaxing arbitrary bounds
|
||||
// (e.g., ones with modifiers, outlives-bounds, …) and where-clauses.
|
||||
|
||||
trait SizedAlias = Sized;
|
||||
fn take<T: ?SizedAlias>() {} //~ ERROR bound modifier `?` can only be applied to `Sized`
|
||||
|
||||
fn main() {}
|
||||
24
tests/ui/traits/alias/relaxed-bounds.stderr
Normal file
24
tests/ui/traits/alias/relaxed-bounds.stderr
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
error: relaxed bounds are not permitted in trait alias bounds
|
||||
--> $DIR/relaxed-bounds.rs:6:16
|
||||
|
|
||||
LL | trait Alias0 = ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait aliases are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: this relaxed bound is not permitted here
|
||||
--> $DIR/relaxed-bounds.rs:7:28
|
||||
|
|
||||
LL | trait Alias1 = where Self: ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item
|
||||
|
||||
error: bound modifier `?` can only be applied to `Sized`
|
||||
--> $DIR/relaxed-bounds.rs:17:12
|
||||
|
|
||||
LL | fn take<T: ?SizedAlias>() {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed.
|
||||
|
||||
type _0 = dyn ?Sized;
|
||||
//~^ ERROR at least one trait is required for an object type [E0224]
|
||||
//~| ERROR relaxed bounds are not permitted in trait object types
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/only-maybe-bound.rs:3:15
|
||||
|
|
||||
LL | type _0 = dyn ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/only-maybe-bound.rs:3:11
|
||||
|
|
||||
LL | type _0 = dyn ?Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
|
|
@ -30,6 +30,9 @@ trait Tr: ?Sized {} //~ ERROR relaxed bounds are not permitted in supertrait bou
|
|||
|
||||
// Test that relaxed `Sized` bounds are rejected in trait object types:
|
||||
|
||||
type O0 = dyn ?Sized;
|
||||
//~^ ERROR relaxed bounds are not permitted in trait object types
|
||||
//~| ERROR at least one trait is required for an object type [E0224]
|
||||
type O1 = dyn Tr + ?Sized; //~ ERROR relaxed bounds are not permitted in trait object types
|
||||
type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
//~^ ERROR relaxed bounds are not permitted in trait object types
|
||||
|
|
|
|||
|
|
@ -55,7 +55,15 @@ LL | trait Tr: ?Sized {}
|
|||
= note: traits are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:20
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:15
|
||||
|
|
||||
LL | type O0 = dyn ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:36:20
|
||||
|
|
||||
LL | type O1 = dyn Tr + ?Sized;
|
||||
| ^^^^^^
|
||||
|
|
@ -63,7 +71,7 @@ LL | type O1 = dyn Tr + ?Sized;
|
|||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:34:15
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:37:15
|
||||
|
|
||||
LL | type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
| ^^^^^^
|
||||
|
|
@ -71,7 +79,7 @@ LL | type O2 = dyn ?Sized + ?Sized + Tr;
|
|||
= note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax
|
||||
|
||||
error: relaxed bounds are not permitted in trait object types
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:34:24
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:37:24
|
||||
|
|
||||
LL | type O2 = dyn ?Sized + ?Sized + Tr;
|
||||
| ^^^^^^
|
||||
|
|
@ -90,5 +98,12 @@ error: bound modifier `?` can only be applied to `Sized`
|
|||
LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
error[E0224]: at least one trait is required for an object type
|
||||
--> $DIR/relaxed-bounds-invalid-places.rs:33:11
|
||||
|
|
||||
LL | type O0 = dyn ?Sized;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0224`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue