about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/etc/gdb_rust_pretty_printing.py12
-rw-r--r--src/libcore/any.rs41
-rw-r--r--src/libcore/iter/range.rs8
-rw-r--r--src/tools/tidy/src/error_codes_check.rs68
4 files changed, 106 insertions, 23 deletions
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
index a6b09722e1c..5da01b96fa5 100755
--- a/src/etc/gdb_rust_pretty_printing.py
+++ b/src/etc/gdb_rust_pretty_printing.py
@@ -284,10 +284,20 @@ class RustStdVecPrinter(object):
                 ("(len: %i, cap: %i)" % (length, cap)))
 
     def children(self):
+        saw_inaccessible = False
         (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val)
         gdb_ptr = data_ptr.get_wrapped_value()
         for index in xrange(0, length):
-            yield (str(index), (gdb_ptr + index).dereference())
+            if saw_inaccessible:
+                return
+            try:
+                # rust-lang/rust#64343: passing deref expr to `str` allows
+                # catching exception on garbage pointer
+                str((gdb_ptr + index).dereference())
+                yield (str(index), (gdb_ptr + index).dereference())
+            except RuntimeError:
+                saw_inaccessible = True
+                yield (str(index), "inaccessible")
 
 
 class RustStdVecDequePrinter(object):
diff --git a/src/libcore/any.rs b/src/libcore/any.rs
index 39a5dd7263c..57a2aecd8be 100644
--- a/src/libcore/any.rs
+++ b/src/libcore/any.rs
@@ -452,7 +452,7 @@ impl TypeId {
 /// The current implementation uses the same infrastructure as compiler
 /// diagnostics and debuginfo, but this is not guaranteed.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```rust
 /// assert_eq!(
@@ -465,3 +465,42 @@ impl TypeId {
 pub const fn type_name<T: ?Sized>() -> &'static str {
     intrinsics::type_name::<T>()
 }
+
+/// Returns the name of the type of the pointed-to value as a string slice.
+/// This is the same as `type_name::<T>()`, but can be used where the type of a
+/// variable is not easily available.
+///
+/// # Note
+///
+/// This is intended for diagnostic use. The exact contents and format of the
+/// string are not specified, other than being a best-effort description of the
+/// type. For example, `type_name_of::<Option<String>>(None)` could return the
+/// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
+/// `"foobar"`. In addition, the output may change between versions of the
+/// compiler.
+///
+/// The type name should not be considered a unique identifier of a type;
+/// multiple types may share the same type name.
+///
+/// The current implementation uses the same infrastructure as compiler
+/// diagnostics and debuginfo, but this is not guaranteed.
+///
+/// # Examples
+///
+/// Prints the default integer and float types.
+///
+/// ```rust
+/// #![feature(type_name_of_val)]
+/// use std::any::type_name_of_val;
+///
+/// let x = 1;
+/// println!("{}", type_name_of_val(&x));
+/// let y = 1.0;
+/// println!("{}", type_name_of_val(&y));
+/// ```
+#[unstable(feature = "type_name_of_val", issue = "66359")]
+#[rustc_const_unstable(feature = "const_type_name")]
+pub const fn type_name_of_val<T: ?Sized>(val: &T) -> &'static str {
+    let _ = val;
+    type_name::<T>()
+}
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index efda3b263cc..63036f516a0 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -20,10 +20,14 @@ pub trait Step: Clone + PartialOrd + Sized {
     /// without overflow.
     fn steps_between(start: &Self, end: &Self) -> Option<usize>;
 
-    /// Replaces this step with `1`, returning itself.
+    /// Replaces this step with `1`, returning a clone of itself.
+    ///
+    /// The output of this method should always be greater than the output of replace_zero.
     fn replace_one(&mut self) -> Self;
 
-    /// Replaces this step with `0`, returning itself.
+    /// Replaces this step with `0`, returning a clone of itself.
+    ///
+    /// The output of this method should always be less than the output of replace_one.
     fn replace_zero(&mut self) -> Self;
 
     /// Adds one to this step, returning the result.
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index bd58de81c77..5364005840a 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -3,6 +3,8 @@
 
 use std::collections::HashMap;
 use std::ffi::OsStr;
+use std::fs::read_to_string;
+use std::io::Read;
 use std::path::Path;
 
 // A few of those error codes can't be tested but all the others can and *should* be tested!
@@ -50,29 +52,60 @@ const WHITELIST: &[&str] = &[
     "E0729",
 ];
 
-fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>) {
+fn check_error_code_explanation(
+    f: &str,
+    error_codes: &mut HashMap<String, bool>,
+    err_code: String,
+) {
+    for line in f.lines() {
+        let s = line.trim();
+        if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
+            error_codes.insert(err_code, true);
+            return;
+        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
+            error_codes.get_mut(&err_code).map(|x| *x = true);
+            return;
+        }
+    }
+}
+
+macro_rules! some_or_continue {
+    ($e:expr) => (
+        match $e {
+            Some(e) => e,
+            None => continue,
+        }
+    );
+}
+
+fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
     let mut reached_no_explanation = false;
-    let mut last_error_code = None;
 
     for line in f.lines() {
         let s = line.trim();
-        if s.starts_with('E') && s.ends_with(": r##\"") {
+        if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
             if let Some(err_code) = s.splitn(2, ':').next() {
                 let err_code = err_code.to_owned();
-                last_error_code = Some(err_code.clone());
                 if !error_codes.contains_key(&err_code) {
-                    error_codes.insert(err_code, false);
+                    error_codes.insert(err_code.clone(), false);
                 }
-            }
-        } else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
-            if let Some(err_code) = s.splitn(2, 'E').skip(1).next() {
-                if let Some(err_code) = err_code.splitn(2, ',').next() {
-                    let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false);
-                    *nb = true;
+                // Now we extract the tests from the markdown file!
+                let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
+                let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
+                let path = some_or_continue!(path.parent()).join(md_file_name);
+                match read_to_string(&path) {
+                    Ok(content) => {
+                        check_error_code_explanation(
+                            &content,
+                            error_codes,
+                            err_code,
+                        );
+                    }
+                    Err(e) => {
+                        eprintln!("Couldn't read `{}`: {}", path.display(), e);
+                    }
                 }
             }
-        } else if s == ";" {
-            reached_no_explanation = true;
         } else if reached_no_explanation && s.starts_with('E') {
             if let Some(err_code) = s.splitn(2, ',').next() {
                 let err_code = err_code.to_owned();
@@ -80,11 +113,8 @@ fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>) {
                     error_codes.insert(err_code, false);
                 }
             }
-        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
-            if let Some(last) = last_error_code {
-                error_codes.get_mut(&last).map(|x| *x = true);
-            }
-            last_error_code = None;
+        } else if s == ";" {
+            reached_no_explanation = true;
         }
     }
 }
@@ -111,7 +141,7 @@ pub fn check(path: &Path, bad: &mut bool) {
                 &mut |entry, contents| {
         let file_name = entry.file_name();
         if file_name == "error_codes.rs" {
-            extract_error_codes(contents, &mut error_codes);
+            extract_error_codes(contents, &mut error_codes, entry.path());
         } else if entry.path().extension() == Some(OsStr::new("stderr")) {
             extract_error_codes_from_tests(contents, &mut error_codes);
         }