about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-02-03 00:58:37 +0000
committerbors <bors@rust-lang.org>2016-02-03 00:58:37 +0000
commita9922419cf84a12b2b9c69f8b261cdd7c287c1a5 (patch)
tree892a71c2d529580445b468a47d1b627ee5b8fbca
parentdea183aa8461e8520b08864ec81ad2985be36d34 (diff)
parent1a21dabf27232c5c9281a6bf7a8b83afb3efa201 (diff)
downloadrust-a9922419cf84a12b2b9c69f8b261cdd7c287c1a5.tar.gz
rust-a9922419cf84a12b2b9c69f8b261cdd7c287c1a5.zip
Auto merge of #31370 - Manishearth:rollup, r=Manishearth
- Successful merges: #27499, #31220, #31329, #31332, #31347, #31351, #31352, #31366
- Failed merges:
-rw-r--r--src/doc/book/guessing-game.md2
-rw-r--r--src/doc/book/patterns.md34
-rw-r--r--src/etc/errorck.py2
-rw-r--r--src/libcore/iter.rs67
-rw-r--r--src/librustc_typeck/coherence/orphan.rs9
-rw-r--r--src/librustc_typeck/diagnostics.rs42
-rw-r--r--src/librustdoc/html/render.rs14
-rw-r--r--src/libstd/macros.rs3
-rw-r--r--src/libsyntax/ast.rs16
-rw-r--r--src/test/run-pass/macro-doc-raw-str-hashes.rs39
10 files changed, 210 insertions, 18 deletions
diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md
index 861ef6810f5..a5259e9ca4c 100644
--- a/src/doc/book/guessing-game.md
+++ b/src/doc/book/guessing-game.md
@@ -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
diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md
index 8e9e7246e56..6fd7f4cd475 100644
--- a/src/doc/book/patterns.md
+++ b/src/doc/book/patterns.md
@@ -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 {
diff --git a/src/etc/errorck.py b/src/etc/errorck.py
index 1b15d2c8598..1f5f3784ac6 100644
--- a/src/etc/errorck.py
+++ b/src/etc/errorck.py
@@ -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
 
 
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 93514dbd6bb..3f1808a0396 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -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)]
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 69eb7f51f37..fb257f0e673 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -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;
                     }
                 }
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index df09cd26134..f138b997f4c 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -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()
+    }
+}
 ```
 "##,
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 850045382e1..dfbe08a0e42 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -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(),
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 0917346213f..b7afd12d8e5 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -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
     ///
     /// ```
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 19bedab9d30..088f911ed8c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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,
                 }))
             }
diff --git a/src/test/run-pass/macro-doc-raw-str-hashes.rs b/src/test/run-pass/macro-doc-raw-str-hashes.rs
new file mode 100644
index 00000000000..ffbe237b74e
--- /dev/null
+++ b/src/test/run-pass/macro-doc-raw-str-hashes.rs
@@ -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: ["###]
+    };
+}