Rollup merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=oli-obk

Implement `?const` opt-out for trait bounds

For now, such bounds are treated exactly the same as unprefixed ones in all contexts. [RFC 2632](https://github.com/rust-lang/rfcs/pull/2632) does not specify whether such bounds are forbidden outside of `const` contexts, so they are allowed at the moment.

Prior to this PR, the constness of a trait bound/impl was stored in `TraitRef`. Now, the constness of an `impl` is stored in `ast::ItemKind::Impl` and the constness of a bound in `ast::TraitBoundModifer`. Additionally, constness of trait bounds is now stored in an additional field of `ty::Predicate::Trait`, and the combination of the constness of the item along with any `TraitBoundModifier` determines the constness of the bound in accordance with the RFC. Encoding the constness of impls at the `ty` level is left for a later PR.

After a discussion in \#wg-grammar on Discord, it was decided that the grammar should not encode the mutual exclusivity of trait bound modifiers. The grammar for trait bound modifiers remains `[?const] [?]`. To encode this, I add a dummy variant to `ast::TraitBoundModifier` that is used when the syntax `?const ?` appears. This variant causes an error in AST validation and disappears during HIR lowering.

cc #67794

r? @oli-obk
This commit is contained in:
Mazdak Farrokhzad 2020-01-21 19:42:20 +01:00 committed by GitHub
commit 3484e2fab4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
71 changed files with 495 additions and 311 deletions

View file

@ -1,8 +1,8 @@
error: `?const` on trait bounds is not yet implemented
--> $DIR/feature-gate.rs:11:29
error: fatal error triggered by #[rustc_error]
--> $DIR/feature-gate.rs:16:1
|
LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
| ^^^^^^^^
LL | fn main() {}
| ^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -3,6 +3,7 @@
#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
#![allow(incomplete_features)]
#![feature(rustc_attrs)]
trait T {
const CONST: i32;
@ -10,6 +11,6 @@ trait T {
const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
//[stock]~^ ERROR `?const` on trait bounds is experimental
//[stock,gated]~^^ ERROR `?const` on trait bounds is not yet implemented
fn main() {}
#[rustc_error]
fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]

View file

@ -1,5 +1,5 @@
error[E0658]: `?const` on trait bounds is experimental
--> $DIR/feature-gate.rs:11:29
--> $DIR/feature-gate.rs:12:29
|
LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
| ^^^^^^
@ -7,12 +7,6 @@ LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
= note: for more information, see https://github.com/rust-lang/rust/issues/67794
= help: add `#![feature(const_trait_bound_opt_out)]` to the crate attributes to enable
error: `?const` on trait bounds is not yet implemented
--> $DIR/feature-gate.rs:11:29
|
LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
| ^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -8,18 +8,14 @@ impl T for S {}
fn rpit() -> impl ?const T { S }
//~^ ERROR `?const` is not permitted in `impl Trait`
//~| ERROR `?const` on trait bounds is not yet implemented
fn apit(_: impl ?const T) {}
//~^ ERROR `?const` is not permitted in `impl Trait`
//~| ERROR `?const` on trait bounds is not yet implemented
fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
//~^ ERROR `?const` is not permitted in `impl Trait`
//~| ERROR `?const` on trait bounds is not yet implemented
fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
//~^ ERROR `?const` is not permitted in `impl Trait`
//~| ERROR `?const` on trait bounds is not yet implemented
fn main() {}

View file

@ -5,46 +5,22 @@ LL | fn rpit() -> impl ?const T { S }
| ^^^^^^^^
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:13:17
--> $DIR/in-impl-trait.rs:12:17
|
LL | fn apit(_: impl ?const T) {}
| ^^^^^^^^
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:17:50
--> $DIR/in-impl-trait.rs:15:50
|
LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
| ^^^^^^^^
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:21:48
--> $DIR/in-impl-trait.rs:18:48
|
LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-impl-trait.rs:9:19
|
LL | fn rpit() -> impl ?const T { S }
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-impl-trait.rs:13:17
|
LL | fn apit(_: impl ?const T) {}
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-impl-trait.rs:17:50
|
LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-impl-trait.rs:21:48
|
LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
| ^^^^^^^^
error: aborting due to 8 previous errors
error: aborting due to 4 previous errors

View file

@ -4,6 +4,5 @@
trait Super {}
trait T: ?const Super {}
//~^ ERROR `?const` is not permitted in supertraits
//~| ERROR `?const` on trait bounds is not yet implemented
fn main() {}

View file

@ -4,11 +4,5 @@ error: `?const` is not permitted in supertraits
LL | trait T: ?const Super {}
| ^^^^^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-trait-bounds.rs:5:10
|
LL | trait T: ?const Super {}
| ^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error

View file

@ -9,14 +9,11 @@ impl T for S {}
// An inherent impl for the trait object `?const T`.
impl ?const T {}
//~^ ERROR `?const` is not permitted in trait objects
//~| ERROR `?const` on trait bounds is not yet implemented
fn trait_object() -> &'static dyn ?const T { &S }
//~^ ERROR `?const` is not permitted in trait objects
//~| ERROR `?const` on trait bounds is not yet implemented
fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
//~^ ERROR `?const` is not permitted in trait objects
//~| ERROR `?const` on trait bounds is not yet implemented
fn main() {}

View file

@ -5,34 +5,16 @@ LL | impl ?const T {}
| ^^^^^^^^
error: `?const` is not permitted in trait objects
--> $DIR/in-trait-object.rs:14:35
--> $DIR/in-trait-object.rs:13:35
|
LL | fn trait_object() -> &'static dyn ?const T { &S }
| ^^^^^^^^
error: `?const` is not permitted in trait objects
--> $DIR/in-trait-object.rs:18:61
--> $DIR/in-trait-object.rs:16:61
|
LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-trait-object.rs:10:6
|
LL | impl ?const T {}
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-trait-object.rs:14:35
|
LL | fn trait_object() -> &'static dyn ?const T { &S }
| ^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/in-trait-object.rs:18:61
|
LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
| ^^^^^^^^
error: aborting due to 6 previous errors
error: aborting due to 3 previous errors

View file

@ -3,6 +3,5 @@
struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
//~^ ERROR `?const` and `?` are mutually exclusive
//~| ERROR `?const` on trait bounds is not yet implemented
fn main() {}

View file

@ -4,11 +4,5 @@ error: `?const` and `?` are mutually exclusive
LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^
error: `?const` on trait bounds is not yet implemented
--> $DIR/with-maybe-sized.rs:4:13
|
LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error

View file

@ -1,5 +1,3 @@
// compile-flags: -Z parse-only
#![feature(const_trait_impl)]
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
@ -8,7 +6,12 @@
struct S;
trait T {}
impl const S {}
//~^ ERROR inherent impls cannot be `const`
//~| ERROR const trait impls are not yet implemented
impl const T {}
//~^ ERROR `const` cannot modify an inherent impl
//~^ ERROR inherent impls cannot be `const`
//~| ERROR const trait impls are not yet implemented
fn main() {}

View file

@ -1,10 +1,30 @@
error: `const` cannot modify an inherent impl
--> $DIR/inherent-impl.rs:11:6
error: inherent impls cannot be `const`
--> $DIR/inherent-impl.rs:9:1
|
LL | impl const S {}
| ^^^^^^^^^^^^^^^
|
= note: only trait implementations may be annotated with `const`
error: inherent impls cannot be `const`
--> $DIR/inherent-impl.rs:13:1
|
LL | impl const T {}
| ^^^^^
| ^^^^^^^^^^^^^^^
|
= help: only a trait impl can be `const`
= note: only trait implementations may be annotated with `const`
error: aborting due to previous error
error: const trait impls are not yet implemented
--> $DIR/inherent-impl.rs:9:1
|
LL | impl const S {}
| ^^^^^^^^^^^^^^^
error: const trait impls are not yet implemented
--> $DIR/inherent-impl.rs:13:1
|
LL | impl const T {}
| ^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors