Auto merge of #35393 - GuillaumeGomez:err_codes2, r=jonathandturner
Err codes r? @jonathandturner
This commit is contained in:
commit
ddf92ffae4
13 changed files with 243 additions and 22 deletions
|
@ -25,8 +25,8 @@ one is too specific or the ordering is incorrect.
|
||||||
|
|
||||||
For example, the following `match` block has too many arms:
|
For example, the following `match` block has too many arms:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0001
|
||||||
match foo {
|
match Some(0) {
|
||||||
Some(bar) => {/* ... */}
|
Some(bar) => {/* ... */}
|
||||||
None => {/* ... */}
|
None => {/* ... */}
|
||||||
_ => {/* ... */} // All possible cases have already been handled
|
_ => {/* ... */} // All possible cases have already been handled
|
||||||
|
@ -108,7 +108,7 @@ one or more possible inputs to a match expression. Guaranteed matches are
|
||||||
required in order to assign values to match expressions, or alternatively,
|
required in order to assign values to match expressions, or alternatively,
|
||||||
determine the flow of execution. Erroneous code example:
|
determine the flow of execution. Erroneous code example:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0004
|
||||||
enum Terminator {
|
enum Terminator {
|
||||||
HastaLaVistaBaby,
|
HastaLaVistaBaby,
|
||||||
TalkToMyHand,
|
TalkToMyHand,
|
||||||
|
@ -153,7 +153,7 @@ E0005: r##"
|
||||||
Patterns used to bind names must be irrefutable, that is, they must guarantee
|
Patterns used to bind names must be irrefutable, that is, they must guarantee
|
||||||
that a name will be extracted in all cases. Erroneous code example:
|
that a name will be extracted in all cases. Erroneous code example:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0005
|
||||||
let x = Some(1);
|
let x = Some(1);
|
||||||
let Some(y) = x;
|
let Some(y) = x;
|
||||||
// error: refutable pattern in local binding: `None` not covered
|
// error: refutable pattern in local binding: `None` not covered
|
||||||
|
@ -187,7 +187,7 @@ like the following is invalid as it requires the entire `Option<String>` to be
|
||||||
moved into a variable called `op_string` while simultaneously requiring the
|
moved into a variable called `op_string` while simultaneously requiring the
|
||||||
inner `String` to be moved into a variable called `s`.
|
inner `String` to be moved into a variable called `s`.
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0007
|
||||||
let x = Some("s".to_string());
|
let x = Some("s".to_string());
|
||||||
|
|
||||||
match x {
|
match x {
|
||||||
|
@ -205,7 +205,7 @@ name is bound by move in a pattern, it should also be moved to wherever it is
|
||||||
referenced in the pattern guard code. Doing so however would prevent the name
|
referenced in the pattern guard code. Doing so however would prevent the name
|
||||||
from being available in the body of the match arm. Consider the following:
|
from being available in the body of the match arm. Consider the following:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0008
|
||||||
match Some("hi".to_string()) {
|
match Some("hi".to_string()) {
|
||||||
Some(s) if s.len() == 0 => {}, // use s.
|
Some(s) if s.len() == 0 => {}, // use s.
|
||||||
_ => {},
|
_ => {},
|
||||||
|
@ -229,7 +229,7 @@ match Some("hi".to_string()) {
|
||||||
Though this example seems innocuous and easy to solve, the problem becomes clear
|
Though this example seems innocuous and easy to solve, the problem becomes clear
|
||||||
when it encounters functions which consume the value:
|
when it encounters functions which consume the value:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0008
|
||||||
struct A{}
|
struct A{}
|
||||||
|
|
||||||
impl A {
|
impl A {
|
||||||
|
@ -283,7 +283,7 @@ This limitation may be removed in a future version of Rust.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0009
|
||||||
struct X { x: (), }
|
struct X { x: (), }
|
||||||
|
|
||||||
let x = Some((X { x: () }, X { x: () }));
|
let x = Some((X { x: () }, X { x: () }));
|
||||||
|
@ -351,25 +351,25 @@ An if-let pattern attempts to match the pattern, and enters the body if the
|
||||||
match was successful. If the match is irrefutable (when it cannot fail to
|
match was successful. If the match is irrefutable (when it cannot fail to
|
||||||
match), use a regular `let`-binding instead. For instance:
|
match), use a regular `let`-binding instead. For instance:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0162
|
||||||
struct Irrefutable(i32);
|
struct Irrefutable(i32);
|
||||||
let irr = Irrefutable(0);
|
let irr = Irrefutable(0);
|
||||||
|
|
||||||
// This fails to compile because the match is irrefutable.
|
// This fails to compile because the match is irrefutable.
|
||||||
if let Irrefutable(x) = irr {
|
if let Irrefutable(x) = irr {
|
||||||
// This body will always be executed.
|
// This body will always be executed.
|
||||||
foo(x);
|
// ...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Try this instead:
|
Try this instead:
|
||||||
|
|
||||||
```ignore
|
```
|
||||||
struct Irrefutable(i32);
|
struct Irrefutable(i32);
|
||||||
let irr = Irrefutable(0);
|
let irr = Irrefutable(0);
|
||||||
|
|
||||||
let Irrefutable(x) = irr;
|
let Irrefutable(x) = irr;
|
||||||
foo(x);
|
println!("{}", x);
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ A while-let pattern attempts to match the pattern, and enters the body if the
|
||||||
match was successful. If the match is irrefutable (when it cannot fail to
|
match was successful. If the match is irrefutable (when it cannot fail to
|
||||||
match), use a regular `let`-binding inside a `loop` instead. For instance:
|
match), use a regular `let`-binding inside a `loop` instead. For instance:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0165
|
||||||
struct Irrefutable(i32);
|
struct Irrefutable(i32);
|
||||||
let irr = Irrefutable(0);
|
let irr = Irrefutable(0);
|
||||||
|
|
||||||
|
@ -455,7 +455,7 @@ that a name will be extracted in all cases. Instead of pattern matching the
|
||||||
loop variable, consider using a `match` or `if let` inside the loop body. For
|
loop variable, consider using a `match` or `if let` inside the loop body. For
|
||||||
instance:
|
instance:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0297
|
||||||
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
||||||
|
|
||||||
// This fails because `None` is not covered.
|
// This fails because `None` is not covered.
|
||||||
|
@ -497,7 +497,7 @@ on which the match depends in such a way, that the match would not be
|
||||||
exhaustive. For instance, the following would not match any arm if mutable
|
exhaustive. For instance, the following would not match any arm if mutable
|
||||||
borrows were allowed:
|
borrows were allowed:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0301
|
||||||
match Some(()) {
|
match Some(()) {
|
||||||
None => { },
|
None => { },
|
||||||
option if option.take().is_none() => {
|
option if option.take().is_none() => {
|
||||||
|
@ -515,10 +515,10 @@ on which the match depends in such a way, that the match would not be
|
||||||
exhaustive. For instance, the following would not match any arm if assignments
|
exhaustive. For instance, the following would not match any arm if assignments
|
||||||
were allowed:
|
were allowed:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0302
|
||||||
match Some(()) {
|
match Some(()) {
|
||||||
None => { },
|
None => { },
|
||||||
option if { option = None; false } { },
|
option if { option = None; false } => { },
|
||||||
Some(_) => { } // When the previous match failed, the option became `None`.
|
Some(_) => { } // When the previous match failed, the option became `None`.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -529,14 +529,18 @@ In certain cases it is possible for sub-bindings to violate memory safety.
|
||||||
Updates to the borrow checker in a future version of Rust may remove this
|
Updates to the borrow checker in a future version of Rust may remove this
|
||||||
restriction, but for now patterns must be rewritten without sub-bindings.
|
restriction, but for now patterns must be rewritten without sub-bindings.
|
||||||
|
|
||||||
```ignore
|
Before:
|
||||||
// Before.
|
|
||||||
|
```compile_fail,E0303
|
||||||
match Some("hi".to_string()) {
|
match Some("hi".to_string()) {
|
||||||
ref op_string_ref @ Some(s) => {},
|
ref op_string_ref @ Some(s) => {},
|
||||||
None => {},
|
None => {},
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
// After.
|
After:
|
||||||
|
|
||||||
|
```
|
||||||
match Some("hi".to_string()) {
|
match Some("hi".to_string()) {
|
||||||
Some(ref s) => {
|
Some(ref s) => {
|
||||||
let op_string_ref = &Some(s);
|
let op_string_ref = &Some(s);
|
||||||
|
@ -556,7 +560,7 @@ This error indicates that the compiler was unable to sensibly evaluate an
|
||||||
constant expression that had to be evaluated. Attempting to divide by 0
|
constant expression that had to be evaluated. Attempting to divide by 0
|
||||||
or causing integer overflow are two ways to induce this error. For example:
|
or causing integer overflow are two ways to induce this error. For example:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0080
|
||||||
enum Enum {
|
enum Enum {
|
||||||
X = (1 << 500),
|
X = (1 << 500),
|
||||||
Y = (1 / 0)
|
Y = (1 / 0)
|
||||||
|
@ -575,7 +579,7 @@ E0306: r##"
|
||||||
In an array literal `[x; N]`, `N` is the number of elements in the array. This
|
In an array literal `[x; N]`, `N` is the number of elements in the array. This
|
||||||
must be an unsigned integer. Erroneous code example:
|
must be an unsigned integer. Erroneous code example:
|
||||||
|
|
||||||
```compile_fail
|
```compile_fail,E0306
|
||||||
let x = [0i32; true]; // error: expected positive integer for repeat count,
|
let x = [0i32; true]; // error: expected positive integer for repeat count,
|
||||||
// found boolean
|
// found boolean
|
||||||
```
|
```
|
||||||
|
|
21
src/test/compile-fail/E0271.rs
Normal file
21
src/test/compile-fail/E0271.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
trait Trait { type AssociatedType; }
|
||||||
|
|
||||||
|
fn foo<T>(t: T) where T: Trait<AssociatedType=u32> {
|
||||||
|
println!("in foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for i8 { type AssociatedType = &'static str; }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo(3_i8); //~ ERROR E0271
|
||||||
|
}
|
18
src/test/compile-fail/E0275.rs
Normal file
18
src/test/compile-fail/E0275.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
|
||||||
|
struct Bar<T>(T);
|
||||||
|
|
||||||
|
impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
20
src/test/compile-fail/E0276.rs
Normal file
20
src/test/compile-fail/E0276.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn foo<T>(x: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Foo for bool {
|
||||||
|
fn foo<T>(x: T) where T: Copy {} //~ ERROR E0276
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
21
src/test/compile-fail/E0277.rs
Normal file
21
src/test/compile-fail/E0277.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn bar(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn some_func<T: Foo>(foo: T) {
|
||||||
|
foo.bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
some_func(5i32); //~ ERROR E0277
|
||||||
|
}
|
16
src/test/compile-fail/E0281.rs
Normal file
16
src/test/compile-fail/E0281.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn foo<F: Fn()>(x: F) { }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo(|y| { }); //~ ERROR E0281
|
||||||
|
//~^ ERROR E0281
|
||||||
|
}
|
13
src/test/compile-fail/E0282.rs
Normal file
13
src/test/compile-fail/E0282.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = "hello".chars().rev().collect(); //~ ERROR E0282
|
||||||
|
}
|
29
src/test/compile-fail/E0283.rs
Normal file
29
src/test/compile-fail/E0283.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
trait Generator {
|
||||||
|
fn create() -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
|
||||||
|
impl Generator for Impl {
|
||||||
|
fn create() -> u32 { 1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnotherImpl;
|
||||||
|
|
||||||
|
impl Generator for AnotherImpl {
|
||||||
|
fn create() -> u32 { 2 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let cont: u32 = Generator::create(); //~ ERROR E0283
|
||||||
|
}
|
13
src/test/compile-fail/E0296.rs
Normal file
13
src/test/compile-fail/E0296.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![recursion_limit] //~ ERROR E0296
|
||||||
|
|
||||||
|
fn main() {}
|
15
src/test/compile-fail/E0297.rs
Normal file
15
src/test/compile-fail/E0297.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let xs : Vec<Option<i32>> = vec!(Some(1), None);
|
||||||
|
|
||||||
|
for Some(x) in xs {} //~ ERROR E0297
|
||||||
|
}
|
17
src/test/compile-fail/E0301.rs
Normal file
17
src/test/compile-fail/E0301.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Some(()) {
|
||||||
|
None => { },
|
||||||
|
option if option.take().is_none() => {}, //~ ERROR E0301
|
||||||
|
Some(_) => { }
|
||||||
|
}
|
||||||
|
}
|
17
src/test/compile-fail/E0302.rs
Normal file
17
src/test/compile-fail/E0302.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Some(()) {
|
||||||
|
None => { },
|
||||||
|
option if { option = None; false } => { }, //~ ERROR E0302
|
||||||
|
Some(_) => { }
|
||||||
|
}
|
||||||
|
}
|
17
src/test/compile-fail/E0303.rs
Normal file
17
src/test/compile-fail/E0303.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Some("hi".to_string()) {
|
||||||
|
ref op_string_ref @ Some(s) => {}, //~ ERROR E0303
|
||||||
|
//~^ ERROR E0009
|
||||||
|
None => {},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue