about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-19 00:56:21 +0000
committerbors <bors@rust-lang.org>2018-07-19 00:56:21 +0000
commit629d891499bca79aeb8ea079f756c566fdabbd3e (patch)
tree57437d0b26123c42852dd692743584fcb35a631d /src
parent166795dda66ce8132e2686923704d6bdcb5c2bc3 (diff)
parentae9c550415f639791e83b4b058c69f2842a4ff5c (diff)
downloadrust-629d891499bca79aeb8ea079f756c566fdabbd3e.tar.gz
rust-629d891499bca79aeb8ea079f756c566fdabbd3e.zip
Auto merge of #52486 - kennytm:rollup, r=kennytm
Rollup of 13 pull requests

Successful merges:

 - #51628 (use checked write in `LineWriter` example)
 - #52116 (Handle array manually in str case conversion methods)
 - #52218 (Amend option.take examples)
 - #52418 (Do not use desugared ident when suggesting adding a type)
 - #52439 (Revert some changes from #51917 to fix custom libdir)
 - #52455 (Fix doc comment: use `?` instead of `.unwrap()`)
 - #52458 (rustc: Fix a suggestion for the `proc_macro` feature)
 - #52464 (Allow clippy to be installed with make install)
 - #52472 (rustc: Enable `use_extern_macros` in 2018 edition)
 - #52477 (Clarify short-circuiting behvaior of Iterator::zip.)
 - #52480 (Cleanup #24958)
 - #52487 (Don't build twice the sanitizers on Linux)
 - #52510 (rustdoc: remove FIXME about macro redirects)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/bin/rustdoc.rs3
-rw-r--r--src/bootstrap/builder.rs4
-rw-r--r--src/build_helper/lib.rs27
-rw-r--r--src/liballoc/str.rs29
-rw-r--r--src/libcore/iter/iterator.rs4
-rw-r--r--src/libcore/option.rs6
-rw-r--r--src/libcore/unicode/mod.rs3
-rw-r--r--src/librustc/hir/lowering.rs6
-rw-r--r--src/librustc/ich/impls_syntax.rs1
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs11
-rw-r--r--src/librustc_asan/build.rs4
-rw-r--r--src/librustc_lsan/build.rs4
-rw-r--r--src/librustc_msan/build.rs4
-rw-r--r--src/librustc_resolve/lib.rs2
-rw-r--r--src/librustc_tsan/build.rs4
-rw-r--r--src/librustdoc/html/render.rs1
-rw-r--r--src/libstd/io/buffered.rs33
-rw-r--r--src/libstd/net/tcp.rs2
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/libsyntax_pos/hygiene.rs2
-rw-r--r--src/test/debuginfo/type-names.rs3
-rw-r--r--src/test/ui/issue-20261.stderr2
-rw-r--r--src/test/ui/issue-51116.rs24
-rw-r--r--src/test/ui/issue-51116.stderr14
24 files changed, 153 insertions, 42 deletions
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 798d5c3eb67..a54e58665cc 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -35,7 +35,7 @@ fn main() {
     };
 
     let mut dylib_path = bootstrap::util::dylib_path();
-    dylib_path.insert(0, PathBuf::from(libdir));
+    dylib_path.insert(0, PathBuf::from(libdir.clone()));
 
     let mut cmd = Command::new(rustdoc);
     cmd.args(&args)
@@ -69,6 +69,7 @@ fn main() {
 
     if verbose > 1 {
         eprintln!("rustdoc command: {:?}", cmd);
+        eprintln!("libdir: {:?}", libdir);
     }
 
     std::process::exit(match cmd.status() {
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 79167b1fd5e..c67787b5b0a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -459,6 +459,7 @@ impl<'a> Builder<'a> {
                 dist::Cargo,
                 dist::Rls,
                 dist::Rustfmt,
+                dist::Clippy,
                 dist::LlvmTools,
                 dist::Extended,
                 dist::HashSign
@@ -469,6 +470,7 @@ impl<'a> Builder<'a> {
                 install::Cargo,
                 install::Rls,
                 install::Rustfmt,
+                install::Clippy,
                 install::Analysis,
                 install::Src,
                 install::Rustc
@@ -825,7 +827,7 @@ impl<'a> Builder<'a> {
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
         if cmd != "build" && cmd != "check" && want_rustdoc {
-            cargo.env("RUSTDOC_LIBDIR", &libdir);
+            cargo.env("RUSTDOC_LIBDIR", self.sysroot_libdir(compiler, self.config.build));
         }
 
         if mode.is_tool() {
diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs
index 4d767f09689..00e5dee256e 100644
--- a/src/build_helper/lib.rs
+++ b/src/build_helper/lib.rs
@@ -15,6 +15,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::time::{SystemTime, UNIX_EPOCH};
 use std::{env, fs};
+use std::thread;
 
 /// A helper macro to `unwrap` a result except also print out details like:
 ///
@@ -181,7 +182,9 @@ pub struct NativeLibBoilerplate {
 
 impl Drop for NativeLibBoilerplate {
     fn drop(&mut self) {
-        t!(File::create(self.out_dir.join("rustbuild.timestamp")));
+        if !thread::panicking() {
+            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
+        }
     }
 }
 
@@ -225,24 +228,34 @@ pub fn native_lib_boilerplate(
     }
 }
 
-pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) -> Result<NativeLibBoilerplate, ()> {
-    let (link_name, search_path) = match &*env::var("TARGET").unwrap() {
+pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
+    -> Result<(NativeLibBoilerplate, String), ()>
+{
+    let (link_name, search_path, dynamic) = match &*env::var("TARGET").unwrap() {
         "x86_64-unknown-linux-gnu" => (
             format!("clang_rt.{}-x86_64", sanitizer_name),
             "build/lib/linux",
+            false,
         ),
         "x86_64-apple-darwin" => (
-            format!("dylib=clang_rt.{}_osx_dynamic", sanitizer_name),
+            format!("clang_rt.{}_osx_dynamic", sanitizer_name),
             "build/lib/darwin",
+            true,
         ),
         _ => return Err(()),
     };
-    native_lib_boilerplate(
+    let to_link = if dynamic {
+        format!("dylib={}", link_name)
+    } else {
+        format!("static={}", link_name)
+    };
+    let lib = native_lib_boilerplate(
         "libcompiler_builtins/compiler-rt",
         sanitizer_name,
-        &link_name,
+        &to_link,
         search_path,
-    )
+    )?;
+    Ok((lib, link_name))
 }
 
 fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index bb99d0401d3..4d6434c378e 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -45,6 +45,7 @@ use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
 use core::mem;
 use core::ptr;
 use core::iter::FusedIterator;
+use core::unicode::conversions;
 
 use borrow::{Borrow, ToOwned};
 use boxed::Box;
@@ -369,7 +370,18 @@ impl str {
                 // See https://github.com/rust-lang/rust/issues/26035
                 map_uppercase_sigma(self, i, &mut s)
             } else {
-                s.extend(c.to_lowercase());
+                match conversions::to_lower(c) {
+                    [a, '\0', _] => s.push(a),
+                    [a, b, '\0'] => {
+                        s.push(a);
+                        s.push(b);
+                    }
+                    [a, b, c] => {
+                        s.push(a);
+                        s.push(b);
+                        s.push(c);
+                    }
+                }
             }
         }
         return s;
@@ -423,7 +435,20 @@ impl str {
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_uppercase(&self) -> String {
         let mut s = String::with_capacity(self.len());
-        s.extend(self.chars().flat_map(|c| c.to_uppercase()));
+        for c in self[..].chars() {
+            match conversions::to_upper(c) {
+                [a, '\0', _] => s.push(a),
+                [a, b, '\0'] => {
+                    s.push(a);
+                    s.push(b);
+                }
+                [a, b, c] => {
+                    s.push(a);
+                    s.push(b);
+                    s.push(c);
+                }
+            }
+        }
         return s;
     }
 
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index c0681619bf8..afc273d265b 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -384,7 +384,9 @@ pub trait Iterator {
     ///
     /// In other words, it zips two iterators together, into a single one.
     ///
-    /// If either iterator returns [`None`], [`next`] will return [`None`].
+    /// If either iterator returns [`None`], [`next`] from the zipped iterator
+    /// will return [`None`]. If the first iterator returns [`None`], `zip` will
+    /// short-circuit and `next` will not be called on the second iterator.
     ///
     /// # Examples
     ///
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index f3e823670aa..9f9dbd0777a 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -833,12 +833,14 @@ impl<T> Option<T> {
     ///
     /// ```
     /// let mut x = Some(2);
-    /// x.take();
+    /// let y = x.take();
     /// assert_eq!(x, None);
+    /// assert_eq!(y, Some(2));
     ///
     /// let mut x: Option<u32> = None;
-    /// x.take();
+    /// let y = x.take();
     /// assert_eq!(x, None);
+    /// assert_eq!(y, None);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/unicode/mod.rs b/src/libcore/unicode/mod.rs
index b6b033adc04..e5cda880f88 100644
--- a/src/libcore/unicode/mod.rs
+++ b/src/libcore/unicode/mod.rs
@@ -20,6 +20,9 @@ pub(crate) mod version;
 pub mod derived_property {
     pub use unicode::tables::derived_property::{Case_Ignorable, Cased};
 }
+pub mod conversions {
+    pub use unicode::tables::conversions::{to_lower, to_upper};
+}
 
 // For use in libsyntax
 pub mod property {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 722934ac39a..93fb282546b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4011,8 +4011,12 @@ impl<'a> LoweringContext<'a> {
                 let iter = self.str_to_ident("iter");
 
                 let next_ident = self.str_to_ident("__next");
+                let next_sp = self.allow_internal_unstable(
+                    CompilerDesugaringKind::ForLoop,
+                    head_sp,
+                );
                 let next_pat = self.pat_ident_binding_mode(
-                    pat.span,
+                    next_sp,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
                 );
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index fa9c5cefdf3..c9ac6cdedbb 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -412,6 +412,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
     DotFill,
     QuestionMark,
     ExistentialReturnType,
+    ForLoop,
     Catch
 });
 
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 773de8912ce..04d14f40b85 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -13,6 +13,7 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::InferCtxt;
 use infer::type_variable::TypeVariableOrigin;
 use ty::{self, Ty, TyInfer, TyVar};
+use syntax::codemap::CompilerDesugaringKind;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
 
@@ -132,7 +133,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             labels.push((pattern.span, format!("consider giving this closure parameter a type")));
         } else if let Some(pattern) = local_visitor.found_local_pattern {
             if let Some(simple_ident) = pattern.simple_ident() {
-                labels.push((pattern.span, format!("consider giving `{}` a type", simple_ident)));
+                match pattern.span.compiler_desugaring_kind() {
+                    None => labels.push((pattern.span,
+                                         format!("consider giving `{}` a type", simple_ident))),
+                    Some(CompilerDesugaringKind::ForLoop) => labels.push((
+                        pattern.span,
+                        "the element type for this iterator is not specified".to_string(),
+                    )),
+                    _ => {}
+                }
             } else {
                 labels.push((pattern.span, format!("consider giving the pattern a type")));
             }
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index cb7721affe7..b8614c520e7 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -18,7 +18,7 @@ use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let native = match sanitizer_lib_boilerplate("asan") {
+        let (native, target) = match sanitizer_lib_boilerplate("asan") {
             Ok(native) => native,
             _ => return,
         };
@@ -29,7 +29,7 @@ fn main() {
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
             .out_dir(&native.out_dir)
-            .build_target("asan")
+            .build_target(&target)
             .build();
     }
     println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index 3d2ae480de6..05e40cdcedd 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -18,7 +18,7 @@ use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let native = match sanitizer_lib_boilerplate("lsan") {
+        let (native, target) = match sanitizer_lib_boilerplate("lsan") {
             Ok(native) => native,
             _ => return,
         };
@@ -29,7 +29,7 @@ fn main() {
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
             .out_dir(&native.out_dir)
-            .build_target("lsan")
+            .build_target(&target)
             .build();
     }
     println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index 7e2a82dd0ab..4abfc358560 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -18,7 +18,7 @@ use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let native = match sanitizer_lib_boilerplate("msan") {
+        let (native, target) = match sanitizer_lib_boilerplate("msan") {
             Ok(native) => native,
             _ => return,
         };
@@ -29,7 +29,7 @@ fn main() {
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
             .out_dir(&native.out_dir)
-            .build_target("msan")
+            .build_target(&target)
             .build();
     }
     println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f388b911feb..177e4ed8cf3 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4521,7 +4521,7 @@ impl<'a> Resolver<'a> {
                     attr::mark_known(attr);
 
                     let msg = "attribute procedural macros are experimental";
-                    let feature = "proc_macro";
+                    let feature = "use_extern_macros";
 
                     feature_err(&self.session.parse_sess, feature,
                                 attr.span, GateIssue::Language, msg)
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index 641d9c3647d..38595478c74 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -18,7 +18,7 @@ use cmake::Config;
 
 fn main() {
     if let Some(llvm_config) = env::var_os("LLVM_CONFIG") {
-        let native = match sanitizer_lib_boilerplate("tsan") {
+        let (native, target) = match sanitizer_lib_boilerplate("tsan") {
             Ok(native) => native,
             _ => return,
         };
@@ -29,7 +29,7 @@ fn main() {
             .define("COMPILER_RT_BUILD_XRAY", "OFF")
             .define("LLVM_CONFIG_PATH", llvm_config)
             .out_dir(&native.out_dir)
-            .build_target("tsan")
+            .build_target(&target)
             .build();
     }
     println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 41c08dbf4ab..3070458d0be 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1968,7 +1968,6 @@ impl Context {
 
                 // If the item is a macro, redirect from the old macro URL (with !)
                 // to the new one (without).
-                // FIXME(#35705) remove this redirect.
                 if item_type == ItemType::Macro {
                     let redir_name = format!("{}.{}!.html", item_type, name);
                     let redir_dst = self.dst.join(redir_name);
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index ee297d3783e..189569683a9 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -738,7 +738,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
 /// reducing the number of actual writes to the file.
 ///
 /// ```no_run
-/// use std::fs::File;
+/// use std::fs::{self, File};
 /// use std::io::prelude::*;
 /// use std::io::LineWriter;
 ///
@@ -752,17 +752,30 @@ impl<W> fmt::Display for IntoInnerError<W> {
 ///     let file = File::create("poem.txt")?;
 ///     let mut file = LineWriter::new(file);
 ///
-///     for &byte in road_not_taken.iter() {
-///        file.write(&[byte]).unwrap();
-///     }
+///     file.write_all(b"I shall be telling this with a sigh")?;
+///
+///     // No bytes are written until a newline is encountered (or
+///     // the internal buffer is filled).
+///     assert_eq!(fs::read_to_string("poem.txt")?, "");
+///     file.write_all(b"\n")?;
+///     assert_eq!(
+///         fs::read_to_string("poem.txt")?,
+///         "I shall be telling this with a sigh\n",
+///     );
 ///
-///     // let's check we did the right thing.
-///     let mut file = File::open("poem.txt")?;
-///     let mut contents = String::new();
+///     // Write the rest of the poem.
+///     file.write_all(b"Somewhere ages and ages hence:
+/// Two roads diverged in a wood, and I -
+/// I took the one less traveled by,
+/// And that has made all the difference.")?;
 ///
-///     file.read_to_string(&mut contents)?;
+///     // The last line of the poem doesn't end in a newline, so
+///     // we have to flush or drop the `LineWriter` to finish
+///     // writing.
+///     file.flush()?;
 ///
-///     assert_eq!(contents.as_bytes(), &road_not_taken[..]);
+///     // Confirm the whole poem was written.
+///     assert_eq!(fs::read("poem.txt")?, &road_not_taken[..]);
 ///     Ok(())
 /// }
 /// ```
@@ -862,7 +875,7 @@ impl<W: Write> LineWriter<W> {
     ///
     /// The internal buffer is written out before returning the writer.
     ///
-    // # Errors
+    /// # Errors
     ///
     /// An `Err` will be returned if an error occurs while flushing the buffer.
     ///
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 0f60b5b3ee4..6b4bbdddf32 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -81,7 +81,7 @@ pub struct TcpStream(net_imp::TcpStream);
 /// }
 ///
 /// fn main() -> io::Result<()> {
-///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+///     let listener = TcpListener::bind("127.0.0.1:80")?;
 ///
 ///     // accept connections and process them serially
 ///     for stream in listener.incoming() {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 2ef90e3ec47..84b5f9659b5 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -284,7 +284,7 @@ declare_features! (
     // Allows #[link(..., cfg(..))]
     (active, link_cfg, "1.14.0", Some(37406), None),
 
-    (active, use_extern_macros, "1.15.0", Some(35896), None),
+    (active, use_extern_macros, "1.15.0", Some(35896), Some(Edition::Edition2018)),
 
     // `extern "ptx-*" fn()`
     (active, abi_ptx, "1.15.0", Some(38788), None),
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index c7076478332..1531f030127 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -602,6 +602,7 @@ pub enum CompilerDesugaringKind {
     /// `impl Trait` with `Foo`.
     ExistentialReturnType,
     Async,
+    ForLoop,
 }
 
 impl CompilerDesugaringKind {
@@ -612,6 +613,7 @@ impl CompilerDesugaringKind {
             CompilerDesugaringKind::QuestionMark => "?",
             CompilerDesugaringKind::Catch => "do catch",
             CompilerDesugaringKind::ExistentialReturnType => "existential type",
+            CompilerDesugaringKind::ForLoop => "for loop",
         })
     }
 }
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
index c89c0e4e758..3ec8b048b12 100644
--- a/src/test/debuginfo/type-names.rs
+++ b/src/test/debuginfo/type-names.rs
@@ -11,9 +11,6 @@
 // ignore-tidy-linelength
 // ignore-lldb
 // ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155
-// ignore-android: FIXME(#24958)
-// ignore-arm: FIXME(#24958)
-// ignore-aarch64: FIXME(#24958)
 
 // compile-flags:-g
 
diff --git a/src/test/ui/issue-20261.stderr b/src/test/ui/issue-20261.stderr
index a4a2aec8969..a7a7ea7c69b 100644
--- a/src/test/ui/issue-20261.stderr
+++ b/src/test/ui/issue-20261.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed
   --> $DIR/issue-20261.rs:14:11
    |
 LL |     for (ref i,) in [].iter() {
-   |         -------- consider giving `__next` a type
+   |                     --------- the element type for this iterator is not specified
 LL |         i.clone();
    |           ^^^^^ cannot infer type for `_`
    |
diff --git a/src/test/ui/issue-51116.rs b/src/test/ui/issue-51116.rs
new file mode 100644
index 00000000000..34217c6236c
--- /dev/null
+++ b/src/test/ui/issue-51116.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 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.
+
+fn main() {
+    let tiles = Default::default();
+    for row in &mut tiles {
+        for tile in row {
+            //~^ NOTE the element type for this iterator is not specified
+            *tile = 0;
+            //~^ ERROR type annotations needed
+            //~| NOTE cannot infer type for `_`
+            //~| NOTE type must be known at this point
+        }
+    }
+
+    let tiles: [[usize; 3]; 3] = tiles;
+}
diff --git a/src/test/ui/issue-51116.stderr b/src/test/ui/issue-51116.stderr
new file mode 100644
index 00000000000..0c38688340b
--- /dev/null
+++ b/src/test/ui/issue-51116.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-51116.rs:16:13
+   |
+LL |         for tile in row {
+   |                     --- the element type for this iterator is not specified
+LL |             //~^ NOTE the element type for this iterator is not specified
+LL |             *tile = 0;
+   |             ^^^^^ cannot infer type for `_`
+   |
+   = note: type must be known at this point
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.