about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--RELEASES.md2
-rw-r--r--src/libcollections/slice.rs59
-rw-r--r--src/librustc/dep_graph/thread.rs2
-rw-r--r--src/librustc/diagnostics.rs35
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs8
-rw-r--r--src/librustc_typeck/collect.rs10
-rw-r--r--src/libstd/fs.rs3
-rw-r--r--src/libstd/macros.rs25
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/test/compile-fail/feature-gate-dropck-ugeh-2.rs22
-rw-r--r--src/test/compile-fail/feature-gate-dropck-ugeh.rs2
-rw-r--r--src/test/compile-fail/issue-17994.rs3
-rw-r--r--src/test/compile-fail/issue-39122.rs13
-rw-r--r--src/test/compile-fail/private-in-public-warn.rs1
-rw-r--r--src/test/compile-fail/uninhabited-reference-type-feature-gated.rs19
-rw-r--r--src/test/debuginfo/borrowed-enum.rs1
-rw-r--r--src/test/debuginfo/generic-struct-style-enum.rs1
-rw-r--r--src/test/debuginfo/generic-tuple-style-enum.rs1
-rw-r--r--src/test/debuginfo/packed-struct.rs1
-rw-r--r--src/test/debuginfo/recursive-struct.rs1
-rw-r--r--src/test/debuginfo/struct-in-enum.rs1
-rw-r--r--src/test/debuginfo/struct-style-enum.rs1
-rw-r--r--src/test/debuginfo/tuple-style-enum.rs1
-rw-r--r--src/test/debuginfo/union-smoke.rs1
-rw-r--r--src/test/debuginfo/unique-enum.rs1
-rw-r--r--src/test/run-pass/empty-types-in-patterns.rs5
-rw-r--r--src/tools/compiletest/src/header.rs50
-rw-r--r--src/tools/compiletest/src/main.rs3
28 files changed, 236 insertions, 42 deletions
diff --git a/RELEASES.md b/RELEASES.md
index e85c9d18db9..a2241c20d74 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -3371,7 +3371,7 @@ Version 1.0.0-alpha (2015-01-09)
       platforms.
     * Rust comes with rust-gdb and rust-lldb scripts that launch their
       respective debuggers with Rust-appropriate pretty-printing.
-    * The Windows installation of Rust is distributed with the the
+    * The Windows installation of Rust is distributed with the
       MinGW components currently required to link binaries on that
       platform.
 
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 805021516db..e704f400d49 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -181,7 +181,7 @@ impl<T> [T] {
         core_slice::SliceExt::len(self)
     }
 
-    /// Returns true if the slice has a length of 0.
+    /// Returns `true` if the slice has a length of 0.
     ///
     /// # Example
     ///
@@ -342,15 +342,22 @@ impl<T> [T] {
         core_slice::SliceExt::last_mut(self)
     }
 
-    /// Returns the element of a slice at the given index, or `None` if the
-    /// index is out of bounds.
+    /// Returns a reference to an element or subslice depending on the type of
+    /// index.
+    ///
+    /// - If given a position, returns a reference to the element at that
+    ///   position or `None` if out of bounds.
+    /// - If given a range, returns the subslice corresponding to that range,
+    ///   or `None` if out of bounds.
     ///
     /// # Examples
     ///
     /// ```
     /// let v = [10, 40, 30];
     /// assert_eq!(Some(&40), v.get(1));
+    /// assert_eq!(Some(&[10, 40][..]), v.get(0..2));
     /// assert_eq!(None, v.get(3));
+    /// assert_eq!(None, v.get(0..4));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -360,7 +367,10 @@ impl<T> [T] {
         core_slice::SliceExt::get(self, index)
     }
 
-    /// Returns a mutable reference to the element at the given index.
+    /// Returns a mutable reference to an element or subslice depending on the
+    /// type of index (see [`get()`]) or `None` if the index is out of bounds.
+    ///
+    /// [`get()`]: #method.get
     ///
     /// # Examples
     ///
@@ -372,7 +382,6 @@ impl<T> [T] {
     /// }
     /// assert_eq!(x, &[0, 42, 2]);
     /// ```
-    /// or `None` if the index is out of bounds
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
@@ -381,8 +390,8 @@ impl<T> [T] {
         core_slice::SliceExt::get_mut(self, index)
     }
 
-    /// Returns a pointer to the element at the given index, without doing
-    /// bounds checking. So use it very carefully!
+    /// Returns a reference to an element or subslice, without doing bounds
+    /// checking. So use it very carefully!
     ///
     /// # Examples
     ///
@@ -401,8 +410,8 @@ impl<T> [T] {
         core_slice::SliceExt::get_unchecked(self, index)
     }
 
-    /// Returns an unsafe mutable pointer to the element in index. So use it
-    /// very carefully!
+    /// Returns a mutable reference to an element or subslice, without doing
+    /// bounds checking. So use it very carefully!
     ///
     /// # Examples
     ///
@@ -540,12 +549,8 @@ impl<T> [T] {
     ///
     /// ```
     /// let x = &mut [1, 2, 4];
-    /// {
-    ///     let iterator = x.iter_mut();
-    ///
-    ///     for elem in iterator {
-    ///         *elem += 2;
-    ///     }
+    /// for elem in x.iter_mut() {
+    ///     *elem += 2;
     /// }
     /// assert_eq!(x, &[3, 4, 6]);
     /// ```
@@ -880,7 +885,7 @@ impl<T> [T] {
         core_slice::SliceExt::rsplitn_mut(self, n, pred)
     }
 
-    /// Returns true if the slice contains an element with the given value.
+    /// Returns `true` if the slice contains an element with the given value.
     ///
     /// # Examples
     ///
@@ -896,7 +901,7 @@ impl<T> [T] {
         core_slice::SliceExt::contains(self, x)
     }
 
-    /// Returns true if `needle` is a prefix of the slice.
+    /// Returns `true` if `needle` is a prefix of the slice.
     ///
     /// # Examples
     ///
@@ -907,6 +912,15 @@ impl<T> [T] {
     /// assert!(!v.starts_with(&[50]));
     /// assert!(!v.starts_with(&[10, 50]));
     /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.starts_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.starts_with(&[]));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn starts_with(&self, needle: &[T]) -> bool
         where T: PartialEq
@@ -914,7 +928,7 @@ impl<T> [T] {
         core_slice::SliceExt::starts_with(self, needle)
     }
 
-    /// Returns true if `needle` is a suffix of the slice.
+    /// Returns `true` if `needle` is a suffix of the slice.
     ///
     /// # Examples
     ///
@@ -925,6 +939,15 @@ impl<T> [T] {
     /// assert!(!v.ends_with(&[50]));
     /// assert!(!v.ends_with(&[50, 30]));
     /// ```
+    ///
+    /// Always returns `true` if `needle` is an empty slice:
+    ///
+    /// ```
+    /// let v = &[10, 40, 30];
+    /// assert!(v.ends_with(&[]));
+    /// let v: &[u8] = &[];
+    /// assert!(v.ends_with(&[]));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ends_with(&self, needle: &[T]) -> bool
         where T: PartialEq
diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs
index 9f755cf86e4..d3a940c811b 100644
--- a/src/librustc/dep_graph/thread.rs
+++ b/src/librustc/dep_graph/thread.rs
@@ -56,7 +56,7 @@ pub struct DepGraphThreadData {
     // current buffer, where we accumulate messages
     messages: VecCell<DepMessage>,
 
-    // whence to receive new buffer when full
+    // where to receive new buffer when full
     swap_in: Receiver<Vec<DepMessage>>,
 
     // where to send buffer when full
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 636d543a071..0d180e6ad76 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1454,6 +1454,40 @@ struct Prince<'kiss, 'SnowWhite: 'kiss> { // You say here that 'kiss must live
 ```
 "##,
 
+E0491: r##"
+A reference has a longer lifetime than the data it references.
+
+Erroneous code example:
+
+```compile_fail,E0491
+// struct containing a reference requires a lifetime parameter,
+// because the data the reference points to must outlive the struct (see E0106)
+struct Struct<'a> {
+    ref_i32: &'a i32,
+}
+
+// However, a nested struct like this, the signature itself does not tell
+// whether 'a outlives 'b or the other way around.
+// So it could be possible that 'b of reference outlives 'a of the data.
+struct Nested<'a, 'b> {
+    ref_struct: &'b Struct<'a>, // compile error E0491
+}
+```
+
+To fix this issue, you can specify a bound to the lifetime like below:
+
+```
+struct Struct<'a> {
+    ref_i32: &'a i32,
+}
+
+// 'a: 'b means 'a outlives 'b
+struct Nested<'a: 'b, 'b> {
+    ref_struct: &'b Struct<'a>,
+}
+```
+"##,
+
 E0496: r##"
 A lifetime name is shadowing another lifetime name. Erroneous code example:
 
@@ -1697,7 +1731,6 @@ register_diagnostics! {
     E0488, // lifetime of variable does not enclose its declaration
     E0489, // type/lifetime parameter not in scope here
     E0490, // a value of type `..` is borrowed for too long
-    E0491, // in type `..`, reference has a longer lifetime than the data it...
     E0495, // cannot infer an appropriate lifetime due to conflicting requirements
     E0566  // conflicting representation hints
 }
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index c5b75839e99..92395e3c381 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -190,7 +190,13 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                     ty.uninhabited_from(visited, tcx)
                 }
             }
-            TyRef(_, ref tm) => tm.ty.uninhabited_from(visited, tcx),
+            TyRef(_, ref tm) => {
+                if tcx.sess.features.borrow().never_type {
+                    tm.ty.uninhabited_from(visited, tcx)
+                } else {
+                    DefIdForest::empty()
+                }
+            }
 
             _ => DefIdForest::empty(),
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index f832bf8d86e..e13434db5d8 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -716,6 +716,16 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
         }
     }
 
+    for predicate in generics.where_clause.predicates.iter() {
+        match *predicate {
+            hir::WherePredicate::BoundPredicate(..) => {
+                warn = true;
+            }
+            hir::WherePredicate::RegionPredicate(..) => { }
+            hir::WherePredicate::EqPredicate(..) => { }
+        }
+    }
+
     if warn {
         // According to accepted RFC #XXX, we should
         // eventually accept these, but it will not be
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 41934dc057e..06402cc0e8e 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -81,7 +81,8 @@ use time::SystemTime;
 /// # }
 /// ```
 ///
-/// [`BufReader`]: ../io/struct.BufReader.html
+/// [`Read`]: ../io/trait.Read.html
+/// [`BufReader<R>`]: ../io/struct.BufReader.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 52c6da58151..d79a9a202d9 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -458,23 +458,38 @@ pub mod builtin {
 
     /// Parse a file as an expression or an item according to the context.
     ///
-    /// The file is located relative to the current file. (similarly to how
-    /// modules are found)
+    /// The file is located relative to the current file (similarly to how
+    /// modules are found).
     ///
     /// Using this macro is often a bad idea, because if the file is
     /// parsed as an expression, it is going to be placed in the
-    /// surrounding code unhygenically. This could result in variables
+    /// surrounding code unhygienically. This could result in variables
     /// or functions being different from what the file expected if
     /// there are variables or functions that have the same name in
     /// the current file.
     ///
     /// # Examples
     ///
+    /// Assume there are two files in the same directory with the following
+    /// contents:
+    ///
+    /// File 'my_str.in':
+    ///
     /// ```ignore
-    /// fn foo() {
-    ///     include!("/path/to/a/file")
+    /// "Hello World!"
+    /// ```
+    ///
+    /// File 'main.rs':
+    ///
+    /// ```ignore
+    /// fn main() {
+    ///     let my_str = include!("my_str.in");
+    ///     println!("{}", my_str);
     /// }
     /// ```
+    ///
+    /// Compiling 'main.rs' and running the resulting binary will print "Hello
+    /// World!".
     #[stable(feature = "rust1", since = "1.0.0")]
     #[macro_export]
     macro_rules! include { ($file:expr) => ({ /* compiler built-in */ }) }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ba6e752d310..fb75201cea5 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -689,10 +689,10 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                                        cfg_fn!(omit_gdb_pretty_printer_section))),
     ("unsafe_destructor_blind_to_params",
      Normal,
-     Gated(Stability::Unstable,
+     Gated(Stability::Deprecated("https://github.com/rust-lang/rust/issues/34761"),
            "dropck_parametricity",
-           "unsafe_destructor_blind_to_params has unstable semantics \
-            and may be removed in the future",
+           "unsafe_destructor_blind_to_params has been replaced by \
+            may_dangle and will be removed in the future",
            cfg_fn!(dropck_parametricity))),
     ("may_dangle",
      Normal,
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs b/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs
new file mode 100644
index 00000000000..70ec561439c
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-dropck-ugeh-2.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 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.
+
+#![deny(deprecated)]
+#![feature(dropck_parametricity)]
+
+struct Foo;
+
+impl Drop for Foo {
+    #[unsafe_destructor_blind_to_params]
+    //~^ ERROR use of deprecated attribute `dropck_parametricity`
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs
index 7c290b3c9c2..360895d30b0 100644
--- a/src/test/compile-fail/feature-gate-dropck-ugeh.rs
+++ b/src/test/compile-fail/feature-gate-dropck-ugeh.rs
@@ -27,7 +27,7 @@ struct Foo<T> { data: Vec<T> }
 
 impl<T> Drop for Foo<T> {
     #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
-    //~^ ERROR unsafe_destructor_blind_to_params has unstable semantics
+    //~^ ERROR unsafe_destructor_blind_to_params has been replaced
     fn drop(&mut self) { }
 }
 
diff --git a/src/test/compile-fail/issue-17994.rs b/src/test/compile-fail/issue-17994.rs
index fcbc08327b9..ac15bd9d15b 100644
--- a/src/test/compile-fail/issue-17994.rs
+++ b/src/test/compile-fail/issue-17994.rs
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 trait Tr {}
-type Huh<T> where T: Tr = isize; //~ ERROR type parameter `T` is unused
+type Huh<T> where T: Tr = isize; //~  ERROR type parameter `T` is unused
+                                 //~| WARNING E0122
 fn main() {}
diff --git a/src/test/compile-fail/issue-39122.rs b/src/test/compile-fail/issue-39122.rs
new file mode 100644
index 00000000000..2e8a740f893
--- /dev/null
+++ b/src/test/compile-fail/issue-39122.rs
@@ -0,0 +1,13 @@
+// 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.
+
+type Foo<T: std::ops::Add> = T; //~ WARNING E0122
+
+type Bar<T> where T: std::ops::Add = T; //~ WARNING E0122
diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs
index 3496348985d..92d96595fd7 100644
--- a/src/test/compile-fail/private-in-public-warn.rs
+++ b/src/test/compile-fail/private-in-public-warn.rs
@@ -89,6 +89,7 @@ mod traits_where {
     pub type Alias<T> where T: PrivTr = T;
         //~^ ERROR private trait `traits_where::PrivTr` in public interface
         //~| WARNING hard error
+        //~| WARNING E0122
     pub trait Tr2<T> where T: PrivTr {}
         //~^ ERROR private trait `traits_where::PrivTr` in public interface
         //~| WARNING hard error
diff --git a/src/test/compile-fail/uninhabited-reference-type-feature-gated.rs b/src/test/compile-fail/uninhabited-reference-type-feature-gated.rs
new file mode 100644
index 00000000000..8f246eddbcd
--- /dev/null
+++ b/src/test/compile-fail/uninhabited-reference-type-feature-gated.rs
@@ -0,0 +1,19 @@
+// Copyright 2016 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.
+
+enum Void {}
+
+fn main() {
+    let x: Result<u32, &'static Void> = Ok(23);
+    let _ = match x {   //~ ERROR non-exhaustive
+        Ok(n) => n,
+    };
+}
+
diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs
index f34fc3b20d2..c457fed7ecd 100644
--- a/src/test/debuginfo/borrowed-enum.rs
+++ b/src/test/debuginfo/borrowed-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs
index a328eec6893..df56ccccca3 100644
--- a/src/test/debuginfo/generic-struct-style-enum.rs
+++ b/src/test/debuginfo/generic-struct-style-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs
index 9ada5fdeff7..e538700f0f8 100644
--- a/src/test/debuginfo/generic-tuple-style-enum.rs
+++ b/src/test/debuginfo/generic-tuple-style-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs
index b84161c36a5..c476e9fe079 100644
--- a/src/test/debuginfo/packed-struct.rs
+++ b/src/test/debuginfo/packed-struct.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs
index 80147b14174..f33dfac07d2 100644
--- a/src/test/debuginfo/recursive-struct.rs
+++ b/src/test/debuginfo/recursive-struct.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // ignore-lldb
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs
index ffd36ae14ad..d9763aedd7c 100644
--- a/src/test/debuginfo/struct-in-enum.rs
+++ b/src/test/debuginfo/struct-in-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs
index b6196daaa46..6212caa6953 100644
--- a/src/test/debuginfo/struct-style-enum.rs
+++ b/src/test/debuginfo/struct-style-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs
index 988f223b3bc..f85cd6a50f5 100644
--- a/src/test/debuginfo/tuple-style-enum.rs
+++ b/src/test/debuginfo/tuple-style-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs
index 5d3fbd62023..844e9405ba5 100644
--- a/src/test/debuginfo/union-smoke.rs
+++ b/src/test/debuginfo/union-smoke.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs
index cf8d90e30f1..e8eb4315007 100644
--- a/src/test/debuginfo/unique-enum.rs
+++ b/src/test/debuginfo/unique-enum.rs
@@ -10,6 +10,7 @@
 
 // ignore-tidy-linelength
 // min-lldb-version: 310
+// ignore-gdb-version: 7.11.90 - 7.12
 
 // compile-flags:-g
 
diff --git a/src/test/run-pass/empty-types-in-patterns.rs b/src/test/run-pass/empty-types-in-patterns.rs
index 23705d36e3d..033b185a0ef 100644
--- a/src/test/run-pass/empty-types-in-patterns.rs
+++ b/src/test/run-pass/empty-types-in-patterns.rs
@@ -55,6 +55,11 @@ fn main() {
         Err(e) => match e {},
     };
 
+    let x: Result<u32, &!> = Ok(123);
+    match x {
+        Ok(y) => y,
+    };
+
     bar(&[]);
 }
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index e57c9949b1c..ac1ac1c2f6c 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -73,19 +73,29 @@ impl EarlyProps {
                 return false;
             }
 
-            if parse_name_directive(line, "ignore-gdb") {
+            if !line.contains("ignore-gdb-version") &&
+               parse_name_directive(line, "ignore-gdb") {
                 return true;
             }
 
             if let Some(actual_version) = config.gdb_version {
                 if line.contains("min-gdb-version") {
-                    let min_version = line.trim()
-                        .split(' ')
-                        .last()
-                        .expect("Malformed GDB version directive");
+                    let (start_ver, end_ver) = extract_gdb_version_range(line);
+
+                    if start_ver != end_ver {
+                        panic!("Expected single GDB version")
+                    }
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    actual_version < extract_gdb_version(min_version).unwrap()
+                    actual_version < start_ver
+                } else if line.contains("ignore-gdb-version") {
+                    let (min_version, max_version) = extract_gdb_version_range(line);
+
+                    if max_version < min_version {
+                        panic!("Malformed GDB version range: max < min")
+                    }
+
+                    actual_version >= min_version && actual_version <= max_version
                 } else {
                     false
                 }
@@ -94,6 +104,34 @@ impl EarlyProps {
             }
         }
 
+        // Takes a directive of the form "ignore-gdb-version <version1> [- <version2>]",
+        // returns the numeric representation of <version1> and <version2> as
+        // tuple: (<version1> as u32, <version2> as u32)
+        // If the <version2> part is omitted, the second component of the tuple
+        // is the same as <version1>.
+        fn extract_gdb_version_range(line: &str) -> (u32, u32) {
+            const ERROR_MESSAGE: &'static str = "Malformed GDB version directive";
+
+            let range_components = line.split(' ')
+                                       .flat_map(|word| word.split('-'))
+                                       .filter(|word| word.len() > 0)
+                                       .skip_while(|word| extract_gdb_version(word).is_none())
+                                       .collect::<Vec<&str>>();
+
+            match range_components.len() {
+                1 => {
+                    let v = extract_gdb_version(range_components[0]).unwrap();
+                    (v, v)
+                }
+                2 => {
+                    let v_min = extract_gdb_version(range_components[0]).unwrap();
+                    let v_max = extract_gdb_version(range_components[1]).expect(ERROR_MESSAGE);
+                    (v_min, v_max)
+                }
+                _ => panic!(ERROR_MESSAGE),
+            }
+        }
+
         fn ignore_lldb(config: &Config, line: &str) -> bool {
             if config.mode != common::DebugInfoLldb {
                 return false;
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index f6c8393ac21..8c9982d1d4e 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -587,7 +587,6 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
         return Some(((major * 1000) + minor) * 1000 + patch);
     }
 
-    println!("Could not extract GDB version from line '{}'", full_version_line);
     None
 }
 
@@ -624,8 +623,6 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
                 }).collect::<String>();
                 if !vers.is_empty() { return Some(vers) }
             }
-            println!("Could not extract LLDB version from line '{}'",
-                     full_version_line);
         }
     }
     None