Rollup merge of #151783 - mu001999-contrib:impl/final-method, r=fee1-dead
Implement RFC 3678: Final trait methods Tracking: https://github.com/rust-lang/rust/issues/131179 This PR is based on rust-lang/rust#130802, with some minor changes and conflict resolution. Futhermore, this PR excludes final methods from the vtable of a dyn Trait. And some excerpt from the original PR description: > Implements the surface part of https://github.com/rust-lang/rfcs/pull/3678. > > I'm using the word "method" in the title, but in the diagnostics and the feature gate I used "associated function", since that's more accurate. cc @joshtriplett
This commit is contained in:
commit
1367126837
57 changed files with 755 additions and 117 deletions
22
tests/rustdoc-html/final-trait-method.rs
Normal file
22
tests/rustdoc-html/final-trait-method.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#![feature(final_associated_functions)]
|
||||
|
||||
//@ has final_trait_method/trait.Item.html
|
||||
pub trait Item {
|
||||
//@ has - '//*[@id="method.foo"]' 'final fn foo()'
|
||||
//@ !has - '//*[@id="method.foo"]' 'default fn foo()'
|
||||
final fn foo() {}
|
||||
|
||||
//@ has - '//*[@id="method.bar"]' 'fn bar()'
|
||||
//@ !has - '//*[@id="method.bar"]' 'default fn bar()'
|
||||
//@ !has - '//*[@id="method.bar"]' 'final fn bar()'
|
||||
fn bar() {}
|
||||
}
|
||||
|
||||
//@ has final_trait_method/struct.Foo.html
|
||||
pub struct Foo;
|
||||
impl Item for Foo {
|
||||
//@ has - '//*[@id="method.bar"]' 'fn bar()'
|
||||
//@ !has - '//*[@id="method.bar"]' 'final fn bar()'
|
||||
//@ !has - '//*[@id="method.bar"]' 'default fn bar()'
|
||||
fn bar() {}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||
error: expected one of `#`, `async`, `const`, `default`, `extern`, `final`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||
--> $DIR/gen_fn.rs:4:1
|
||||
|
|
||||
LL | gen fn foo() {}
|
||||
| ^^^ expected one of 10 possible tokens
|
||||
| ^^^ expected one of 11 possible tokens
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//@[e2024] edition: 2024
|
||||
|
||||
gen fn foo() {}
|
||||
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||
//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `final`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen`
|
||||
//[e2024]~^^ ERROR: gen blocks are experimental
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
trait Foo {
|
||||
final fn bar() {}
|
||||
//~^ ERROR `final` on trait functions is experimental
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: `final` on trait functions is experimental
|
||||
--> $DIR/feature-gate-final-associated-functions.rs:2:5
|
||||
|
|
||||
LL | final fn bar() {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
|
||||
= help: add `#![feature(final_associated_functions)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -2,8 +2,8 @@ fn main() {}
|
|||
|
||||
extern "C" { //~ NOTE while parsing this item list starting here
|
||||
pub pub fn foo();
|
||||
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||
//~| NOTE expected one of 9 possible tokens
|
||||
//~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `final`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||
//~| NOTE expected one of 10 possible tokens
|
||||
//~| HELP there is already a visibility modifier, remove one
|
||||
//~| NOTE explicit visibility first seen here
|
||||
} //~ NOTE the item list ends here
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||
error: expected one of `(`, `async`, `const`, `default`, `extern`, `final`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub`
|
||||
--> $DIR/duplicate-visibility.rs:4:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
|
|
@ -6,7 +6,7 @@ LL | extern "C" {
|
|||
LL | pub pub fn foo();
|
||||
| ^^^
|
||||
| |
|
||||
| expected one of 9 possible tokens
|
||||
| expected one of 10 possible tokens
|
||||
| help: there is already a visibility modifier, remove one
|
||||
...
|
||||
LL | }
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB`
|
||||
error: expected one of `#`, `async`, `auto`, `const`, `default`, `enum`, `extern`, `final`, `fn`, `gen`, `impl`, `macro_rules`, `macro`, `mod`, `pub`, `safe`, `static`, `struct`, `trait`, `type`, `unsafe`, or `use`, found `puB`
|
||||
--> $DIR/pub-fn.rs:1:1
|
||||
|
|
||||
LL | puB fn code() {}
|
||||
| ^^^ expected one of 21 possible tokens
|
||||
| ^^^ expected one of 22 possible tokens
|
||||
|
|
||||
help: write keyword `pub` in lowercase
|
||||
|
|
||||
|
|
|
|||
40
tests/ui/traits/final/dyn-compat.rs
Normal file
40
tests/ui/traits/final/dyn-compat.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(final_associated_functions)]
|
||||
|
||||
trait FinalNoReceiver {
|
||||
final fn no_receiver() {}
|
||||
}
|
||||
|
||||
trait FinalGeneric {
|
||||
final fn generic<T>(&self, _value: T) {}
|
||||
}
|
||||
|
||||
trait FinalSelfParam {
|
||||
final fn self_param(&self, _other: &Self) {}
|
||||
}
|
||||
|
||||
trait FinalSelfReturn {
|
||||
final fn self_return(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl FinalNoReceiver for S {}
|
||||
impl FinalGeneric for S {}
|
||||
impl FinalSelfParam for S {}
|
||||
impl FinalSelfReturn for S {}
|
||||
|
||||
fn main() {
|
||||
let s = S;
|
||||
<S as FinalNoReceiver>::no_receiver();
|
||||
let obj_generic: &dyn FinalGeneric = &s;
|
||||
let obj_param: &dyn FinalSelfParam = &s;
|
||||
let obj_return: &dyn FinalSelfReturn = &s;
|
||||
obj_generic.generic(1u8);
|
||||
obj_param.self_param(obj_param);
|
||||
let _ = obj_return.self_return();
|
||||
let _: &dyn FinalNoReceiver = &s;
|
||||
}
|
||||
13
tests/ui/traits/final/final-kw.gated.stderr
Normal file
13
tests/ui/traits/final/final-kw.gated.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: `final` on trait functions is experimental
|
||||
--> $DIR/final-kw.rs:5:5
|
||||
|
|
||||
LL | final fn foo() {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
|
||||
= help: add `#![feature(final_associated_functions)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
9
tests/ui/traits/final/final-kw.rs
Normal file
9
tests/ui/traits/final/final-kw.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
//@ revisions: ungated gated
|
||||
|
||||
#[cfg(ungated)]
|
||||
trait Trait {
|
||||
final fn foo() {}
|
||||
//~^ ERROR `final` on trait functions is experimental
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
13
tests/ui/traits/final/final-kw.ungated.stderr
Normal file
13
tests/ui/traits/final/final-kw.ungated.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0658]: `final` on trait functions is experimental
|
||||
--> $DIR/final-kw.rs:5:5
|
||||
|
|
||||
LL | final fn foo() {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
|
||||
= help: add `#![feature(final_associated_functions)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
8
tests/ui/traits/final/final-must-have-body.rs
Normal file
8
tests/ui/traits/final/final-must-have-body.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#![feature(final_associated_functions)]
|
||||
|
||||
trait Foo {
|
||||
final fn method();
|
||||
//~^ ERROR `final` is only allowed on associated functions if they have a body
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
10
tests/ui/traits/final/final-must-have-body.stderr
Normal file
10
tests/ui/traits/final/final-must-have-body.stderr
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
error: `final` is only allowed on associated functions if they have a body
|
||||
--> $DIR/final-must-have-body.rs:4:5
|
||||
|
|
||||
LL | final fn method();
|
||||
| -----^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
12
tests/ui/traits/final/overriding.rs
Normal file
12
tests/ui/traits/final/overriding.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#![feature(final_associated_functions)]
|
||||
|
||||
trait Foo {
|
||||
final fn method() {}
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
fn method() {}
|
||||
//~^ ERROR cannot override `method` because it already has a `final` definition in the trait
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
14
tests/ui/traits/final/overriding.stderr
Normal file
14
tests/ui/traits/final/overriding.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: cannot override `method` because it already has a `final` definition in the trait
|
||||
--> $DIR/overriding.rs:8:5
|
||||
|
|
||||
LL | fn method() {}
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
note: `method` is marked final here
|
||||
--> $DIR/overriding.rs:4:5
|
||||
|
|
||||
LL | final fn method() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
72
tests/ui/traits/final/positions.rs
Normal file
72
tests/ui/traits/final/positions.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#![feature(final_associated_functions)]
|
||||
|
||||
// Just for exercising the syntax positions
|
||||
#![feature(associated_type_defaults, extern_types, inherent_associated_types)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
final struct Foo {}
|
||||
//~^ ERROR a struct cannot be `final`
|
||||
|
||||
final trait Trait {
|
||||
//~^ ERROR a trait cannot be `final`
|
||||
|
||||
final fn method() {}
|
||||
// OK!
|
||||
|
||||
final type Foo = ();
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final const FOO: usize = 1;
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
}
|
||||
|
||||
final impl Foo {
|
||||
final fn method() {}
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final type Foo = ();
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final const FOO: usize = 1;
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
}
|
||||
|
||||
final impl Trait for Foo {
|
||||
final fn method() {}
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
//~^^ ERROR cannot override `method` because it already has a `final` definition in the trait
|
||||
|
||||
final type Foo = ();
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
//~^^ ERROR cannot override `Foo` because it already has a `final` definition in the trait
|
||||
|
||||
final const FOO: usize = 1;
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
//~^^ ERROR cannot override `FOO` because it already has a `final` definition in the trait
|
||||
}
|
||||
|
||||
|
||||
final fn foo() {}
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final type FooTy = ();
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final const FOO: usize = 0;
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final unsafe extern "C" {
|
||||
//~^ ERROR an extern block cannot be `final`
|
||||
|
||||
final fn foo_extern();
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final type FooExtern;
|
||||
//~^ ERROR `final` is only allowed on associated functions in traits
|
||||
|
||||
final static FOO_EXTERN: usize = 0;
|
||||
//~^ ERROR a static item cannot be `final`
|
||||
//~| ERROR incorrect `static` inside `extern` block
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
187
tests/ui/traits/final/positions.stderr
Normal file
187
tests/ui/traits/final/positions.stderr
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
error: a struct cannot be `final`
|
||||
--> $DIR/positions.rs:7:1
|
||||
|
|
||||
LL | final struct Foo {}
|
||||
| ^^^^^ `final` because of this
|
||||
|
|
||||
= note: only associated functions in traits can be `final`
|
||||
|
||||
error: a trait cannot be `final`
|
||||
--> $DIR/positions.rs:10:1
|
||||
|
|
||||
LL | final trait Trait {
|
||||
| ^^^^^ `final` because of this
|
||||
|
|
||||
= note: only associated functions in traits can be `final`
|
||||
|
||||
error: a static item cannot be `final`
|
||||
--> $DIR/positions.rs:67:5
|
||||
|
|
||||
LL | final static FOO_EXTERN: usize = 0;
|
||||
| ^^^^^ `final` because of this
|
||||
|
|
||||
= note: only associated functions in traits can be `final`
|
||||
|
||||
error: an extern block cannot be `final`
|
||||
--> $DIR/positions.rs:58:1
|
||||
|
|
||||
LL | final unsafe extern "C" {
|
||||
| ^^^^^ `final` because of this
|
||||
|
|
||||
= note: only associated functions in traits can be `final`
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:16:5
|
||||
|
|
||||
LL | final type Foo = ();
|
||||
| -----^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:19:5
|
||||
|
|
||||
LL | final const FOO: usize = 1;
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:24:5
|
||||
|
|
||||
LL | final fn method() {}
|
||||
| -----^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:27:5
|
||||
|
|
||||
LL | final type Foo = ();
|
||||
| -----^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:30:5
|
||||
|
|
||||
LL | final const FOO: usize = 1;
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:35:5
|
||||
|
|
||||
LL | final fn method() {}
|
||||
| -----^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:39:5
|
||||
|
|
||||
LL | final type Foo = ();
|
||||
| -----^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:43:5
|
||||
|
|
||||
LL | final const FOO: usize = 1;
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:49:1
|
||||
|
|
||||
LL | final fn foo() {}
|
||||
| -----^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:52:1
|
||||
|
|
||||
LL | final type FooTy = ();
|
||||
| -----^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:55:1
|
||||
|
|
||||
LL | final const FOO: usize = 0;
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:61:5
|
||||
|
|
||||
LL | final fn foo_extern();
|
||||
| -----^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: `final` is only allowed on associated functions in traits
|
||||
--> $DIR/positions.rs:64:5
|
||||
|
|
||||
LL | final type FooExtern;
|
||||
| -----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `final` because of this
|
||||
|
||||
error: incorrect `static` inside `extern` block
|
||||
--> $DIR/positions.rs:67:18
|
||||
|
|
||||
LL | final unsafe extern "C" {
|
||||
| ----------------------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body
|
||||
...
|
||||
LL | final static FOO_EXTERN: usize = 0;
|
||||
| ^^^^^^^^^^ - the invalid body
|
||||
| |
|
||||
| cannot have a body
|
||||
|
|
||||
= note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
|
||||
|
||||
error: cannot override `method` because it already has a `final` definition in the trait
|
||||
--> $DIR/positions.rs:35:5
|
||||
|
|
||||
LL | final fn method() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: `method` is marked final here
|
||||
--> $DIR/positions.rs:13:5
|
||||
|
|
||||
LL | final fn method() {}
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot override `Foo` because it already has a `final` definition in the trait
|
||||
--> $DIR/positions.rs:39:5
|
||||
|
|
||||
LL | final type Foo = ();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: `Foo` is marked final here
|
||||
--> $DIR/positions.rs:16:5
|
||||
|
|
||||
LL | final type Foo = ();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot override `FOO` because it already has a `final` definition in the trait
|
||||
--> $DIR/positions.rs:43:5
|
||||
|
|
||||
LL | final const FOO: usize = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: `FOO` is marked final here
|
||||
--> $DIR/positions.rs:19:5
|
||||
|
|
||||
LL | final const FOO: usize = 1;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
|
||||
13
tests/ui/traits/final/works.rs
Normal file
13
tests/ui/traits/final/works.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(final_associated_functions)]
|
||||
|
||||
trait Foo {
|
||||
final fn bar(&self) {}
|
||||
}
|
||||
|
||||
impl Foo for () {}
|
||||
|
||||
fn main() {
|
||||
().bar();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue