Auto merge of #42165 - frewsxcv:rollup, r=frewsxcv
Rollup of 8 pull requests - Successful merges: #42016, #42122, #42144, #42145, #42151, #42152, #42160, #42163 - Failed merges:
This commit is contained in:
commit
852b7cb91e
@ -49,7 +49,6 @@
|
||||
- [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
|
||||
- [linkage](language-features/linkage.md)
|
||||
- [log_syntax](language-features/log-syntax.md)
|
||||
- [loop_break_value](language-features/loop-break-value.md)
|
||||
- [macro_reexport](language-features/macro-reexport.md)
|
||||
- [macro_vis_matcher](language-features/macro-vis-matcher.md)
|
||||
- [main](language-features/main.md)
|
||||
|
@ -6,5 +6,25 @@ The tracking issue for this feature is: [#34981]
|
||||
|
||||
------------------------
|
||||
|
||||
At present, literals are only accepted as the value of a key-value pair in
|
||||
attributes. What's more, only _string_ literals are accepted. This means that
|
||||
literals can only appear in forms of `#[attr(name = "value")]` or
|
||||
`#[attr = "value"]`.
|
||||
|
||||
The `attr_literals` unstable feature allows other types of literals to be used
|
||||
in attributes. Here are some examples of attributes that can now be used with
|
||||
this feature enabled:
|
||||
|
||||
+```rust,ignore
|
||||
+#[attr]
|
||||
+#[attr(true)]
|
||||
+#[attr(ident)]
|
||||
+#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
|
||||
+#[attr(100)]
|
||||
+#[attr(enabled = true)]
|
||||
+#[enabled(true)]
|
||||
+#[attr("hello")]
|
||||
+#[repr(C, align = 4)]
|
||||
+#[repr(C, align(4))]
|
||||
+```
|
||||
|
||||
|
@ -5,3 +5,26 @@ The tracking issue for this feature is: [#31436]
|
||||
[#31436]: https://github.com/rust-lang/rust/issues/31436
|
||||
|
||||
------------------------
|
||||
|
||||
The `catch_expr` feature adds support for a `catch` expression. The `catch`
|
||||
expression creates a new scope one can use the `?` operator in.
|
||||
|
||||
```rust
|
||||
#![feature(catch_expr)]
|
||||
|
||||
use std::num::ParseIntError;
|
||||
|
||||
let result: Result<i32, ParseIntError> = do catch {
|
||||
Ok("1".parse::<i32>()?
|
||||
+ "2".parse::<i32>()?
|
||||
+ "3".parse::<i32>()?)
|
||||
};
|
||||
assert_eq!(result, Ok(6));
|
||||
|
||||
let result: Result<i32, ParseIntError> = do catch {
|
||||
Ok("1".parse::<i32>()?
|
||||
+ "foo".parse::<i32>()?
|
||||
+ "3".parse::<i32>()?)
|
||||
};
|
||||
assert!(result.is_err());
|
||||
```
|
||||
|
@ -1,83 +0,0 @@
|
||||
# `loop_break_value`
|
||||
|
||||
The tracking issue for this feature is: [#37339]
|
||||
|
||||
[#37339]: https://github.com/rust-lang/rust/issues/37339
|
||||
|
||||
Documentation to be appended to section G of the book.
|
||||
|
||||
------------------------
|
||||
|
||||
### Loops as expressions
|
||||
|
||||
Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
|
||||
never exits.
|
||||
A `loop` can instead evaluate to a useful value via *break with value*:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
// Find the first square number over 1000:
|
||||
let mut n = 1;
|
||||
let square = loop {
|
||||
if n * n > 1000 {
|
||||
break n * n;
|
||||
}
|
||||
n += 1;
|
||||
};
|
||||
```
|
||||
|
||||
The evaluation type may be specified externally:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
// Declare that value returned is unsigned 64-bit:
|
||||
let n: u64 = loop {
|
||||
break 1;
|
||||
};
|
||||
```
|
||||
|
||||
It is an error if types do not agree, either between a "break" value and an external requirement,
|
||||
or between multiple "break" values:
|
||||
|
||||
```no_compile
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
loop {
|
||||
if true {
|
||||
break 1u32;
|
||||
} else {
|
||||
break 0u8; // error: types do not agree
|
||||
}
|
||||
};
|
||||
|
||||
let n: i32 = loop {
|
||||
break 0u32; // error: type does not agree with external requirement
|
||||
};
|
||||
```
|
||||
|
||||
#### Break: label, value
|
||||
|
||||
Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
|
||||
|
||||
1. `break;`
|
||||
2. `break 'label;`
|
||||
3. `break EXPR;`
|
||||
4. `break 'label EXPR;`
|
||||
|
||||
When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
|
||||
|
||||
Using a label allows returning a value from an inner loop:
|
||||
|
||||
```rust
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
let result = 'outer: loop {
|
||||
for n in 1..10 {
|
||||
if n > 4 {
|
||||
break 'outer n;
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
@ -6,5 +6,42 @@ The tracking issue for this feature is: [#29628]
|
||||
|
||||
------------------------
|
||||
|
||||
The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
|
||||
attribute, which allows trait definitions to add specialized notes to error
|
||||
messages when an implementation was expected but not found.
|
||||
|
||||
For example:
|
||||
|
||||
```rust,compile_fail
|
||||
#![feature(on_unimplemented)]
|
||||
|
||||
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an \
|
||||
iterator over elements of type `{A}`"]
|
||||
trait MyIterator<A> {
|
||||
fn next(&mut self) -> A;
|
||||
}
|
||||
|
||||
fn iterate_chars<I: MyIterator<char>>(i: I) {
|
||||
// ...
|
||||
}
|
||||
|
||||
fn main() {
|
||||
iterate_chars(&[1, 2, 3][..]);
|
||||
}
|
||||
```
|
||||
|
||||
When the user compiles this, they will see the following;
|
||||
|
||||
```txt
|
||||
error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
|
||||
--> <anon>:14:5
|
||||
|
|
||||
14 | iterate_chars(&[1, 2, 3][..]);
|
||||
| ^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
|
||||
|
|
||||
= note: a collection of type `&[{integer}]` cannot be built from an iterator over elements of type `char`
|
||||
= note: required by `iterate_chars`
|
||||
|
||||
error: aborting due to previous error
|
||||
```
|
||||
|
||||
|
@ -1410,6 +1410,9 @@ impl<T> [T] {
|
||||
|
||||
/// Converts `self` into a vector without clones or allocation.
|
||||
///
|
||||
/// The resulting vector can be converted back into a box via
|
||||
/// `Vec<T>`'s `into_boxed_slice` method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -174,7 +174,7 @@ impl<T> Option<T> {
|
||||
// Querying the contained values
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Returns `true` if the option is a `Some` value.
|
||||
/// Returns `true` if the option is a [`Some`] value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -185,6 +185,8 @@ impl<T> Option<T> {
|
||||
/// let x: Option<u32> = None;
|
||||
/// assert_eq!(x.is_some(), false);
|
||||
/// ```
|
||||
///
|
||||
/// [`Some`]: #variant.Some
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_some(&self) -> bool {
|
||||
@ -194,7 +196,7 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the option is a `None` value.
|
||||
/// Returns `true` if the option is a [`None`] value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -205,6 +207,8 @@ impl<T> Option<T> {
|
||||
/// let x: Option<u32> = None;
|
||||
/// assert_eq!(x.is_none(), true);
|
||||
/// ```
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn is_none(&self) -> bool {
|
||||
@ -269,13 +273,14 @@ impl<T> Option<T> {
|
||||
// Getting to contained values
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Unwraps an option, yielding the content of a `Some`.
|
||||
/// Unwraps an option, yielding the content of a [`Some`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the value is a [`None`] with a custom panic message provided by
|
||||
/// `msg`.
|
||||
///
|
||||
/// [`Some`]: #variant.Some
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
@ -298,16 +303,17 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Moves the value `v` out of the `Option<T>` if it is `Some(v)`.
|
||||
/// Moves the value `v` out of the `Option<T>` if it is [`Some(v)`].
|
||||
///
|
||||
/// In general, because this function may panic, its use is discouraged.
|
||||
/// Instead, prefer to use pattern matching and handle the `None`
|
||||
/// Instead, prefer to use pattern matching and handle the [`None`]
|
||||
/// case explicitly.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the self value equals [`None`].
|
||||
///
|
||||
/// [`Some(v)`]: #variant.Some
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
@ -395,7 +401,9 @@ impl<T> Option<T> {
|
||||
}
|
||||
|
||||
/// Applies a function to the contained value (if any),
|
||||
/// or returns a `default` (if not).
|
||||
/// or returns a [`default`][] (if not).
|
||||
///
|
||||
/// [`default`]: ../default/trait.Default.html#tymethod.default
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -416,7 +424,9 @@ impl<T> Option<T> {
|
||||
}
|
||||
|
||||
/// Applies a function to the contained value (if any),
|
||||
/// or computes a `default` (if not).
|
||||
/// or computes a [`default`][] (if not).
|
||||
///
|
||||
/// [`default`]: ../default/trait.Default.html#tymethod.default
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -438,12 +448,14 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
|
||||
/// [`Ok(v)`] and `None` to [`Err(err)`][Err].
|
||||
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
|
||||
/// [`Ok(v)`] and [`None`] to [`Err(err)`].
|
||||
///
|
||||
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
|
||||
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
|
||||
/// [Err]: ../../std/result/enum.Result.html#variant.Err
|
||||
/// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
|
||||
/// [`None`]: #variant.None
|
||||
/// [`Some(v)`]: #variant.Some
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -463,12 +475,14 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
|
||||
/// [`Ok(v)`] and `None` to [`Err(err())`][Err].
|
||||
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
|
||||
/// [`Ok(v)`] and [`None`] to [`Err(err())`].
|
||||
///
|
||||
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
|
||||
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
|
||||
/// [Err]: ../../std/result/enum.Result.html#variant.Err
|
||||
/// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
|
||||
/// [`None`]: #variant.None
|
||||
/// [`Some(v)`]: #variant.Some
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -534,7 +548,9 @@ impl<T> Option<T> {
|
||||
// Boolean operations on the values, eager and lazy
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Returns `None` if the option is `None`, otherwise returns `optb`.
|
||||
/// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -564,11 +580,13 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `None` if the option is `None`, otherwise calls `f` with the
|
||||
/// Returns [`None`] if the option is [`None`], otherwise calls `f` with the
|
||||
/// wrapped value and returns the result.
|
||||
///
|
||||
/// Some languages call this operation flatmap.
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -645,9 +663,11 @@ impl<T> Option<T> {
|
||||
// Entry-like operations to insert if None and return a reference
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Inserts `v` into the option if it is `None`, then
|
||||
/// Inserts `v` into the option if it is [`None`], then
|
||||
/// returns a mutable reference to the contained value.
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -678,9 +698,11 @@ impl<T> Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts a value computed from `f` into the option if it is `None`, then
|
||||
/// Inserts a value computed from `f` into the option if it is [`None`], then
|
||||
/// returns a mutable reference to the contained value.
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -715,7 +737,9 @@ impl<T> Option<T> {
|
||||
// Misc
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Takes the value out of the option, leaving a `None` in its place.
|
||||
/// Takes the value out of the option, leaving a [`None`] in its place.
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -757,16 +781,16 @@ impl<'a, T: Clone> Option<&'a T> {
|
||||
impl<T: Default> Option<T> {
|
||||
/// Returns the contained value or a default
|
||||
///
|
||||
/// Consumes the `self` argument then, if `Some`, returns the contained
|
||||
/// value, otherwise if `None`, returns the default value for that
|
||||
/// Consumes the `self` argument then, if [`Some`], returns the contained
|
||||
/// value, otherwise if [`None`], returns the default value for that
|
||||
/// type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Convert a string to an integer, turning poorly-formed strings
|
||||
/// into 0 (the default value for integers). `parse` converts
|
||||
/// a string to any other type that implements `FromStr`, returning
|
||||
/// `None` on error.
|
||||
/// into 0 (the default value for integers). [`parse`] converts
|
||||
/// a string to any other type that implements [`FromStr`], returning
|
||||
/// [`None`] on error.
|
||||
///
|
||||
/// ```
|
||||
/// let good_year_from_input = "1909";
|
||||
@ -777,6 +801,11 @@ impl<T: Default> Option<T> {
|
||||
/// assert_eq!(1909, good_year);
|
||||
/// assert_eq!(0, bad_year);
|
||||
/// ```
|
||||
///
|
||||
/// [`Some`]: #variant.Some
|
||||
/// [`None`]: #variant.None
|
||||
/// [`parse`]: ../../std/primitive.str.html#method.parse
|
||||
/// [`FromStr`]: ../../std/str/trait.FromStr.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn unwrap_or_default(self) -> T {
|
||||
@ -801,7 +830,9 @@ fn expect_failed(msg: &str) -> ! {
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Default for Option<T> {
|
||||
/// Returns None.
|
||||
/// Returns [`None`].
|
||||
///
|
||||
/// [`None`]: #variant.None
|
||||
#[inline]
|
||||
fn default() -> Option<T> { None }
|
||||
}
|
||||
@ -1020,8 +1051,8 @@ unsafe impl<A> TrustedLen for IntoIter<A> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||
/// Takes each element in the `Iterator`: if it is `None`, no further
|
||||
/// elements are taken, and the `None` is returned. Should no `None` occur, a
|
||||
/// Takes each element in the [`Iterator`]: if it is [`None`], no further
|
||||
/// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a
|
||||
/// container with the values of each `Option` is returned.
|
||||
///
|
||||
/// Here is an example which increments every integer in a vector,
|
||||
@ -1037,6 +1068,9 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||
/// ).collect();
|
||||
/// assert!(res == Some(vec![2, 3]));
|
||||
/// ```
|
||||
///
|
||||
/// [`Iterator`]: ../iter/trait.Iterator.html
|
||||
/// [`None`]: enum.Option.html#variant.None
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
|
||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||
|
@ -30,7 +30,6 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(libc)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(quote)]
|
||||
@ -45,6 +44,7 @@
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
#![recursion_limit="128"]
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(libc)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
@ -32,6 +31,7 @@
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
|
@ -76,7 +76,6 @@ This API is completely unstable and subject to change.
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
@ -84,6 +83,7 @@ This API is completely unstable and subject to change.
|
||||
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
|
||||
#![cfg_attr(stage0, feature(rustc_private))]
|
||||
#![cfg_attr(stage0, feature(staged_api))]
|
||||
#![cfg_attr(stage0, feature(loop_break_value))]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
@ -41,26 +41,11 @@ use super::Clean;
|
||||
///
|
||||
/// The returned value is `None` if the definition could not be inlined,
|
||||
/// and `Some` of a vector of items if it was successfully expanded.
|
||||
pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
|
||||
pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
|
||||
-> Option<Vec<clean::Item>> {
|
||||
if def == Def::Err { return None }
|
||||
let did = def.def_id();
|
||||
if did.is_local() { return None }
|
||||
try_inline_def(cx, def).map(|vec| {
|
||||
vec.into_iter().map(|mut item| {
|
||||
match into {
|
||||
Some(into) if item.name.is_some() => {
|
||||
item.name = Some(into.clean(cx));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
item
|
||||
}).collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
|
||||
let tcx = cx.tcx;
|
||||
let mut ret = Vec::new();
|
||||
let inner = match def {
|
||||
Def::Trait(did) => {
|
||||
@ -112,16 +97,15 @@ fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
let did = def.def_id();
|
||||
cx.renderinfo.borrow_mut().inlined.insert(did);
|
||||
ret.push(clean::Item {
|
||||
source: tcx.def_span(did).clean(cx),
|
||||
name: Some(tcx.item_name(did).to_string()),
|
||||
source: cx.tcx.def_span(did).clean(cx),
|
||||
name: Some(name.clean(cx)),
|
||||
attrs: load_attrs(cx, did),
|
||||
inner: inner,
|
||||
visibility: Some(clean::Public),
|
||||
stability: tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
||||
stability: cx.tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
|
||||
def_id: did,
|
||||
});
|
||||
Some(ret)
|
||||
@ -463,7 +447,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
|
||||
let def_id = item.def.def_id();
|
||||
if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
|
||||
if !visited.insert(def_id) { continue }
|
||||
if let Some(i) = try_inline_def(cx, item.def) {
|
||||
if let Some(i) = try_inline(cx, item.def, item.name) {
|
||||
items.extend(i)
|
||||
}
|
||||
}
|
||||
|
@ -2618,7 +2618,7 @@ impl Clean<Vec<Item>> for doctree::Import {
|
||||
} else {
|
||||
let name = self.name;
|
||||
if !denied {
|
||||
if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
|
||||
if let Some(items) = inline::try_inline(cx, path.def, name) {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
@ -23,18 +23,20 @@ use ptr;
|
||||
use slice;
|
||||
use str::{self, Utf8Error};
|
||||
|
||||
/// A type representing an owned C-compatible string
|
||||
/// A type representing an owned C-compatible string.
|
||||
///
|
||||
/// This type serves the primary purpose of being able to safely generate a
|
||||
/// C-compatible string from a Rust byte slice or vector. An instance of this
|
||||
/// type is a static guarantee that the underlying bytes contain no interior 0
|
||||
/// bytes and the final byte is 0.
|
||||
///
|
||||
/// A `CString` is created from either a byte slice or a byte vector. A `u8`
|
||||
/// slice can be obtained with the `as_bytes` method. Slices produced from a
|
||||
/// A `CString` is created from either a byte slice or a byte vector. A [`u8`]
|
||||
/// slice can be obtained with the `as_bytes` method. Slices produced from a
|
||||
/// `CString` do *not* contain the trailing nul terminator unless otherwise
|
||||
/// specified.
|
||||
///
|
||||
/// [`u8`]: ../primitive.u8.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
@ -81,12 +83,14 @@ pub struct CString {
|
||||
///
|
||||
/// Note that this structure is **not** `repr(C)` and is not recommended to be
|
||||
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
|
||||
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
|
||||
/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
|
||||
/// interface to other consumers.
|
||||
///
|
||||
/// [`from_ptr`]: #method.from_ptr
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Inspecting a foreign C string
|
||||
/// Inspecting a foreign C string:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::CStr;
|
||||
@ -100,7 +104,7 @@ pub struct CString {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Passing a Rust-originating C string
|
||||
/// Passing a Rust-originating C string:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::{CString, CStr};
|
||||
@ -116,7 +120,9 @@ pub struct CString {
|
||||
/// work(&s);
|
||||
/// ```
|
||||
///
|
||||
/// Converting a foreign C string into a Rust `String`
|
||||
/// Converting a foreign C string into a Rust [`String`]:
|
||||
///
|
||||
/// [`String`]: ../string/struct.String.html
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::ffi::CStr;
|
||||
@ -142,14 +148,18 @@ pub struct CStr {
|
||||
inner: [c_char]
|
||||
}
|
||||
|
||||
/// An error returned from `CString::new` to indicate that a nul byte was found
|
||||
/// An error returned from [`CString::new`] to indicate that a nul byte was found
|
||||
/// in the vector provided.
|
||||
///
|
||||
/// [`CString::new`]: struct.CString.html#method.new
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct NulError(usize, Vec<u8>);
|
||||
|
||||
/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
|
||||
/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul
|
||||
/// byte was found too early in the slice provided or one wasn't found at all.
|
||||
///
|
||||
/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
|
||||
pub struct FromBytesWithNulError {
|
||||
@ -175,8 +185,10 @@ impl FromBytesWithNulError {
|
||||
}
|
||||
}
|
||||
|
||||
/// An error returned from `CString::into_string` to indicate that a UTF-8 error
|
||||
/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error
|
||||
/// was encountered during the conversion.
|
||||
///
|
||||
/// [`CString::into_string`]: struct.CString.html#method.into_string
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "cstring_into", since = "1.7.0")]
|
||||
pub struct IntoStringError {
|
||||
@ -224,10 +236,12 @@ impl CString {
|
||||
/// Creates a C-compatible string from a byte vector without checking for
|
||||
/// interior 0 bytes.
|
||||
///
|
||||
/// This method is equivalent to `new` except that no runtime assertion
|
||||
/// This method is equivalent to [`new`] except that no runtime assertion
|
||||
/// is made that `v` contains no 0 bytes, and it requires an actual
|
||||
/// byte vector, not anything that can be converted to one with Into.
|
||||
///
|
||||
/// [`new`]: #method.new
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -252,9 +266,11 @@ impl CString {
|
||||
/// # Safety
|
||||
///
|
||||
/// This should only ever be called with a pointer that was earlier
|
||||
/// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
|
||||
/// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take
|
||||
/// ownership of a string that was allocated by foreign code) is likely to lead
|
||||
/// to undefined behavior or allocator corruption.
|
||||
///
|
||||
/// [`into_raw`]: #method.into_raw
|
||||
#[stable(feature = "cstr_memory", since = "1.4.0")]
|
||||
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
|
||||
let len = libc::strlen(ptr) + 1; // Including the NUL byte
|
||||
@ -265,19 +281,23 @@ impl CString {
|
||||
/// Transfers ownership of the string to a C caller.
|
||||
///
|
||||
/// The pointer must be returned to Rust and reconstituted using
|
||||
/// `from_raw` to be properly deallocated. Specifically, one
|
||||
/// [`from_raw`] to be properly deallocated. Specifically, one
|
||||
/// should *not* use the standard C `free` function to deallocate
|
||||
/// this string.
|
||||
///
|
||||
/// Failure to call `from_raw` will lead to a memory leak.
|
||||
/// Failure to call [`from_raw`] will lead to a memory leak.
|
||||
///
|
||||
/// [`from_raw`]: #method.from_raw
|
||||
#[stable(feature = "cstr_memory", since = "1.4.0")]
|
||||
pub fn into_raw(self) -> *mut c_char {
|
||||
Box::into_raw(self.into_inner()) as *mut c_char
|
||||
}
|
||||
|
||||
/// Converts the `CString` into a `String` if it contains valid Unicode data.
|
||||
/// Converts the `CString` into a [`String`] if it contains valid Unicode data.
|
||||
///
|
||||
/// On failure, ownership of the original `CString` is returned.
|
||||
///
|
||||
/// [`String`]: ../string/struct.String.html
|
||||
#[stable(feature = "cstring_into", since = "1.7.0")]
|
||||
pub fn into_string(self) -> Result<String, IntoStringError> {
|
||||
String::from_utf8(self.into_bytes())
|
||||
@ -299,8 +319,10 @@ impl CString {
|
||||
vec
|
||||
}
|
||||
|
||||
/// Equivalent to the `into_bytes` function except that the returned vector
|
||||
/// Equivalent to the [`into_bytes`] function except that the returned vector
|
||||
/// includes the trailing nul byte.
|
||||
///
|
||||
/// [`into_bytes`]: #method.into_bytes
|
||||
#[stable(feature = "cstring_into", since = "1.7.0")]
|
||||
pub fn into_bytes_with_nul(self) -> Vec<u8> {
|
||||
self.into_inner().into_vec()
|
||||
@ -315,26 +337,34 @@ impl CString {
|
||||
&self.inner[..self.inner.len() - 1]
|
||||
}
|
||||
|
||||
/// Equivalent to the `as_bytes` function except that the returned slice
|
||||
/// Equivalent to the [`as_bytes`] function except that the returned slice
|
||||
/// includes the trailing nul byte.
|
||||
///
|
||||
/// [`as_bytes`]: #method.as_bytes
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn as_bytes_with_nul(&self) -> &[u8] {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Extracts a `CStr` slice containing the entire string.
|
||||
/// Extracts a [`CStr`] slice containing the entire string.
|
||||
///
|
||||
/// [`CStr`]: struct.CStr.html
|
||||
#[unstable(feature = "as_c_str", issue = "40380")]
|
||||
pub fn as_c_str(&self) -> &CStr {
|
||||
&*self
|
||||
}
|
||||
|
||||
/// Converts this `CString` into a boxed `CStr`.
|
||||
/// Converts this `CString` into a boxed [`CStr`].
|
||||
///
|
||||
/// [`CStr`]: struct.CStr.html
|
||||
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
|
||||
pub fn into_boxed_c_str(self) -> Box<CStr> {
|
||||
unsafe { mem::transmute(self.into_inner()) }
|
||||
}
|
||||
|
||||
// Bypass "move out of struct which implements `Drop` trait" restriction.
|
||||
// Bypass "move out of struct which implements [`Drop`] trait" restriction.
|
||||
///
|
||||
/// [`Drop`]: ../ops/trait.Drop.html
|
||||
fn into_inner(self) -> Box<[u8]> {
|
||||
unsafe {
|
||||
let result = ptr::read(&self.inner);
|
||||
@ -443,7 +473,9 @@ impl Default for Box<CStr> {
|
||||
|
||||
impl NulError {
|
||||
/// Returns the position of the nul byte in the slice that was provided to
|
||||
/// `CString::new`.
|
||||
/// [`CString::new`].
|
||||
///
|
||||
/// [`CString::new`]: struct.CString.html#method.new
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -518,8 +550,10 @@ impl fmt::Display for FromBytesWithNulError {
|
||||
}
|
||||
|
||||
impl IntoStringError {
|
||||
/// Consumes this error, returning original `CString` which generated the
|
||||
/// Consumes this error, returning original [`CString`] which generated the
|
||||
/// error.
|
||||
///
|
||||
/// [`CString`]: struct.CString.html
|
||||
#[stable(feature = "cstring_into", since = "1.7.0")]
|
||||
pub fn into_cstring(self) -> CString {
|
||||
self.inner
|
||||
@ -557,9 +591,9 @@ impl CStr {
|
||||
/// allows inspection and interoperation of non-owned C strings. This method
|
||||
/// is unsafe for a number of reasons:
|
||||
///
|
||||
/// * There is no guarantee to the validity of `ptr`
|
||||
/// * There is no guarantee to the validity of `ptr`.
|
||||
/// * The returned lifetime is not guaranteed to be the actual lifetime of
|
||||
/// `ptr`
|
||||
/// `ptr`.
|
||||
/// * There is no guarantee that the memory pointed to by `ptr` contains a
|
||||
/// valid nul terminator byte at the end of the string.
|
||||
///
|
||||
@ -703,26 +737,30 @@ impl CStr {
|
||||
|
||||
/// Converts this C string to a byte slice containing the trailing 0 byte.
|
||||
///
|
||||
/// This function is the equivalent of `to_bytes` except that it will retain
|
||||
/// This function is the equivalent of [`to_bytes`] except that it will retain
|
||||
/// the trailing nul instead of chopping it off.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented as a 0-cost cast, but
|
||||
/// > it is planned to alter its definition in the future to perform the
|
||||
/// > length calculation whenever this method is called.
|
||||
///
|
||||
/// [`to_bytes`]: #method.to_bytes
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn to_bytes_with_nul(&self) -> &[u8] {
|
||||
unsafe { mem::transmute(&self.inner) }
|
||||
}
|
||||
|
||||
/// Yields a `&str` slice if the `CStr` contains valid UTF-8.
|
||||
/// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
|
||||
///
|
||||
/// This function will calculate the length of this string and check for
|
||||
/// UTF-8 validity, and then return the `&str` if it's valid.
|
||||
/// UTF-8 validity, and then return the [`&str`] if it's valid.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented to check for validity
|
||||
/// > after a 0-cost cast, but it is planned to alter its definition in the
|
||||
/// > future to perform the length calculation in addition to the UTF-8
|
||||
/// > check whenever this method is called.
|
||||
///
|
||||
/// [`&str`]: ../primitive.str.html
|
||||
#[stable(feature = "cstr_to_str", since = "1.4.0")]
|
||||
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
|
||||
// NB: When CStr is changed to perform the length check in .to_bytes()
|
||||
@ -732,23 +770,29 @@ impl CStr {
|
||||
str::from_utf8(self.to_bytes())
|
||||
}
|
||||
|
||||
/// Converts a `CStr` into a `Cow<str>`.
|
||||
/// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
|
||||
///
|
||||
/// This function will calculate the length of this string (which normally
|
||||
/// requires a linear amount of work to be done) and then return the
|
||||
/// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
|
||||
/// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences
|
||||
/// with `U+FFFD REPLACEMENT CHARACTER`.
|
||||
///
|
||||
/// > **Note**: This method is currently implemented to check for validity
|
||||
/// > after a 0-cost cast, but it is planned to alter its definition in the
|
||||
/// > future to perform the length calculation in addition to the UTF-8
|
||||
/// > check whenever this method is called.
|
||||
///
|
||||
/// [`Cow`]: ../borrow/enum.Cow.html
|
||||
/// [`str`]: ../primitive.str.html
|
||||
#[stable(feature = "cstr_to_str", since = "1.4.0")]
|
||||
pub fn to_string_lossy(&self) -> Cow<str> {
|
||||
String::from_utf8_lossy(self.to_bytes())
|
||||
}
|
||||
|
||||
/// Converts a `Box<CStr>` into a `CString` without copying or allocating.
|
||||
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
|
||||
///
|
||||
/// [`Box`]: ../boxed/struct.Box.html
|
||||
/// [`CString`]: struct.CString.html
|
||||
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
|
||||
pub fn into_c_string(self: Box<CStr>) -> CString {
|
||||
unsafe { mem::transmute(self) }
|
||||
|
@ -297,9 +297,6 @@ declare_features! (
|
||||
|
||||
(active, use_extern_macros, "1.15.0", Some(35896)),
|
||||
|
||||
// Allows `break {expr}` with a value inside `loop`s.
|
||||
(active, loop_break_value, "1.14.0", Some(37339)),
|
||||
|
||||
// Allows #[target_feature(...)]
|
||||
(active, target_feature, "1.15.0", None),
|
||||
|
||||
@ -423,6 +420,8 @@ declare_features! (
|
||||
(accepted, pub_restricted, "1.18.0", Some(32409)),
|
||||
// The #![windows_subsystem] attribute
|
||||
(accepted, windows_subsystem, "1.18.0", Some(37499)),
|
||||
// Allows `break {expr}` with a value inside `loop`s.
|
||||
(accepted, loop_break_value, "1.19.0", Some(37339)),
|
||||
);
|
||||
// If you change this, please modify src/doc/unstable-book as well. You must
|
||||
// move that documentation into the relevant place in the other docs, and
|
||||
@ -1301,10 +1300,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Break(_, Some(_)) => {
|
||||
gate_feature_post!(&self, loop_break_value, e.span,
|
||||
"`break` with a value is experimental");
|
||||
}
|
||||
ast::ExprKind::Lit(ref lit) => {
|
||||
if let ast::LitKind::Int(_, ref ty) = lit.node {
|
||||
match *ty {
|
||||
|
43
src/test/compile-fail/isssue-38821.rs
Normal file
43
src/test/compile-fail/isssue-38821.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
pub struct Nullable<T: NotNull>(T);
|
||||
|
||||
pub trait NotNull {}
|
||||
|
||||
pub trait IntoNullable {
|
||||
type Nullable;
|
||||
}
|
||||
|
||||
impl<T: NotNull> IntoNullable for T {
|
||||
type Nullable = Nullable<T>;
|
||||
}
|
||||
|
||||
impl<T: NotNull> IntoNullable for Nullable<T> {
|
||||
type Nullable = Nullable<T>;
|
||||
}
|
||||
|
||||
pub trait Expression {
|
||||
type SqlType;
|
||||
}
|
||||
|
||||
pub trait Column: Expression {}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
//~^ ERROR the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
|
||||
pub enum ColumnInsertValue<Col, Expr> where
|
||||
Col: Column,
|
||||
Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
|
||||
{
|
||||
Expression(Col, Expr),
|
||||
Default(Col),
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
|
||||
fn main() {
|
||||
|
@ -15,7 +15,6 @@
|
||||
// like to revisit these and potentially change them. --nmatsakis
|
||||
|
||||
#![feature(never_type)]
|
||||
#![feature(loop_break_value)]
|
||||
|
||||
trait BadDefault {
|
||||
fn default() -> Self;
|
||||
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(never_type)]
|
||||
|
||||
#[allow(unused)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -8,8 +8,12 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
loop {
|
||||
break 123; //~ ERROR `break` with a value is experimental
|
||||
#![crate_name = "foo"]
|
||||
|
||||
pub mod iter {
|
||||
mod range {
|
||||
pub struct StepBy;
|
||||
}
|
||||
pub use self::range::StepBy as DeprecatedStepBy;
|
||||
pub struct StepBy;
|
||||
}
|
34
src/test/rustdoc/inline_cross/renamed-via-module.rs
Normal file
34
src/test/rustdoc/inline_cross/renamed-via-module.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// aux-build:renamed-via-module.rs
|
||||
// build-aux-docs
|
||||
// ignore-cross-compile
|
||||
|
||||
#![crate_name = "bar"]
|
||||
|
||||
extern crate foo;
|
||||
|
||||
// @has foo/iter/index.html
|
||||
// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
|
||||
// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
|
||||
// @has foo/iter/struct.DeprecatedStepBy.html
|
||||
// @has - '//h1' "Struct foo::iter::DeprecatedStepBy"
|
||||
// @has foo/iter/struct.StepBy.html
|
||||
// @has - '//h1' "Struct foo::iter::StepBy"
|
||||
|
||||
// @has bar/iter/index.html
|
||||
// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
|
||||
// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
|
||||
// @has bar/iter/struct.DeprecatedStepBy.html
|
||||
// @has - '//h1' "Struct bar::iter::DeprecatedStepBy"
|
||||
// @has bar/iter/struct.StepBy.html
|
||||
// @has - '//h1' "Struct bar::iter::StepBy"
|
||||
pub use foo::iter;
|
@ -8,7 +8,6 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(loop_break_value)]
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use std::ptr;
|
||||
|
@ -1,7 +1,7 @@
|
||||
error[E0571]: `break` with value from a `for` loop
|
||||
--> $DIR/loop-break-value-no-repeat.rs:23:9
|
||||
--> $DIR/loop-break-value-no-repeat.rs:22:9
|
||||
|
|
||||
23 | break 22
|
||||
22 | break 22
|
||||
| ^^^^^^^^ can only break with a value inside `loop`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2415,11 +2415,11 @@ actual:\n\
|
||||
println!("expected {}:\n{}\n", kind, expected);
|
||||
println!("diff of {}:\n", kind);
|
||||
|
||||
for diff in diff::lines(actual, expected) {
|
||||
for diff in diff::lines(expected, actual) {
|
||||
match diff {
|
||||
diff::Result::Left(l) => println!("+{}", l),
|
||||
diff::Result::Left(l) => println!("-{}", l),
|
||||
diff::Result::Both(l, _) => println!(" {}", l),
|
||||
diff::Result::Right(r) => println!("-{}", r),
|
||||
diff::Result::Right(r) => println!("+{}", r),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user