Auto merge of #31370 - Manishearth:rollup, r=Manishearth
- Successful merges: #27499, #31220, #31329, #31332, #31347, #31351, #31352, #31366 - Failed merges:
This commit is contained in:
commit
a9922419cf
src
doc/book
etc
libcore
librustc_typeck
librustdoc/html
libstd
libsyntax
test/run-pass
@ -276,7 +276,7 @@ it’s called on, and if it isn’t a successful one, [`panic!`][panic]s with a
|
||||
message you passed it. A `panic!` like this will cause our program to crash,
|
||||
displaying the message.
|
||||
|
||||
[expect]: ../std/option/enum.Option.html#method.expect
|
||||
[expect]: ../std/result/enum.Result.html#method.expect
|
||||
[panic]: error-handling.html
|
||||
|
||||
If we leave off calling this method, our program will compile, but
|
||||
|
@ -173,7 +173,39 @@ let (x, _, z) = coordinate();
|
||||
Here, we bind the first and last element of the tuple to `x` and `z`, but
|
||||
ignore the middle element.
|
||||
|
||||
Similarly, you can use `..` in a pattern to disregard multiple values.
|
||||
It’s worth noting that using `_` never binds the value in the first place,
|
||||
which means a value may not move:
|
||||
|
||||
```rust
|
||||
let tuple: (u32, String) = (5, String::from("five"));
|
||||
|
||||
// Here, tuple is moved, because the String moved:
|
||||
let (x, _s) = tuple;
|
||||
|
||||
// The next line would give "error: use of partially moved value: `tuple`"
|
||||
// println!("Tuple is: {:?}", tuple);
|
||||
|
||||
// However,
|
||||
|
||||
let tuple = (5, String::from("five"));
|
||||
|
||||
// Here, tuple is _not_ moved, as the String was never moved, and u32 is Copy:
|
||||
let (x, _) = tuple;
|
||||
|
||||
// That means this works:
|
||||
println!("Tuple is: {:?}", tuple);
|
||||
```
|
||||
|
||||
This also means that any temporary variables will be dropped at the end of the
|
||||
statement:
|
||||
|
||||
```rust
|
||||
// Here, the String created will be dropped immediately, as it’s not bound:
|
||||
|
||||
let _ = String::from(" hello ").trim();
|
||||
```
|
||||
|
||||
You can also use `..` in a pattern to disregard multiple values:
|
||||
|
||||
```rust
|
||||
enum OptionalTuple {
|
||||
|
@ -114,7 +114,7 @@ if len(errcode_not_found) > 0:
|
||||
if errcode in errcode_checked:
|
||||
continue
|
||||
all_errors.append(errcode)
|
||||
print("error: unused error code: " + errcode)
|
||||
print("error: unused error code: {0} ({1}:{2})".format(*errcode_map[errcode][0]))
|
||||
errors = True
|
||||
|
||||
|
||||
|
@ -1050,6 +1050,30 @@ pub trait Iterator {
|
||||
/// // got a false, take_while() isn't used any more
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// Because `take_while()` needs to look at the value in order to see if it
|
||||
/// should be included or not, consuming iterators will see that it is
|
||||
/// removed:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3, 4];
|
||||
/// let mut iter = a.into_iter();
|
||||
///
|
||||
/// let result: Vec<i32> = iter.by_ref()
|
||||
/// .take_while(|n| **n != 3)
|
||||
/// .cloned()
|
||||
/// .collect();
|
||||
///
|
||||
/// assert_eq!(result, &[1, 2]);
|
||||
///
|
||||
/// let result: Vec<i32> = iter.cloned().collect();
|
||||
///
|
||||
/// assert_eq!(result, &[4]);
|
||||
/// ```
|
||||
///
|
||||
/// The `3` is no longer there, because it was consumed in order to see if
|
||||
/// the iteration should stop, but wasn't placed back into the iterator or
|
||||
/// some similar thing.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P> where
|
||||
@ -3258,6 +3282,49 @@ impl<A, B> DoubleEndedIterator for Zip<A, B> where
|
||||
///
|
||||
/// [`map()`]: trait.Iterator.html#method.map
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
///
|
||||
/// # Notes about side effects
|
||||
///
|
||||
/// The [`map()`] iterator implements [`DoubleEndedIterator`], meaning that
|
||||
/// you can also [`map()`] backwards:
|
||||
///
|
||||
/// ```rust
|
||||
/// let v: Vec<i32> = vec![1, 2, 3].into_iter().rev().map(|x| x + 1).collect();
|
||||
///
|
||||
/// assert_eq!(v, [4, 3, 2]);
|
||||
/// ```
|
||||
///
|
||||
/// [`DoubleEndedIterator`]: trait.DoubleEndedIterator.html
|
||||
///
|
||||
/// But if your closure has state, iterating backwards may act in a way you do
|
||||
/// not expect. Let's go through an example. First, in the forward direction:
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut c = 0;
|
||||
///
|
||||
/// for pair in vec!['a', 'b', 'c'].into_iter()
|
||||
/// .map(|letter| { c += 1; (letter, c) }) {
|
||||
/// println!("{:?}", pair);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This will print "('a', 1), ('b', 2), ('c', 3)".
|
||||
///
|
||||
/// Now consider this twist where we add a call to `rev`. This version will
|
||||
/// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed,
|
||||
/// but the values of the counter still go in order. This is because `map()` is
|
||||
/// still being called lazilly on each item, but we are popping items off the
|
||||
/// back of the vector now, instead of shifting them from the front.
|
||||
///
|
||||
/// ```rust
|
||||
/// let mut c = 0;
|
||||
///
|
||||
/// for pair in vec!['a', 'b', 'c'].into_iter()
|
||||
/// .map(|letter| { c += 1; (letter, c) })
|
||||
/// .rev() {
|
||||
/// println!("{:?}", pair);
|
||||
/// }
|
||||
/// ```
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
|
@ -209,9 +209,12 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
|
||||
return;
|
||||
}
|
||||
_ => {
|
||||
span_err!(self.tcx.sess, item.span, E0118,
|
||||
"no base type found for inherent implementation; \
|
||||
implement a trait or new type instead");
|
||||
struct_span_err!(self.tcx.sess, item.span, E0118,
|
||||
"no base type found for inherent implementation")
|
||||
.span_help(item.span,
|
||||
"either implement a trait on it or create a newtype to wrap it \
|
||||
instead")
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1489,22 +1489,46 @@ For information on the design of the orphan rules, see [RFC 1023].
|
||||
"##,
|
||||
|
||||
E0118: r##"
|
||||
Rust can't find a base type for an implementation you are providing, or the type
|
||||
cannot have an implementation. For example, only a named type or a trait can
|
||||
have an implementation:
|
||||
You're trying to write an inherent implementation for something which isn't a
|
||||
struct nor an enum. Erroneous code example:
|
||||
|
||||
```
|
||||
type NineString = [char, ..9] // This isn't a named type (struct, enum or trait)
|
||||
impl NineString {
|
||||
// Some code here
|
||||
impl (u8, u8) { // error: no base type found for inherent implementation
|
||||
fn get_state(&self) -> String {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the other, simpler case, Rust just can't find the type you are providing an
|
||||
impelementation for:
|
||||
To fix this error, please implement a trait on the type or wrap it in a struct.
|
||||
Example:
|
||||
|
||||
```
|
||||
impl SomeTypeThatDoesntExist { }
|
||||
// we create a trait here
|
||||
trait LiveLongAndProsper {
|
||||
fn get_state(&self) -> String;
|
||||
}
|
||||
|
||||
// and now you can implement it on (u8, u8)
|
||||
impl LiveLongAndProsper for (u8, u8) {
|
||||
fn get_state(&self) -> String {
|
||||
"He's dead, Jim!".to_owned()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can create a newtype. A newtype is a wrapping tuple-struct.
|
||||
For example, `NewType` is a newtype over `Foo` in `struct NewType(Foo)`.
|
||||
Example:
|
||||
|
||||
```
|
||||
struct TypeWrapper((u8, u8));
|
||||
|
||||
impl TypeWrapper {
|
||||
fn get_state(&self) -> String {
|
||||
"Fascinating!".to_owned()
|
||||
}
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
|
@ -54,10 +54,12 @@ use externalfiles::ExternalHtml;
|
||||
|
||||
use serialize::json::{self, ToJson};
|
||||
use syntax::{abi, ast};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc::middle::cstore::LOCAL_CRATE;
|
||||
use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::stability;
|
||||
use rustc::session::config::get_unstable_features_setting;
|
||||
use rustc_front::hir;
|
||||
|
||||
use clean::{self, SelfTy};
|
||||
@ -1897,10 +1899,14 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
|
||||
fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
f: &clean::Function) -> fmt::Result {
|
||||
let vis_constness = match get_unstable_features_setting() {
|
||||
UnstableFeatures::Allow => f.constness,
|
||||
_ => hir::Constness::NotConst
|
||||
};
|
||||
try!(write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
|
||||
{name}{generics}{decl}{where_clause}</pre>",
|
||||
vis = VisSpace(it.visibility),
|
||||
constness = ConstnessSpace(f.constness),
|
||||
constness = ConstnessSpace(vis_constness),
|
||||
unsafety = UnsafetySpace(f.unsafety),
|
||||
abi = AbiSpace(f.abi),
|
||||
name = it.name.as_ref().unwrap(),
|
||||
@ -2122,9 +2128,13 @@ fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
|
||||
href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
|
||||
}
|
||||
};
|
||||
let vis_constness = match get_unstable_features_setting() {
|
||||
UnstableFeatures::Allow => constness,
|
||||
_ => hir::Constness::NotConst
|
||||
};
|
||||
write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
|
||||
{generics}{decl}{where_clause}",
|
||||
ConstnessSpace(constness),
|
||||
ConstnessSpace(vis_constness),
|
||||
UnsafetySpace(unsafety),
|
||||
match abi {
|
||||
Abi::Rust => String::new(),
|
||||
|
@ -365,6 +365,9 @@ pub mod builtin {
|
||||
/// stringification of all the tokens passed to the macro. No restrictions
|
||||
/// are placed on the syntax of the macro invocation itself.
|
||||
///
|
||||
/// Note that the expanded results of the input tokens may change in the
|
||||
/// future. You should be careful if you rely on the output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1174,6 +1174,20 @@ impl TokenTree {
|
||||
}
|
||||
(&TokenTree::Token(sp, token::DocComment(name)), _) => {
|
||||
let stripped = strip_doc_comment_decoration(&name.as_str());
|
||||
|
||||
// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
|
||||
// required to wrap the text.
|
||||
let num_of_hashes = stripped.chars().scan(0, |cnt, x| {
|
||||
*cnt = if x == '"' {
|
||||
1
|
||||
} else if *cnt != 0 && x == '#' {
|
||||
*cnt + 1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Some(*cnt)
|
||||
}).max().unwrap_or(0);
|
||||
|
||||
TokenTree::Delimited(sp, Rc::new(Delimited {
|
||||
delim: token::Bracket,
|
||||
open_span: sp,
|
||||
@ -1181,7 +1195,7 @@ impl TokenTree {
|
||||
token::Plain)),
|
||||
TokenTree::Token(sp, token::Eq),
|
||||
TokenTree::Token(sp, token::Literal(
|
||||
token::StrRaw(token::intern(&stripped), 0), None))],
|
||||
token::StrRaw(token::intern(&stripped), num_of_hashes), None))],
|
||||
close_span: sp,
|
||||
}))
|
||||
}
|
||||
|
39
src/test/run-pass/macro-doc-raw-str-hashes.rs
Normal file
39
src/test/run-pass/macro-doc-raw-str-hashes.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// The number of `#`s used to wrap the documentation comment should differ regarding the content.
|
||||
//
|
||||
// Related issue: #27489
|
||||
|
||||
macro_rules! homura {
|
||||
($x:expr, #[$y:meta]) => (assert_eq!($x, stringify!($y)))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
homura! {
|
||||
r#"doc = r" Madoka""#,
|
||||
/// Madoka
|
||||
};
|
||||
|
||||
homura! {
|
||||
r##"doc = r#" One quote mark: ["]"#"##,
|
||||
/// One quote mark: ["]
|
||||
};
|
||||
|
||||
homura! {
|
||||
r##"doc = r#" Two quote marks: [""]"#"##,
|
||||
/// Two quote marks: [""]
|
||||
};
|
||||
|
||||
homura! {
|
||||
r#####"doc = r####" Raw string ending sequences: ["###]"####"#####,
|
||||
/// Raw string ending sequences: ["###]
|
||||
};
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user