Auto merge of #129753 - folkertdev:stabilize-const-extern-fn, r=RalfJung
stabilize `const_extern_fn` closes https://github.com/rust-lang/rust/issues/64926 tracking issue: https://github.com/rust-lang/rust/issues/64926 reference PR: https://github.com/rust-lang/reference/pull/1596 ## Stabilizaton Report ### Summary Using `const extern "Rust"` and `const extern "C"` was already stabilized (since version 1.62.0, see https://github.com/rust-lang/rust/pull/95346). This PR stabilizes the other calling conventions: it is now possible to write `const unsafe extern "calling-convention" fn` and `const extern "calling-convention" fn` for any supported calling convention: ```rust const extern "C-unwind" fn foo1(val: u8) -> u8 { val + 1} const extern "stdcall" fn foo2(val: u8) -> u8 { val + 1} const unsafe extern "C-unwind" fn bar1(val: bool) -> bool { !val } const unsafe extern "stdcall" fn bar2(val: bool) -> bool { !val } ``` This can be used to const-ify an `extern fn`, or conversely, to make a `const fn` callable from external code. r? T-lang cc `@RalfJung`
This commit is contained in:
commit
4f1be92153
@ -75,22 +75,9 @@ struct PostExpansionVisitor<'a> {
|
||||
|
||||
impl<'a> PostExpansionVisitor<'a> {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||
fn check_abi(&self, abi: ast::StrLit) {
|
||||
let ast::StrLit { symbol_unescaped, span, .. } = abi;
|
||||
|
||||
if let ast::Const::Yes(_) = constness {
|
||||
match symbol_unescaped {
|
||||
// Stable
|
||||
sym::Rust | sym::C => {}
|
||||
abi => gate!(
|
||||
&self,
|
||||
const_extern_fn,
|
||||
span,
|
||||
format!("`{}` as a `const fn` ABI is unstable", abi)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
|
||||
Ok(()) => (),
|
||||
Err(abi::AbiDisabled::Unstable { feature, explain }) => {
|
||||
@ -110,9 +97,9 @@ fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_extern(&self, ext: ast::Extern, constness: ast::Const) {
|
||||
fn check_extern(&self, ext: ast::Extern) {
|
||||
if let ast::Extern::Explicit(abi, _) = ext {
|
||||
self.check_abi(abi, constness);
|
||||
self.check_abi(abi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +226,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||
match &i.kind {
|
||||
ast::ItemKind::ForeignMod(foreign_module) => {
|
||||
if let Some(abi) = foreign_module.abi {
|
||||
self.check_abi(abi, ast::Const::No);
|
||||
self.check_abi(abi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +328,7 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||
match &ty.kind {
|
||||
ast::TyKind::BareFn(bare_fn_ty) => {
|
||||
// Function pointers cannot be `const`
|
||||
self.check_extern(bare_fn_ty.ext, ast::Const::No);
|
||||
self.check_extern(bare_fn_ty.ext);
|
||||
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
|
||||
}
|
||||
ast::TyKind::Never => {
|
||||
@ -446,7 +433,7 @@ fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||
if let Some(header) = fn_kind.header() {
|
||||
// Stability of const fn methods are covered in `visit_assoc_item` below.
|
||||
self.check_extern(header.ext, header.constness);
|
||||
self.check_extern(header.ext);
|
||||
}
|
||||
|
||||
if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
|
||||
|
@ -115,6 +115,8 @@ macro_rules! declare_features {
|
||||
(accepted, conservative_impl_trait, "1.26.0", Some(34511)),
|
||||
/// Allows calling constructor functions in `const fn`.
|
||||
(accepted, const_constructor, "1.40.0", Some(61456)),
|
||||
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
|
||||
(accepted, const_extern_fn, "CURRENT_RUSTC_VERSION", Some(64926)),
|
||||
/// Allows basic arithmetic on floating point types in a `const fn`.
|
||||
(accepted, const_fn_floating_point_arithmetic, "1.82.0", Some(57241)),
|
||||
/// Allows using and casting function pointers in a `const fn`.
|
||||
|
@ -401,8 +401,6 @@ pub fn internal(&self, feature: Symbol) -> bool {
|
||||
(unstable, const_async_blocks, "1.53.0", Some(85368)),
|
||||
/// Allows `const || {}` closures in const contexts.
|
||||
(incomplete, const_closures, "1.68.0", Some(106003)),
|
||||
/// Allows the definition of `const extern fn` and `const unsafe extern fn`.
|
||||
(unstable, const_extern_fn, "1.40.0", Some(64926)),
|
||||
/// Allows `for _ in _` loops in const contexts.
|
||||
(unstable, const_for, "1.56.0", Some(87575)),
|
||||
/// Allows using `&mut` in constant functions.
|
||||
|
@ -607,9 +607,6 @@ fn parse_ty_bare_fn(
|
||||
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
|
||||
let whole_span = lo.to(self.prev_token.span);
|
||||
if let ast::Const::Yes(span) = constness {
|
||||
// If we ever start to allow `const fn()`, then update
|
||||
// feature gating for `#![feature(const_extern_fn)]` to
|
||||
// cover it.
|
||||
self.dcx().emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: span });
|
||||
}
|
||||
if let Some(ast::CoroutineKind::Async { span, .. }) = coroutine_kind {
|
||||
|
@ -17,6 +17,7 @@ macro_rules! msrv_aliases {
|
||||
|
||||
// names may refer to stabilized feature flags or library items
|
||||
msrv_aliases! {
|
||||
1,83,0 { CONST_EXTERN_FN }
|
||||
1,83,0 { CONST_FLOAT_BITS_CONV }
|
||||
1,81,0 { LINT_REASONS_STABILIZATION }
|
||||
1,80,0 { BOX_INTO_ITER}
|
||||
@ -27,7 +28,7 @@ macro_rules! msrv_aliases {
|
||||
1,68,0 { PATH_MAIN_SEPARATOR_STR }
|
||||
1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
|
||||
1,63,0 { CLONE_INTO }
|
||||
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_FN }
|
||||
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE, CONST_EXTERN_C_FN }
|
||||
1,59,0 { THREAD_LOCAL_CONST_INIT }
|
||||
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY, CONST_RAW_PTR_DEREF }
|
||||
1,56,0 { CONST_FN_UNION }
|
||||
|
@ -119,9 +119,7 @@ fn check_fn(
|
||||
.iter()
|
||||
.any(|param| matches!(param.kind, GenericParamKind::Const { .. }));
|
||||
|
||||
if already_const(header)
|
||||
|| has_const_generic_params
|
||||
|| !could_be_const_with_abi(cx, &self.msrv, header.abi)
|
||||
if already_const(header) || has_const_generic_params || !could_be_const_with_abi(&self.msrv, header.abi)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -183,13 +181,13 @@ fn already_const(header: hir::FnHeader) -> bool {
|
||||
header.constness == Constness::Const
|
||||
}
|
||||
|
||||
fn could_be_const_with_abi(cx: &LateContext<'_>, msrv: &Msrv, abi: Abi) -> bool {
|
||||
fn could_be_const_with_abi(msrv: &Msrv, abi: Abi) -> bool {
|
||||
match abi {
|
||||
Abi::Rust => true,
|
||||
// `const extern "C"` was stabilized after 1.62.0
|
||||
Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_FN),
|
||||
Abi::C { unwind: false } => msrv.meets(msrvs::CONST_EXTERN_C_FN),
|
||||
// Rest ABIs are still unstable and need the `const_extern_fn` feature enabled.
|
||||
_ => cx.tcx.features().const_extern_fn,
|
||||
_ => msrv.meets(msrvs::CONST_EXTERN_FN),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,12 +186,6 @@ fn deref_mut_ptr_cannot_be_const(self) -> usize {
|
||||
extern "C" fn c() {}
|
||||
}
|
||||
|
||||
mod with_extern {
|
||||
extern "C-unwind" fn c_unwind() {}
|
||||
extern "system" fn system() {}
|
||||
extern "system-unwind" fn system_unwind() {}
|
||||
}
|
||||
|
||||
mod with_ty_alias {
|
||||
type Foo = impl std::fmt::Debug;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
@ -204,3 +205,16 @@ mod with_ty_alias {
|
||||
// in this test.
|
||||
const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
}
|
||||
|
||||
mod extern_fn {
|
||||
const extern "C-unwind" fn c_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
const extern "system" fn system() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
const extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(incomplete_features, clippy::let_and_return, clippy::missing_transmute_annotations)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
@ -204,3 +205,16 @@ impl FooTrait for () {
|
||||
// in this test.
|
||||
fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
}
|
||||
|
||||
mod extern_fn {
|
||||
extern "C-unwind" fn c_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
extern "system" fn system() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:14:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:15:5
|
||||
|
|
||||
LL | / pub fn new() -> Self {
|
||||
LL | |
|
||||
@ -16,7 +16,7 @@ LL | pub const fn new() -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:20:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:21:5
|
||||
|
|
||||
LL | / fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
|
||||
LL | |
|
||||
@ -30,7 +30,7 @@ LL | const fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T;
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:27:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:28:1
|
||||
|
|
||||
LL | / fn one() -> i32 {
|
||||
LL | |
|
||||
@ -44,7 +44,7 @@ LL | const fn one() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:33:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:34:1
|
||||
|
|
||||
LL | / fn two() -> i32 {
|
||||
LL | |
|
||||
@ -59,7 +59,7 @@ LL | const fn two() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:40:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:41:1
|
||||
|
|
||||
LL | / fn string() -> String {
|
||||
LL | |
|
||||
@ -73,7 +73,7 @@ LL | const fn string() -> String {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:46:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:47:1
|
||||
|
|
||||
LL | / unsafe fn four() -> i32 {
|
||||
LL | |
|
||||
@ -87,7 +87,7 @@ LL | const unsafe fn four() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:52:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:53:1
|
||||
|
|
||||
LL | / fn generic<T>(t: T) -> T {
|
||||
LL | |
|
||||
@ -101,7 +101,7 @@ LL | const fn generic<T>(t: T) -> T {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:61:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:62:1
|
||||
|
|
||||
LL | / fn generic_arr<T: Copy>(t: [T; 1]) -> T {
|
||||
LL | |
|
||||
@ -115,7 +115,7 @@ LL | const fn generic_arr<T: Copy>(t: [T; 1]) -> T {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:75:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:76:9
|
||||
|
|
||||
LL | / pub fn b(self, a: &A) -> B {
|
||||
LL | |
|
||||
@ -129,7 +129,7 @@ LL | pub const fn b(self, a: &A) -> B {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:85:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:86:5
|
||||
|
|
||||
LL | / fn const_fn_stabilized_before_msrv(byte: u8) {
|
||||
LL | |
|
||||
@ -143,7 +143,7 @@ LL | const fn const_fn_stabilized_before_msrv(byte: u8) {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:97:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:98:1
|
||||
|
|
||||
LL | / fn msrv_1_46() -> i32 {
|
||||
LL | |
|
||||
@ -157,7 +157,7 @@ LL | const fn msrv_1_46() -> i32 {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:117:1
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:118:1
|
||||
|
|
||||
LL | fn d(this: D) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -168,7 +168,7 @@ LL | const fn d(this: D) {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:125:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:126:9
|
||||
|
|
||||
LL | / fn deref_ptr_can_be_const(self) -> usize {
|
||||
LL | |
|
||||
@ -182,7 +182,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:130:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:131:9
|
||||
|
|
||||
LL | / fn deref_copied_val(self) -> usize {
|
||||
LL | |
|
||||
@ -196,7 +196,7 @@ LL | const fn deref_copied_val(self) -> usize {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:141:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:142:5
|
||||
|
|
||||
LL | / fn union_access_can_be_const() {
|
||||
LL | |
|
||||
@ -211,7 +211,7 @@ LL | const fn union_access_can_be_const() {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:149:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:150:9
|
||||
|
|
||||
LL | extern "C" fn c() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -222,7 +222,7 @@ LL | const extern "C" fn c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:153:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:154:9
|
||||
|
|
||||
LL | extern fn implicit_c() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -233,7 +233,7 @@ LL | const extern fn implicit_c() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:170:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:171:9
|
||||
|
|
||||
LL | / pub fn new(strings: Vec<String>) -> Self {
|
||||
LL | | Self { strings }
|
||||
@ -246,7 +246,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:175:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:176:9
|
||||
|
|
||||
LL | / pub fn empty() -> Self {
|
||||
LL | | Self { strings: Vec::new() }
|
||||
@ -259,7 +259,7 @@ LL | pub const fn empty() -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:186:9
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:187:9
|
||||
|
|
||||
LL | / pub fn new(text: String) -> Self {
|
||||
LL | | let vec = Vec::new();
|
||||
@ -273,7 +273,7 @@ LL | pub const fn new(text: String) -> Self {
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:205:5
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:206:5
|
||||
|
|
||||
LL | fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -283,5 +283,60 @@ help: make the function `const`
|
||||
LL | const fn alias_ty_is_projection(bar: <() as FooTrait>::Foo) {}
|
||||
| +++++
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:210:5
|
||||
|
|
||||
LL | extern "C-unwind" fn c_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "C-unwind" fn c_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:212:5
|
||||
|
|
||||
LL | extern "system" fn system() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "system" fn system() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:214:5
|
||||
|
|
||||
LL | extern "system-unwind" fn system_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "system-unwind" fn system_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:216:5
|
||||
|
|
||||
LL | pub extern "stdcall" fn std_call() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall" fn std_call() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:218:5
|
||||
|
|
||||
LL | pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: aborting due to 26 previous errors
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const extern "C-unwind" fn c_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
const extern "system" fn system() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
const extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
@ -1,14 +0,0 @@
|
||||
#![warn(clippy::missing_const_for_fn)]
|
||||
#![allow(unsupported_calling_conventions)]
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
extern "C-unwind" fn c_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
extern "system" fn system() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
extern "system-unwind" fn system_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall" fn std_call() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
//~^ ERROR: this could be a `const fn`
|
@ -1,59 +0,0 @@
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:5:1
|
||||
|
|
||||
LL | extern "C-unwind" fn c_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::missing-const-for-fn` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::missing_const_for_fn)]`
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "C-unwind" fn c_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:7:1
|
||||
|
|
||||
LL | extern "system" fn system() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "system" fn system() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:9:1
|
||||
|
|
||||
LL | extern "system-unwind" fn system_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const extern "system-unwind" fn system_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:11:1
|
||||
|
|
||||
LL | pub extern "stdcall" fn std_call() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall" fn std_call() {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const_with_const_extern_fn.rs:13:1
|
||||
|
|
||||
LL | pub extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | pub const extern "stdcall-unwind" fn std_call_unwind() {}
|
||||
| +++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const extern "C" fn foo() {
|
||||
panic!() //~ ERROR evaluation of constant value failed
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/unwind-abort.rs:4:5
|
||||
--> $DIR/unwind-abort.rs:2:5
|
||||
|
|
||||
LL | panic!()
|
||||
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
|
||||
| ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:2:5
|
||||
|
|
||||
note: inside `foo`
|
||||
--> $DIR/unwind-abort.rs:4:5
|
||||
--> $DIR/unwind-abort.rs:2:5
|
||||
|
|
||||
LL | panic!()
|
||||
| ^^^^^^^^
|
||||
note: inside `_`
|
||||
--> $DIR/unwind-abort.rs:7:15
|
||||
--> $DIR/unwind-abort.rs:5:15
|
||||
|
|
||||
LL | const _: () = foo();
|
||||
| ^^^^^
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
extern "C" {
|
||||
fn regular_in_block();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0015]: cannot call non-const fn `regular_in_block` in constant functions
|
||||
--> $DIR/const-extern-fn-call-extern-fn.rs:9:9
|
||||
--> $DIR/const-extern-fn-call-extern-fn.rs:7:9
|
||||
|
|
||||
LL | regular_in_block();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
@ -7,7 +7,7 @@ LL | regular_in_block();
|
||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error[E0015]: cannot call non-const fn `regular` in constant functions
|
||||
--> $DIR/const-extern-fn-call-extern-fn.rs:18:9
|
||||
--> $DIR/const-extern-fn-call-extern-fn.rs:16:9
|
||||
|
|
||||
LL | regular();
|
||||
| ^^^^^^^^^
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
|
||||
//~^ ERROR pointers cannot be cast to integers
|
||||
|
||||
const extern "C" fn ptr_cast(val: *const u8) {
|
||||
val as usize;
|
||||
//~^ ERROR pointers cannot be cast to integers
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: pointers cannot be cast to integers during const eval
|
||||
--> $DIR/const-extern-fn-min-const-fn.rs:3:48
|
||||
--> $DIR/const-extern-fn-min-const-fn.rs:2:5
|
||||
|
|
||||
LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; }
|
||||
| ^^^^^^^^^^^^
|
||||
LL | val as usize;
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: at compile-time, pointers do not have an integer value
|
||||
= note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
|
||||
|
@ -1,12 +1,18 @@
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const unsafe extern "C" fn foo() -> usize {
|
||||
5
|
||||
}
|
||||
|
||||
const unsafe extern "C-unwind" fn bar() -> usize {
|
||||
5
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a: [u8; foo()];
|
||||
//~^ call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
foo();
|
||||
//~^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
let b: [u8; bar()];
|
||||
//~^ call to unsafe function `bar` is unsafe and requires unsafe function or block
|
||||
bar();
|
||||
//~^ ERROR call to unsafe function `bar` is unsafe and requires unsafe function or block
|
||||
}
|
||||
|
@ -1,19 +1,35 @@
|
||||
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:10:5
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:12:5
|
||||
|
|
||||
LL | foo();
|
||||
| ^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function `bar` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:16:5
|
||||
|
|
||||
LL | bar();
|
||||
| ^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:8:17
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:10:17
|
||||
|
|
||||
LL | let a: [u8; foo()];
|
||||
| ^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error[E0133]: call to unsafe function `bar` is unsafe and requires unsafe function or block
|
||||
--> $DIR/const-extern-fn-requires-unsafe.rs:14:17
|
||||
|
|
||||
LL | let b: [u8; bar()];
|
||||
| ^^^^^ call to unsafe function
|
||||
|
|
||||
= note: consult the function's documentation for information on how to avoid undefined behavior
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0133`.
|
||||
|
@ -1,5 +1,4 @@
|
||||
//@ run-pass
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const extern "C" fn foo1(val: u8) -> u8 {
|
||||
val + 1
|
||||
@ -47,6 +46,10 @@ fn main() {
|
||||
let _bar2_cast: unsafe extern "C" fn(bool) -> bool = bar2;
|
||||
|
||||
unsize(&[0, 1, 2]);
|
||||
unsafe { closure(); }
|
||||
unsafe { use_float(); }
|
||||
unsafe {
|
||||
closure();
|
||||
}
|
||||
unsafe {
|
||||
use_float();
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
// Check that `const extern fn` and `const unsafe extern fn` are feature-gated
|
||||
// for certain ABIs.
|
||||
|
||||
const extern fn foo1() {}
|
||||
const extern "C" fn foo2() {}
|
||||
const extern "Rust" fn foo3() {}
|
||||
const extern "cdecl" fn foo4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
|
||||
const unsafe extern fn bar1() {}
|
||||
const unsafe extern "C" fn bar2() {}
|
||||
const unsafe extern "Rust" fn bar3() {}
|
||||
const unsafe extern "cdecl" fn bar4() {} //~ ERROR `cdecl` as a `const fn` ABI is unstable
|
||||
|
||||
fn main() {}
|
@ -1,23 +0,0 @@
|
||||
error[E0658]: `cdecl` as a `const fn` ABI is unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:7:14
|
||||
|
|
||||
LL | const extern "cdecl" fn foo4() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` 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[E0658]: `cdecl` as a `const fn` ABI is unstable
|
||||
--> $DIR/feature-gate-const_extern_fn.rs:11:21
|
||||
|
|
||||
LL | const unsafe extern "cdecl" fn bar4() {}
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #64926 <https://github.com/rust-lang/rust/issues/64926> for more information
|
||||
= help: add `#![feature(const_extern_fn)]` 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 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,8 +1,6 @@
|
||||
// Checks that we report ABI mismatches for "const extern fn"
|
||||
//@ compile-flags: -Z unleash-the-miri-inside-of-you
|
||||
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
const extern "C" fn c_fn() {}
|
||||
|
||||
const fn call_rust_fn(my_fn: extern "Rust" fn()) {
|
||||
|
@ -1,16 +1,16 @@
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/abi-mismatch.rs:9:5
|
||||
--> $DIR/abi-mismatch.rs:7:5
|
||||
|
|
||||
LL | my_fn();
|
||||
| ^^^^^^^ calling a function with calling convention C using calling convention Rust
|
||||
|
|
||||
note: inside `call_rust_fn`
|
||||
--> $DIR/abi-mismatch.rs:9:5
|
||||
--> $DIR/abi-mismatch.rs:7:5
|
||||
|
|
||||
LL | my_fn();
|
||||
| ^^^^^^^
|
||||
note: inside `VAL`
|
||||
--> $DIR/abi-mismatch.rs:15:18
|
||||
--> $DIR/abi-mismatch.rs:13:18
|
||||
|
|
||||
LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -18,7 +18,7 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "
|
||||
warning: skipping const checks
|
||||
|
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/abi-mismatch.rs:9:5
|
||||
--> $DIR/abi-mismatch.rs:7:5
|
||||
|
|
||||
LL | my_fn();
|
||||
| ^^^^^^^
|
||||
|
@ -1,7 +1,5 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
// We don't unwind in const-eval anyways.
|
||||
const extern "C" fn foo() {
|
||||
panic!()
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
//@ edition:2018
|
||||
|
||||
#![feature(const_extern_fn)]
|
||||
|
||||
fn main() {
|
||||
async fn ff1() {} // OK.
|
||||
unsafe fn ff2() {} // OK.
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:12:5
|
||||
--> $DIR/fn-header-semantic-fail.rs:10:5
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ff5() {}
|
||||
| ^^^^^-^^^^^------------------------------
|
||||
@ -8,7 +8,7 @@ LL | const async unsafe extern "C" fn ff5() {}
|
||||
| `const` because of this
|
||||
|
||||
error[E0379]: functions in traits cannot be declared const
|
||||
--> $DIR/fn-header-semantic-fail.rs:18:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:16:9
|
||||
|
|
||||
LL | const fn ft3();
|
||||
| ^^^^^-
|
||||
@ -17,7 +17,7 @@ LL | const fn ft3();
|
||||
| help: remove the `const`
|
||||
|
||||
error[E0379]: functions in traits cannot be declared const
|
||||
--> $DIR/fn-header-semantic-fail.rs:20:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:18:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5();
|
||||
| ^^^^^-
|
||||
@ -26,7 +26,7 @@ LL | const async unsafe extern "C" fn ft5();
|
||||
| help: remove the `const`
|
||||
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:20:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:18:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5();
|
||||
| ^^^^^-^^^^^----------------------------
|
||||
@ -35,7 +35,7 @@ LL | const async unsafe extern "C" fn ft5();
|
||||
| `const` because of this
|
||||
|
||||
error[E0379]: functions in trait impls cannot be declared const
|
||||
--> $DIR/fn-header-semantic-fail.rs:29:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:27:9
|
||||
|
|
||||
LL | const fn ft3() {}
|
||||
| ^^^^^-
|
||||
@ -44,7 +44,7 @@ LL | const fn ft3() {}
|
||||
| help: remove the `const`
|
||||
|
||||
error[E0379]: functions in trait impls cannot be declared const
|
||||
--> $DIR/fn-header-semantic-fail.rs:31:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:29:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5() {}
|
||||
| ^^^^^-
|
||||
@ -53,7 +53,7 @@ LL | const async unsafe extern "C" fn ft5() {}
|
||||
| help: remove the `const`
|
||||
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:31:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:29:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn ft5() {}
|
||||
| ^^^^^-^^^^^------------------------------
|
||||
@ -62,7 +62,7 @@ LL | const async unsafe extern "C" fn ft5() {}
|
||||
| `const` because of this
|
||||
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:41:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:39:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn fi5() {}
|
||||
| ^^^^^-^^^^^------------------------------
|
||||
@ -71,7 +71,7 @@ LL | const async unsafe extern "C" fn fi5() {}
|
||||
| `const` because of this
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:46:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:44:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -79,7 +79,7 @@ LL | async fn fe1();
|
||||
| ^^^^^ help: remove this qualifier
|
||||
|
||||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:47:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:45:9
|
||||
|
|
||||
LL | unsafe fn fe2();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
@ -90,7 +90,7 @@ LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:46:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -99,7 +99,7 @@ LL | const fn fe3();
|
||||
| ^^^^^ help: remove this qualifier
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:49:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:47:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -108,7 +108,7 @@ LL | extern "C" fn fe4();
|
||||
| ^^^^^^^^^^ help: remove this qualifier
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:15
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:15
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -117,7 +117,7 @@ LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^ help: remove this qualifier
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -126,7 +126,7 @@ LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^ help: remove this qualifier
|
||||
|
||||
error: functions in `extern` blocks cannot have qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:28
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:28
|
||||
|
|
||||
LL | extern "C" {
|
||||
| ---------- in this `extern` block
|
||||
@ -135,7 +135,7 @@ LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^^^^^^ help: remove this qualifier
|
||||
|
||||
error: items in unadorned `extern` blocks cannot have safety qualifiers
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -146,7 +146,7 @@ LL | unsafe extern "C" {
|
||||
| ++++++
|
||||
|
||||
error: functions cannot be both `const` and `async`
|
||||
--> $DIR/fn-header-semantic-fail.rs:50:9
|
||||
--> $DIR/fn-header-semantic-fail.rs:48:9
|
||||
|
|
||||
LL | const async unsafe extern "C" fn fe5();
|
||||
| ^^^^^-^^^^^----------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user