Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/doc/book/guessing-game.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 33 additions & 1 deletion src/doc/book/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/etc/errorck.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def check_unused_error_codes(error_codes, check_error_codes, filenames, dirnames
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


Expand Down
67 changes: 67 additions & 0 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)]
Expand Down
9 changes: 6 additions & 3 deletions src/librustc_typeck/coherence/orphan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
42 changes: 33 additions & 9 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
// ...
}
}
```

To fix this error, please implement a trait on the type or wrap it in a struct.
Example:

```
// 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()
}
}
```

In the other, simpler case, Rust just can't find the type you are providing an
impelementation for:
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:

```
impl SomeTypeThatDoesntExist { }
struct TypeWrapper((u8, u8));

impl TypeWrapper {
fn get_state(&self) -> String {
"Fascinating!".to_owned()
}
}
```
"##,

Expand Down
14 changes: 12 additions & 2 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
3 changes: 3 additions & 0 deletions src/libstd/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
/// ```
Expand Down
16 changes: 15 additions & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,14 +1174,28 @@ 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,
tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"),
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,
}))
}
Expand Down
39 changes: 39 additions & 0 deletions src/test/run-pass/macro-doc-raw-str-hashes.rs
Original file line number Diff line number Diff line change
@@ -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: ["###]
};
}