Rollup merge of #67820 - ecstatic-morse:const-trait, r=oli-obk

Parse the syntax described in RFC 2632

This adds support for both `impl const Trait for Ty` and `?const Trait` bound syntax from rust-lang/rfcs#2632 to the parser. For now, both modifiers end up in a newly-added `constness` field on `ast::TraitRef`, although this may change once the implementation is fleshed out.

I was planning on using `delay_span_bug` when this syntax is encountered during lowering, but I can't write `should-ice` UI tests. I emit a normal error instead, which causes duplicates when the feature gate is not enabled (see the `.stderr` files for the feature gate tests). Not sure what the desired approach is; Maybe just do nothing when the syntax is encountered with the feature gate is enabled?

@oli-obk I went with `const_trait_impl` and `const_trait_bound_opt_out` for the names of these features. Are these to your liking?

cc #67792 #67794

r? @Centril
This commit is contained in:
Mazdak Farrokhzad 2020-01-10 02:47:32 +01:00 committed by GitHub
commit f3963873aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 586 additions and 25 deletions

View file

@ -8,6 +8,11 @@ struct S<
T: ?for<'a> Trait, // OK
T: Tr +, // OK
T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
T: ?const Tr, // OK
T: ?const ?Tr, // OK
T: ?const Tr + 'a, // OK
T: ?const 'a, //~ ERROR `?const` may only modify trait bounds, not lifetime bounds
>;
fn main() {}

View file

@ -4,5 +4,11 @@ error: `?` may only modify trait bounds, not lifetime bounds
LL | T: ?'a,
| ^
error: aborting due to previous error
error: `?const` may only modify trait bounds, not lifetime bounds
--> $DIR/bounds-type.rs:15:8
|
LL | T: ?const 'a,
| ^^^^^^
error: aborting due to 2 previous errors

View file

@ -0,0 +1,8 @@
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 previous error

View file

@ -0,0 +1,15 @@
// revisions: stock gated
// gate-test-const_trait_bound_opt_out
#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
#![allow(incomplete_features)]
trait T {
const CONST: i32;
}
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() {}

View file

@ -0,0 +1,18 @@
error[E0658]: `?const` on trait bounds is experimental
--> $DIR/feature-gate.rs:11:29
|
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
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,25 @@
#![feature(const_trait_bound_opt_out)]
#![feature(associated_type_bounds)]
#![allow(incomplete_features)]
trait T {}
struct S;
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

@ -0,0 +1,50 @@
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:9:19
|
LL | fn rpit() -> impl ?const T { S }
| ^^^^^^^^
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:13:17
|
LL | fn apit(_: impl ?const T) {}
| ^^^^^^^^
error: `?const` is not permitted in `impl Trait`
--> $DIR/in-impl-trait.rs:17: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
|
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

View file

@ -0,0 +1,9 @@
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
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

@ -0,0 +1,14 @@
error: `?const` is not permitted in supertraits
--> $DIR/in-trait-bounds.rs:5:10
|
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

View file

@ -0,0 +1,22 @@
#![feature(const_trait_bound_opt_out)]
#![allow(bare_trait_objects)]
#![allow(incomplete_features)]
struct S;
trait T {}
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

@ -0,0 +1,38 @@
error: `?const` is not permitted in trait objects
--> $DIR/in-trait-object.rs:10:6
|
LL | impl ?const T {}
| ^^^^^^^^
error: `?const` is not permitted in trait objects
--> $DIR/in-trait-object.rs:14: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
|
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

View file

@ -0,0 +1,8 @@
// compile-flags: -Z parse-only
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
struct S<T: ?const ?const Tr>;
//~^ ERROR expected identifier, found keyword `const`
//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`

View file

@ -0,0 +1,14 @@
error: expected identifier, found keyword `const`
--> $DIR/opt-out-twice.rs:6:21
|
LL | struct S<T: ?const ?const Tr>;
| ^^^^^ expected identifier, found keyword
error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr`
--> $DIR/opt-out-twice.rs:6:27
|
LL | struct S<T: ?const ?const Tr>;
| ^^ expected one of 7 possible tokens
error: aborting due to 2 previous errors

View file

@ -0,0 +1,10 @@
// compile-flags: -Z parse-only
// check-pass
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
struct S<
T: ?const ?for<'a> Tr<'a> + 'static + ?const std::ops::Add,
T: ?const ?for<'a: 'b> m::Trait<'a>,
>;

View file

@ -0,0 +1,8 @@
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
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

@ -0,0 +1,14 @@
error: `?const` and `?` are mutually exclusive
--> $DIR/with-maybe-sized.rs:4:13
|
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

View file

@ -0,0 +1,7 @@
// compile-flags: -Z parse-only
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
struct S<T: const Tr>;
//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path

View file

@ -0,0 +1,8 @@
error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found keyword `const`
--> $DIR/without-question-mark.rs:6:13
|
LL | struct S<T: const Tr>;
| ^^^^^ expected one of 9 possible tokens
error: aborting due to previous error

View file

@ -0,0 +1,8 @@
error: const trait impls are not yet implemented
--> $DIR/feature-gate.rs:9:1
|
LL | impl const T for S {}
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,13 @@
// revisions: stock gated
// gate-test-const_trait_impl
#![cfg_attr(gated, feature(const_trait_impl))]
#![allow(incomplete_features)]
struct S;
trait T {}
impl const T for S {}
//[stock]~^ ERROR const trait impls are experimental
//[stock,gated]~^^ ERROR const trait impls are not yet implemented
fn main() {}

View file

@ -0,0 +1,18 @@
error[E0658]: const trait impls are experimental
--> $DIR/feature-gate.rs:9:6
|
LL | impl const T for S {}
| ^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/67792
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
error: const trait impls are not yet implemented
--> $DIR/feature-gate.rs:9:1
|
LL | impl const T for S {}
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,11 @@
#![feature(const_trait_bound_opt_out)]
#![feature(const_trait_impl)]
#![allow(incomplete_features)]
struct S;
trait T {}
impl ?const T for S {}
//~^ ERROR expected a trait, found type
fn main() {}

View file

@ -0,0 +1,8 @@
error: expected a trait, found type
--> $DIR/impl-opt-out-trait.rs:8:6
|
LL | impl ?const T for S {}
| ^^^^^^^^
error: aborting due to previous error

View file

@ -0,0 +1,14 @@
// compile-flags: -Z parse-only
#![feature(const_trait_impl)]
#![feature(const_trait_bound_opt_out)]
#![allow(incomplete_features)]
#![allow(bare_trait_objects)]
struct S;
trait T {}
impl const T {}
//~^ ERROR `const` cannot modify an inherent impl
fn main() {}

View file

@ -0,0 +1,10 @@
error: `const` cannot modify an inherent impl
--> $DIR/inherent-impl.rs:11:6
|
LL | impl const T {}
| ^^^^^
|
= help: only a trait impl can be `const`
error: aborting due to previous error

View file

@ -0,0 +1,9 @@
// compile-flags: -Z parse-only
// check-pass
#![feature(const_trait_bound_opt_out)]
#![feature(const_trait_impl)]
#![allow(incomplete_features)]
// For now, this parses since an error does not occur until AST lowering.
impl ?const T {}