From 63c471e10227944268ddf67973a584d68e314a8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 27 Sep 2018 15:50:17 -0700 Subject: [PATCH 01/37] rustc: Tweak filenames encoded into metadata This commit is a fix for #54408 where on nightly right now whenever generics are inlined the path name listed for the inlined function's debuginfo is a relative path to the cwd, which surely doesn't exist! Previously on beta/stable the debuginfo mentioned an absolute path which still didn't exist, but more predictably didn't exist. The change between stable/nightly is that nightly is now compiled with `--remap-path-prefix` to give a deterministic prefix to all rustc-generated paths in debuginfo. By using `--remap-path-prefix` the previous logic would recognize that the cwd was remapped, causing the original relative path name of the standard library to get emitted. If `--remap-path-prefix` *wasn't* passed in then the logic would create an absolute path name and then create a new source file entry. The fix in this commit is to apply the "recreate the source file entry with an absolute path" logic a bit more aggresively. If the source file's name was remapped then we don't touch it, but otherwise we always take the working dir (which may have been remapped) and then join it to the file to ensure that we process all relative file names as well. The end result is that the standard library should have an absolute path for all file names in debuginfo (using our `--remap-path-prefix` argument) as it does on stable after this patch. Closes #54408 --- src/librustc_metadata/encoder.rs | 42 ++++++++----------- .../auxiliary/xcrate-generic.rs | 16 +++++++ .../remap_path_prefix/xcrate-generic.rs | 25 +++++++++++ 3 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs create mode 100644 src/test/codegen/remap_path_prefix/xcrate-generic.rs diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c36ae02ab54e0..292bf1daee22f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -340,7 +340,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); - let (working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir.clone(); + let (working_dir, _cwd_remapped) = self.tcx.sess.working_dir.clone(); let adapted = all_source_files.iter() .filter(|source_file| { @@ -349,32 +349,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { !source_file.is_imported() }) .map(|source_file| { - // When exporting SourceFiles, we expand all paths to absolute - // paths because any relative paths are potentially relative to - // a wrong directory. - // However, if a path has been modified via - // `--remap-path-prefix` we assume the user has already set - // things up the way they want and don't touch the path values - // anymore. match source_file.name { + // This path of this SourceFile has been modified by + // path-remapping, so we use it verbatim (and avoid + // cloning the whole map in the process). + _ if source_file.name_was_remapped => source_file.clone(), + + // Otherwise expand all paths to absolute paths because + // any relative paths are potentially relative to a + // wrong directory. FileName::Real(ref name) => { - if source_file.name_was_remapped || - (name.is_relative() && working_dir_was_remapped) { - // This path of this SourceFile has been modified by - // path-remapping, so we use it verbatim (and avoid cloning - // the whole map in the process). - source_file.clone() - } else { - let mut adapted = (**source_file).clone(); - adapted.name = Path::new(&working_dir).join(name).into(); - adapted.name_hash = { - let mut hasher: StableHasher = StableHasher::new(); - adapted.name.hash(&mut hasher); - hasher.finish() - }; - Lrc::new(adapted) - } + let mut adapted = (**source_file).clone(); + adapted.name = Path::new(&working_dir).join(name).into(); + adapted.name_hash = { + let mut hasher: StableHasher = StableHasher::new(); + adapted.name.hash(&mut hasher); + hasher.finish() + }; + Lrc::new(adapted) }, + // expanded code, not from a file _ => source_file.clone(), } diff --git a/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs new file mode 100644 index 0000000000000..6c477a407812a --- /dev/null +++ b/src/test/codegen/remap_path_prefix/auxiliary/xcrate-generic.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength +// compile-flags: -g --remap-path-prefix={{cwd}}=/the/aux-cwd --remap-path-prefix={{src-base}}/remap_path_prefix/auxiliary=/the/aux-src + +#![crate_type = "lib"] + +pub fn foo() {} diff --git a/src/test/codegen/remap_path_prefix/xcrate-generic.rs b/src/test/codegen/remap_path_prefix/xcrate-generic.rs new file mode 100644 index 0000000000000..f206df9813165 --- /dev/null +++ b/src/test/codegen/remap_path_prefix/xcrate-generic.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-windows +// ignore-tidy-linelength +// compile-flags: -g -C metadata=foo -C no-prepopulate-passes +// aux-build:xcrate-generic.rs + +#![crate_type = "lib"] + +extern crate xcrate_generic; + +pub fn foo() { + xcrate_generic::foo::(); +} + +// Here we check that local debuginfo is mapped correctly. +// CHECK: !DIFile(filename: "/the/aux-src/xcrate-generic.rs", directory: "") From c514b627e4bea768fe8560b96ce585689d008017 Mon Sep 17 00:00:00 2001 From: Charles Hathaway Date: Wed, 10 Oct 2018 11:13:35 -0400 Subject: [PATCH 02/37] update tcp stream documentation --- src/libstd/net/tcp.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 75c7a3d928094..848570e75e71e 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -44,11 +44,10 @@ use time::Duration; /// use std::net::TcpStream; /// /// { -/// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); +/// let mut stream = TcpStream::connect("127.0.0.1:34254")?; /// -/// // ignore the Result -/// let _ = stream.write(&[1]); -/// let _ = stream.read(&mut [0; 128]); // ignore here too +/// stream.write(&[1])?; +/// stream.read(&mut [0; 128])?; /// } // the stream is closed here /// ``` #[stable(feature = "rust1", since = "1.0.0")] From 4530b8c56cb7c1e539472e09c1e2704f67814912 Mon Sep 17 00:00:00 2001 From: Charles Hathaway Date: Thu, 11 Oct 2018 15:35:48 -0400 Subject: [PATCH 03/37] Small changes to fix documentation auto compile issues --- src/libstd/net/tcp.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index 848570e75e71e..ad212a547579b 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -43,11 +43,12 @@ use time::Duration; /// use std::io::prelude::*; /// use std::net::TcpStream; /// -/// { +/// fn main() -> std::io::Result<()> { /// let mut stream = TcpStream::connect("127.0.0.1:34254")?; /// /// stream.write(&[1])?; /// stream.read(&mut [0; 128])?; +/// Ok(()) /// } // the stream is closed here /// ``` #[stable(feature = "rust1", since = "1.0.0")] From 7892257e3d6979ad1715a58f1efa3aa0d2a8605f Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 11 Sep 2018 12:41:56 +0100 Subject: [PATCH 04/37] Check for uninhabitedness instead of never --- src/librustc/cfg/construct.rs | 3 +- src/librustc/middle/liveness.rs | 6 +-- src/librustc/ty/sty.rs | 11 ++++++ src/librustc_codegen_llvm/mir/block.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 3 +- src/librustc_mir/build/expr/into.rs | 5 +-- src/librustc_mir/hair/pattern/check_match.rs | 11 +----- src/test/debuginfo/nil-enum.rs | 38 +++---------------- 8 files changed, 25 insertions(+), 54 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 6b9c0aac52e79..cbc0b7c5485c8 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -415,8 +415,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { args: I) -> CFGIndex { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); - // FIXME(canndrew): This is_never should probably be an is_uninhabited. - if self.tables.expr_ty(call_expr).is_never() { + if self.tables.expr_ty(call_expr).conservative_is_uninhabited() { self.add_unreachable_node() } else { ret diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 1b258a23462c7..299dda9fe7c09 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1197,8 +1197,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - // FIXME(canndrew): This is_never should really be an is_uninhabited - let succ = if self.tables.expr_ty(expr).is_never() { + let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() { self.s.exit_ln } else { succ @@ -1208,8 +1207,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - // FIXME(canndrew): This is_never should really be an is_uninhabited - let succ = if self.tables.expr_ty(expr).is_never() { + let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() { self.s.exit_ln } else { succ diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cc6e6b2861ecb..877eaa86f18c9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1504,6 +1504,17 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + pub fn conservative_is_uninhabited(&self) -> bool { + // Checks whether a type is definitely uninhabited. This is + // conservative: for some types that are uninhabited we return `false`, + // but we only return `true` for types that are definitely uninhabited. + match self.sty { + ty::Never => true, + ty::Adt(def, _) => def.variants.is_empty(), + _ => false + } + } + pub fn is_primitive(&self) -> bool { match self.sty { Bool | Char | Int(_) | Uint(_) | Float(_) => true, diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 5be176f75c96a..8bc61f4a61d43 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -463,7 +463,7 @@ impl FunctionCx<'a, 'll, 'tcx> { // we can do what we like. Here, we declare that transmuting // into an uninhabited type is impossible, so anything following // it must be unreachable. - assert_eq!(bx.cx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); + assert!(sig.output().conservative_is_uninhabited()); bx.unreachable(); } return; diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index e11f452e16be1..17da1f66d9f8a 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1419,8 +1419,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } None => { - // FIXME(canndrew): This is_never should probably be an is_uninhabited - if !sig.output().is_never() { + if !sig.output().conservative_is_uninhabited() { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 4f5ed34a46133..5b6d8913db6df 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -275,8 +275,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { exit_block.unit() } ExprKind::Call { ty, fun, args, from_hir_call } => { - // FIXME(canndrew): This is_never should probably be an is_uninhabited - let diverges = expr.ty.is_never(); + let diverges = expr.ty.conservative_is_uninhabited(); let intrinsic = match ty.sty { ty::FnDef(def_id, _) => { let f = ty.fn_sig(this.hir.tcx()); @@ -332,7 +331,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { func: fun, args, cleanup: Some(cleanup), - destination: if diverges { + destination: if expr.ty.conservative_is_uninhabited() { None } else { Some((destination.clone(), success)) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index f2ae5774da875..c696900866207 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { - self.conservative_is_uninhabited(pat_ty) + pat_ty.conservative_is_uninhabited() }; if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong @@ -257,15 +257,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { }) } - fn conservative_is_uninhabited(&self, scrutinee_ty: Ty<'tcx>) -> bool { - // "rustc-1.0-style" uncontentious uninhabitableness check - match scrutinee_ty.sty { - ty::Never => true, - ty::Adt(def, _) => def.variants.is_empty(), - _ => false - } - } - fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) { let module = self.tcx.hir.get_module_parent(pat.id); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs index ab9c7e2dd2758..27e8e9d17e82c 100644 --- a/src/test/debuginfo/nil-enum.rs +++ b/src/test/debuginfo/nil-enum.rs @@ -1,50 +1,24 @@ -// Copyright 2013-2014 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// NOTE Instantiating an empty enum is UB. This test may break in the future. - -// LLDB can't handle zero-sized values +// LLDB can't handle zero-sized values. // ignore-lldb - // compile-flags:-g // gdb-command:run -// gdb-command:print first +// gdb-command:print *first // gdbg-check:$1 = {} // gdbr-check:$1 = -// gdb-command:print second -// gdbg-check:$2 = {} -// gdbr-check:$2 = - #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] #![feature(maybe_uninit)] #![omit_gdb_pretty_printer_section] -use std::mem::MaybeUninit; - -enum ANilEnum {} -enum AnotherNilEnum {} +enum Void {} -// This test relies on gdbg printing the string "{}" for empty -// structs (which may change some time) -// The error from gdbr is expected since nil enums are not supposed to exist. fn main() { - unsafe { - let first: ANilEnum = MaybeUninit::uninitialized().into_inner(); - let second: AnotherNilEnum = MaybeUninit::uninitialized().into_inner(); + let first: *const Void = 1 as *const _; - zzz(); // #break - } + zzz(); // #break } -fn zzz() {()} +fn zzz() {} From e6500815230a6bd5aa1af9710677bc3a0e0725c5 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 11 Sep 2018 13:04:21 +0100 Subject: [PATCH 05/37] Make uninhabitedness checking more intelligent --- src/librustc/cfg/construct.rs | 2 +- src/librustc/middle/liveness.rs | 4 +-- src/librustc/ty/sty.rs | 32 +++++++++++++++++-- src/librustc_codegen_llvm/mir/block.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 2 +- 7 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index cbc0b7c5485c8..2c52697d56d27 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -415,7 +415,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { args: I) -> CFGIndex { let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let ret = self.straightline(call_expr, func_or_rcvr_exit, args); - if self.tables.expr_ty(call_expr).conservative_is_uninhabited() { + if self.tables.expr_ty(call_expr).conservative_is_uninhabited(self.tcx) { self.add_unreachable_node() } else { ret diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 299dda9fe7c09..9e566658dc7bd 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1197,7 +1197,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() { + let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited(self.ir.tcx) { self.s.exit_ln } else { succ @@ -1207,7 +1207,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited() { + let succ = if self.tables.expr_ty(expr).conservative_is_uninhabited(self.ir.tcx) { self.s.exit_ln } else { succ diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 877eaa86f18c9..ed63617ed0323 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1504,14 +1504,40 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn conservative_is_uninhabited(&self) -> bool { + pub fn conservative_is_uninhabited(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { // Checks whether a type is definitely uninhabited. This is // conservative: for some types that are uninhabited we return `false`, // but we only return `true` for types that are definitely uninhabited. match self.sty { ty::Never => true, - ty::Adt(def, _) => def.variants.is_empty(), - _ => false + ty::Adt(def, _) => { + // Any ADT is uninhabited if: + // (a) It has no variants (i.e. an empty `enum`); + // (b) Each of its variants (a single one in the case of a `struct`) has at least + // one uninhabited field. + def.variants.iter().all(|var| { + var.fields.iter().any(|field| { + tcx.type_of(field.did).conservative_is_uninhabited(tcx) + }) + }) + } + ty::Tuple(tys) => tys.iter().any(|ty| ty.conservative_is_uninhabited(tcx)), + ty::Array(ty, len) => { + match len.val.try_to_scalar() { + // If the array is definitely non-empty, it's uninhabited if + // the type of its elements is uninhabited. + Some(n) if !n.is_null() => ty.conservative_is_uninhabited(tcx), + _ => false + } + } + ty::Ref(..) => { + // Though references to uninhabited types are trivially uninhabited + // theoretically, null references are permitted in unsafe code (as + // long as the value is not dereferenced), so we treat all references + // as inhabited. + false + } + _ => false, } } diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 8bc61f4a61d43..c7ab9927446ad 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -463,7 +463,7 @@ impl FunctionCx<'a, 'll, 'tcx> { // we can do what we like. Here, we declare that transmuting // into an uninhabited type is impossible, so anything following // it must be unreachable. - assert!(sig.output().conservative_is_uninhabited()); + assert!(sig.output().conservative_is_uninhabited(bx.tcx())); bx.unreachable(); } return; diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 17da1f66d9f8a..c0bf16a3e0f90 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1419,7 +1419,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } None => { - if !sig.output().conservative_is_uninhabited() { + if !sig.output().conservative_is_uninhabited(self.tcx()) { span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 5b6d8913db6df..85a1905db17c6 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { func: fun, args, cleanup: Some(cleanup), - destination: if expr.ty.conservative_is_uninhabited() { + destination: if expr.ty.conservative_is_uninhabited(this.hir.tcx()) { None } else { Some((destination.clone(), success)) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index c696900866207..0335947a868b2 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { - pat_ty.conservative_is_uninhabited() + pat_ty.conservative_is_uninhabited(self.tcx) }; if !scrutinee_is_uninhabited { // We know the type is inhabited, so this must be wrong From 8223380837c8b5cb9ccffdeb489af774e7a07474 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 11 Sep 2018 14:55:12 +0100 Subject: [PATCH 06/37] Update uninhabited matches tests --- .../uninhabited-matches-feature-gated.rs | 4 +-- .../uninhabited-matches-feature-gated.stderr | 26 +------------------ 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs index 1d3f8ff12d865..a3b99deac233b 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.rs @@ -20,10 +20,10 @@ fn main() { let _ = match x {}; //~ ERROR non-exhaustive let x: (Void,) = unsafe { std::mem::uninitialized() }; - let _ = match x {}; //~ ERROR non-exhaustive + let _ = match x {}; // okay let x: [Void; 1] = unsafe { std::mem::uninitialized() }; - let _ = match x {}; //~ ERROR non-exhaustive + let _ = match x {}; // okay let x: &[Void] = unsafe { std::mem::uninitialized() }; let _ = match x { //~ ERROR non-exhaustive diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index d86ebda027efb..abaad8958dbe6 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -16,30 +16,6 @@ help: Please ensure that all possible cases are being handled; possibly adding w LL | let _ = match x {}; //~ ERROR non-exhaustive | ^ -error[E0004]: non-exhaustive patterns: type (Void,) is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:23:19 - | -LL | let _ = match x {}; //~ ERROR non-exhaustive - | ^ - | -help: Please ensure that all possible cases are being handled; possibly adding wildcards or more match arms. - --> $DIR/uninhabited-matches-feature-gated.rs:23:19 - | -LL | let _ = match x {}; //~ ERROR non-exhaustive - | ^ - -error[E0004]: non-exhaustive patterns: type [Void; 1] is non-empty - --> $DIR/uninhabited-matches-feature-gated.rs:26:19 - | -LL | let _ = match x {}; //~ ERROR non-exhaustive - | ^ - | -help: Please ensure that all possible cases are being handled; possibly adding wildcards or more match arms. - --> $DIR/uninhabited-matches-feature-gated.rs:26:19 - | -LL | let _ = match x {}; //~ ERROR non-exhaustive - | ^ - error[E0004]: non-exhaustive patterns: `&[_]` not covered --> $DIR/uninhabited-matches-feature-gated.rs:29:19 | @@ -58,7 +34,7 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered LL | let Ok(x) = x; | ^^^^^ pattern `Err(_)` not covered -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors occurred: E0004, E0005. For more information about an error, try `rustc --explain E0004`. From 55d2607a60f40a4ece5bab41ef41b760765d7ce8 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 14 Sep 2018 22:46:13 +0100 Subject: [PATCH 07/37] Address comments --- src/librustc/ty/sty.rs | 6 +++++- src/librustc_codegen_llvm/mir/block.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ed63617ed0323..8c43946ca20fb 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1510,8 +1510,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { // but we only return `true` for types that are definitely uninhabited. match self.sty { ty::Never => true, + ty::Adt(def, _) if def.is_union() => { + // For now, `union`s are never considered uninhabited. + false + } ty::Adt(def, _) => { - // Any ADT is uninhabited if: + // Any ADT is uninhabited if either: // (a) It has no variants (i.e. an empty `enum`); // (b) Each of its variants (a single one in the case of a `struct`) has at least // one uninhabited field. diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index c7ab9927446ad..5be176f75c96a 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -463,7 +463,7 @@ impl FunctionCx<'a, 'll, 'tcx> { // we can do what we like. Here, we declare that transmuting // into an uninhabited type is impossible, so anything following // it must be unreachable. - assert!(sig.output().conservative_is_uninhabited(bx.tcx())); + assert_eq!(bx.cx.layout_of(sig.output()).abi, layout::Abi::Uninhabited); bx.unreachable(); } return; From 47e34a29c50a9f33ba9203643e067fbf0f558ee3 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 20 Sep 2018 20:22:02 +0100 Subject: [PATCH 08/37] Fix Ref inhabitedness comment --- src/librustc/ty/sty.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8c43946ca20fb..b3c0bbd8c14e8 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1535,10 +1535,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } ty::Ref(..) => { - // Though references to uninhabited types are trivially uninhabited - // theoretically, null references are permitted in unsafe code (as - // long as the value is not dereferenced), so we treat all references - // as inhabited. + // References to uninitialised memory is valid for any type, including + // uninhabited types, in unsafe code, so we treat all references as + // inhabited. false } _ => false, From 7bb2980f254118afba9735f6dc53d99039256378 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 16 Oct 2018 16:31:41 +0100 Subject: [PATCH 09/37] Fix handling of divergent dicriminants --- src/librustc_mir/build/expr/into.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 85a1905db17c6..bf0a1e583dff5 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -275,7 +275,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { exit_block.unit() } ExprKind::Call { ty, fun, args, from_hir_call } => { - let diverges = expr.ty.conservative_is_uninhabited(); let intrinsic = match ty.sty { ty::FnDef(def_id, _) => { let f = ty.fn_sig(this.hir.tcx()); From 6c235cf7556ad2b5aaa0d90177532c0be9b84f2b Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 16 Oct 2018 21:16:48 +0100 Subject: [PATCH 10/37] Update const eval uninhabited messages --- src/test/ui/consts/const-eval/ub-uninhabit.rs | 4 ++-- .../ui/consts/const-eval/ub-uninhabit.stderr | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index 99305beee5281..2f00b4bf837d7 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -16,13 +16,13 @@ use std::mem; enum Bar {} const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; -//~^ ERROR this constant likely exhibits undefined behavior +//~^ ERROR this constant cannot be used const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR this constant likely exhibits undefined behavior const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; -//~^ ERROR this constant likely exhibits undefined behavior +//~^ ERROR this constant cannot be used fn main() { } diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 136d5f2919946..629a6ee9f33f3 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,10 +1,12 @@ -error[E0080]: this constant likely exhibits undefined behavior +error: this constant cannot be used --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^^ + | | + | entered unreachable code | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + = note: #[deny(const_err)] on by default error[E0080]: this constant likely exhibits undefined behavior --> $DIR/ub-uninhabit.rs:21:1 @@ -14,13 +16,13 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error[E0080]: this constant likely exhibits undefined behavior +error: this constant cannot be used --> $DIR/ub-uninhabit.rs:24:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0] - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^^ + | | + | entered unreachable code error: aborting due to 3 previous errors From 08306507ee1ca4cf7f0a9227ba37d8de02871d55 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 16 Oct 2018 21:36:29 +0100 Subject: [PATCH 11/37] Nonempty arrays of uninhabited arrays are Abi::Uninhabited --- src/librustc/ty/layout.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 05d4aeb6ddec4..3bc63463b9abb 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -555,13 +555,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; + let abi = if size != Size::ZERO && ty.conservative_is_uninhabited(tcx) { + Abi::Uninhabited + } else { + Abi::Aggregate { sized: true } + }; + tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: 0 }, fields: FieldPlacement::Array { stride: element.size, count }, - abi: Abi::Aggregate { sized: true }, + abi, align: element.align, size }) From 7e14ffb3622848d8cd481482f943dec235afb797 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 16 Oct 2018 21:36:43 +0100 Subject: [PATCH 12/37] conservative_is_uninhabited implies abi.is_uninhabited --- src/librustc/ty/layout.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 3bc63463b9abb..041efd506c5d1 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -190,7 +190,14 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::tls::enter_context(&icx, |_| { let cx = LayoutCx { tcx, param_env }; - cx.layout_raw_uncached(ty) + let layout = cx.layout_raw_uncached(ty); + // Type-level uninhabitedness should always imply ABI uninhabitedness. + if let Ok(layout) = layout { + if ty.conservative_is_uninhabited(tcx) { + assert!(layout.abi.is_uninhabited()); + } + } + layout }) }) } @@ -205,12 +212,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { #[derive(Copy, Clone)] pub struct LayoutCx<'tcx, C> { pub tcx: C, - pub param_env: ty::ParamEnv<'tcx> + pub param_env: ty::ParamEnv<'tcx>, } impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { - fn layout_raw_uncached(self, ty: Ty<'tcx>) - -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { + fn layout_raw_uncached(self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { let tcx = self.tcx; let param_env = self.param_env; let dl = self.data_layout(); From a75f7810a7118e3bb103058091c1d6414b515786 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 17 Oct 2018 16:31:22 +0200 Subject: [PATCH 13/37] AST-borrowck: add separate mem category for thread-locals, as they are not quite rvalues (and of course they are not quite statics either). Namely, they *do* have a restricted region (like rvalues), but they also cannot be moved out of (like statics). --- src/librustc/middle/mem_categorization.rs | 29 ++++++++++++++----- src/librustc_borrowck/borrowck/check_loans.rs | 1 + .../borrowck/gather_loans/gather_moves.rs | 1 + .../borrowck/gather_loans/lifetime.rs | 2 ++ .../borrowck/gather_loans/move_error.rs | 7 ++++- .../borrowck/gather_loans/restrictions.rs | 6 ++++ src/librustc_borrowck/borrowck/mod.rs | 1 + src/librustc_passes/rvalue_promotion.rs | 1 + src/librustc_typeck/check/regionck.rs | 1 + src/librustc_typeck/check/upvar.rs | 2 ++ 10 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 13e6f7a4c745a..9d3f37bc36a9d 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -93,6 +93,7 @@ use util::nodemap::ItemLocalSet; #[derive(Clone, Debug, PartialEq)] pub enum Categorization<'tcx> { Rvalue(ty::Region<'tcx>), // temporary val, argument is its scope + ThreadLocal(ty::Region<'tcx>), // value that cannot move, but still restricted in scope StaticItem, Upvar(Upvar), // upvar referenced by closure env Local(ast::NodeId), // local variable @@ -268,6 +269,7 @@ impl<'tcx> cmt_<'tcx> { Categorization::Deref(ref base_cmt, _) => { base_cmt.immutability_blame() } + Categorization::ThreadLocal(..) | Categorization::StaticItem => { // Do we want to do something here? None @@ -715,17 +717,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Static(def_id, mutbl) => { - // `#[thread_local]` statics may not outlive the current function. - for attr in &self.tcx.get_attrs(def_id)[..] { - if attr.check_name("thread_local") { - return Ok(self.cat_rvalue_node(hir_id, span, expr_ty)); - } - } + // `#[thread_local]` statics may not outlive the current function, but + // they also cannot be moved out of. + let is_thread_local = self.tcx.get_attrs(def_id)[..] + .iter() + .any(|attr| attr.check_name("thread_local")); + + let cat = if is_thread_local { + let re = self.temporary_scope(hir_id.local_id); + Categorization::ThreadLocal(re) + } else { + Categorization::StaticItem + }; Ok(cmt_ { hir_id, - span:span, - cat:Categorization::StaticItem, + span, + cat, mutbl: if mutbl { McDeclared } else { McImmutable}, ty:expr_ty, note: NoteNone @@ -1408,6 +1416,7 @@ impl<'tcx> cmt_<'tcx> { match self.cat { Categorization::Rvalue(..) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Deref(_, UnsafePtr(..)) | Categorization::Deref(_, BorrowedPtr(..)) | @@ -1439,6 +1448,7 @@ impl<'tcx> cmt_<'tcx> { } Categorization::Rvalue(..) | + Categorization::ThreadLocal(..) | Categorization::Local(..) | Categorization::Upvar(..) | Categorization::Deref(_, UnsafePtr(..)) => { // yes, it's aliasable, but... @@ -1485,6 +1495,9 @@ impl<'tcx> cmt_<'tcx> { Categorization::StaticItem => { "static item".into() } + Categorization::ThreadLocal(..) => { + "thread-local static item".into() + } Categorization::Rvalue(..) => { "non-place".into() } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 34ee03b895f9f..033ed8008edc2 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -377,6 +377,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // by-move upvars, which is local data for generators Categorization::Upvar(..) => true, + Categorization::ThreadLocal(region) | Categorization::Rvalue(region) => { // Rvalues promoted to 'static are no longer local if let RegionKind::ReStatic = *region { diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index ffc4fbfb4c9cb..7bb5f411752fe 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -177,6 +177,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, match cmt.cat { Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::UnsafePtr(..)) | + Categorization::ThreadLocal(..) | Categorization::StaticItem => { Some(cmt.clone()) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index c9dcc0d9fa266..6ef5d65d10dca 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -70,6 +70,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { match cmt.cat { Categorization::Rvalue(..) | + Categorization::ThreadLocal(..) | Categorization::Local(..) | // L-Local Categorization::Upvar(..) | Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed @@ -105,6 +106,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { //! rooting etc, and presuming `cmt` is not mutated. match cmt.cat { + Categorization::ThreadLocal(temp_scope) | Categorization::Rvalue(temp_scope) => { temp_scope } diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index b29ab55f9ba78..e1a4473539c8c 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -145,6 +145,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, match move_from.cat { Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::UnsafePtr(..)) | + Categorization::Deref(_, mc::Unique) | + Categorization::ThreadLocal(..) | Categorization::StaticItem => { bccx.cannot_move_out_of( move_from.span, &move_from.descriptive_string(bccx.tcx), Origin::Ast) @@ -166,7 +168,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>, } } } - _ => { + + Categorization::Rvalue(..) | + Categorization::Local(..) | + Categorization::Upvar(..) => { span_bug!(move_from.span, "this path should not cause illegal move"); } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index d9784cc2177fd..52c7ebb4beb02 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -70,6 +70,12 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { RestrictionResult::Safe } + Categorization::ThreadLocal(..) => { + // Thread-locals are statics that have a scope, with + // no underlying structure to provide restrictions. + RestrictionResult::Safe + } + Categorization::Local(local_id) => { // R-Variable, locally declared let lp = new_lp(LpVar(local_id)); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 0ef0d284770f5..d56eb188ccd2d 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -520,6 +520,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option { (None, false) } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 5e9169e86a98d..ca58239df8eac 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -663,6 +663,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { let mut cur = cmt; loop { match cur.cat { + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) => { if loan_cause == euv::MatchDiscriminant { // Ignore the dummy immutable borrow created by EUV. diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 80b4ba6240d33..212ee2698e012 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1243,6 +1243,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { | Categorization::StaticItem | Categorization::Upvar(..) | Categorization::Local(..) + | Categorization::ThreadLocal(..) | Categorization::Rvalue(..) => { // These are all "base cases" with independent lifetimes // that are not subject to inference diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 99effce4ee08d..df994ad9e55c4 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -401,6 +401,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => { @@ -431,6 +432,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Deref(_, mc::UnsafePtr(..)) | Categorization::StaticItem | + Categorization::ThreadLocal(..) | Categorization::Rvalue(..) | Categorization::Local(_) | Categorization::Upvar(..) => {} From e6e4fe6209d0b31c3d119fb75744531f8fad2af8 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 17 Oct 2018 16:32:03 +0200 Subject: [PATCH 14/37] Update existing tests and .stderr files to reflect introduction of thread-local mem category. --- ...borrowck-thread-local-static-borrow-outlives-fn.ast.stderr | 4 ++-- src/test/ui/issues/issue-17954.rs | 2 +- src/test/ui/issues/issue-17954.stderr | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr index 27e0dba5095b2..505bcfb1e6e14 100644 --- a/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr +++ b/src/test/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.ast.stderr @@ -2,9 +2,9 @@ error[E0597]: borrowed value does not live long enough --> $DIR/borrowck-thread-local-static-borrow-outlives-fn.rs:21:21 | LL | assert_static(&FOO); //[ast]~ ERROR [E0597] - | ^^^ - temporary value only lives until here + | ^^^ - borrowed value only lives until here | | - | temporary value does not live long enough + | borrowed value does not live long enough | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/issues/issue-17954.rs b/src/test/ui/issues/issue-17954.rs index ce554a7254812..5f003436951ce 100644 --- a/src/test/ui/issues/issue-17954.rs +++ b/src/test/ui/issues/issue-17954.rs @@ -23,4 +23,4 @@ fn main() { println!("{}", a); }); } -//~^ NOTE temporary value only lives until here +//~^ NOTE borrowed value only lives until here diff --git a/src/test/ui/issues/issue-17954.stderr b/src/test/ui/issues/issue-17954.stderr index 76858a9b097b2..020e544ad10ff 100644 --- a/src/test/ui/issues/issue-17954.stderr +++ b/src/test/ui/issues/issue-17954.stderr @@ -2,10 +2,10 @@ error[E0597]: borrowed value does not live long enough --> $DIR/issue-17954.rs:17:14 | LL | let a = &FOO; - | ^^^ temporary value does not live long enough + | ^^^ borrowed value does not live long enough ... LL | } - | - temporary value only lives until here + | - borrowed value only lives until here | = note: borrowed value must be valid for the static lifetime... From 1d46ce5a7229111850e2619bf297a0561b878cec Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 17 Oct 2018 16:32:43 +0200 Subject: [PATCH 15/37] Add regression test for issue 47215. --- .../issue-47215-ice-from-drop-elab.nll.stderr | 12 +++++++++++ .../issue-47215-ice-from-drop-elab.rs | 20 +++++++++++++++++++ .../issue-47215-ice-from-drop-elab.stderr | 12 +++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr create mode 100644 src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs create mode 100644 src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr new file mode 100644 index 0000000000000..255eb757a4989 --- /dev/null +++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.nll.stderr @@ -0,0 +1,12 @@ +error[E0507]: cannot move out of static item + --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21 + | +LL | let mut x = X; //~ ERROR cannot move out of thread-local static item [E0507] + | ^ + | | + | cannot move out of static item + | help: consider borrowing here: `&X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs new file mode 100644 index 0000000000000..670c6bb869d59 --- /dev/null +++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.rs @@ -0,0 +1,20 @@ +// rust-lang/rust#47215: at one time, the compiler categorized +// thread-local statics as a temporary rvalue, as a way to enforce +// that they are only valid for a given lifetime. +// +// The problem with this is that you cannot move out of static items, +// but you *can* move temporary rvalues. I.e., the categorization +// above only solves half of the problem presented by thread-local +// statics. + +#![feature(thread_local)] + +#[thread_local] +static mut X: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT; + +fn main() { + unsafe { + let mut x = X; //~ ERROR cannot move out of thread-local static item [E0507] + let _y = x.get_mut(); + } +} diff --git a/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr new file mode 100644 index 0000000000000..219a1fd2e7727 --- /dev/null +++ b/src/test/ui/borrowck/issue-47215-ice-from-drop-elab.stderr @@ -0,0 +1,12 @@ +error[E0507]: cannot move out of thread-local static item + --> $DIR/issue-47215-ice-from-drop-elab.rs:17:21 + | +LL | let mut x = X; //~ ERROR cannot move out of thread-local static item [E0507] + | ^ + | | + | cannot move out of thread-local static item + | help: consider using a reference instead: `&X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. From 1cf94f5e5201def3e47d3f41bf161551ad96be7a Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 18 Oct 2018 16:58:10 +0100 Subject: [PATCH 16/37] Use unions for uninhabitedness checking rather than mem::transmute --- src/librustc/ty/layout.rs | 2 +- src/test/ui/consts/const-eval/ub-uninhabit.rs | 26 +++++++------------ .../ui/consts/const-eval/ub-uninhabit.stderr | 26 +++++++++---------- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 041efd506c5d1..f40200fff018a 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -561,7 +561,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let size = element.size.checked_mul(count, dl) .ok_or(LayoutError::SizeOverflow(ty))?; - let abi = if size != Size::ZERO && ty.conservative_is_uninhabited(tcx) { + let abi = if count != 0 && ty.conservative_is_uninhabited(tcx) { Abi::Uninhabited } else { Abi::Aggregate { sized: true } diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index 2f00b4bf837d7..733de2726632d 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -1,13 +1,3 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - #![feature(const_transmute)] use std::mem; @@ -15,14 +5,18 @@ use std::mem; #[derive(Copy, Clone)] enum Bar {} -const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; -//~^ ERROR this constant cannot be used +union TransmuteUnion { + a: A, + b: B, +} + +const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; +//~^ ERROR this constant likely exhibits undefined behavior const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR this constant likely exhibits undefined behavior -const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; -//~^ ERROR this constant cannot be used +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; +//~^ ERROR this constant likely exhibits undefined behavior -fn main() { -} +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 629a6ee9f33f3..62e6ff2c7bd5b 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,28 +1,26 @@ -error: this constant cannot be used - --> $DIR/ub-uninhabit.rs:18:1 +error[E0080]: this constant likely exhibits undefined behavior + --> $DIR/ub-uninhabit.rs:13:1 | -LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^^ - | | - | entered unreachable code +LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type | - = note: #[deny(const_err)] on by default + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: this constant likely exhibits undefined behavior - --> $DIR/ub-uninhabit.rs:21:1 + --> $DIR/ub-uninhabit.rs:16:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error: this constant cannot be used - --> $DIR/ub-uninhabit.rs:24:1 +error[E0080]: this constant likely exhibits undefined behavior + --> $DIR/ub-uninhabit.rs:19:1 | -LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^^ - | | - | entered unreachable code +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error: aborting due to 3 previous errors From aa0875a93ddb9c4a9f8158e8405fef61806040bb Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 19 Oct 2018 15:09:07 +0100 Subject: [PATCH 17/37] Improve `conservative_is_uninhabited` comment --- src/librustc/ty/sty.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index b3c0bbd8c14e8..e017d3dd6df8e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1504,10 +1504,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } + /// Checks whether a type is definitely uninhabited. This is + /// conservative: for some types that are uninhabited we return `false`, + /// but we only return `true` for types that are definitely uninhabited. + /// `ty.conservative_is_uninhabited` implies that any value of type `ty` + /// will be `Abi::Uninhabited`. pub fn conservative_is_uninhabited(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { - // Checks whether a type is definitely uninhabited. This is - // conservative: for some types that are uninhabited we return `false`, - // but we only return `true` for types that are definitely uninhabited. + // FIXME(varkor): we can make this less conversative by substituting concrete + // type arguments. match self.sty { ty::Never => true, ty::Adt(def, _) if def.is_union() => { From 655f9d8e2183c71e957c4cb43e4819bad4d3d037 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Oct 2018 14:45:08 +0200 Subject: [PATCH 18/37] Move cg_llvm::back::linker to cg_utils --- src/Cargo.lock | 2 + src/librustc_codegen_llvm/back/archive.rs | 24 +--------- src/librustc_codegen_llvm/back/link.rs | 7 +-- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 6 +-- src/librustc_codegen_llvm/lib.rs | 30 ++---------- src/librustc_codegen_utils/Cargo.toml | 2 + .../command.rs | 0 src/librustc_codegen_utils/lib.rs | 47 +++++++++++++++++++ .../back => librustc_codegen_utils}/linker.rs | 27 ++++++----- .../symbol_export.rs | 2 +- 11 files changed, 82 insertions(+), 67 deletions(-) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/command.rs (100%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/linker.rs (98%) rename src/{librustc_codegen_llvm/back => librustc_codegen_utils}/symbol_export.rs (99%) diff --git a/src/Cargo.lock b/src/Cargo.lock index 52314b0ac8998..c1dc24ee2425d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2137,11 +2137,13 @@ dependencies = [ "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_allocator 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", "rustc_metadata_utils 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", + "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index af9efc6d7c417..ce4cb1ea3a042 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -52,28 +52,6 @@ enum Addition { }, } -pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) - -> PathBuf { - // On Windows, static libraries sometimes show up as libfoo.a and other - // times show up as foo.lib - let oslibname = format!("{}{}{}", - sess.target.target.options.staticlib_prefix, - name, - sess.target.target.options.staticlib_suffix); - let unixlibname = format!("lib{}.a", name); - - for path in search_paths { - debug!("looking for {} inside {:?}", name, path); - let test = path.join(&oslibname); - if test.exists() { return test } - if oslibname != unixlibname { - let test = path.join(&unixlibname); - if test.exists() { return test } - } - } - sess.fatal(&format!("could not find native static library `{}`, \ - perhaps an -L flag is missing?", name)); -} fn is_relevant_child(c: &Child) -> bool { match c.name() { @@ -128,7 +106,7 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. pub fn add_native_library(&mut self, name: &str) { - let location = find_library(name, &self.config.lib_search_paths, + let location = ::rustc_codegen_utils::find_library(name, &self.config.lib_search_paths, self.config.sess); self.add_archive(&location, |_| false).unwrap_or_else(|e| { self.config.sess.fatal(&format!("failed to add native library {}: {}", diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 9fac343b846e4..34679368f2625 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -12,8 +12,6 @@ use back::wasm; use cc::windows_registry; use super::archive::{ArchiveBuilder, ArchiveConfig}; use super::bytecode::RLIB_BYTECODE_EXTENSION; -use super::linker::Linker; -use super::command::Command; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; @@ -31,6 +29,8 @@ use rustc::hir::def_id::CrateNum; use tempfile::{Builder as TempFileBuilder, TempDir}; use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor}; use rustc_data_structures::fx::FxHashSet; +use rustc_codegen_utils::linker::Linker; +use rustc_codegen_utils::command::Command; use context::get_reloc_model; use llvm; @@ -701,7 +701,8 @@ fn link_natively(sess: &Session, } { - let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor); + let target_cpu = ::llvm_util::target_cpu(sess); + let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu); link_args(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 3ac22f4eaef65..69204715f370f 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -9,7 +9,6 @@ // except according to those terms. use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION}; -use back::symbol_export; use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write::{self, DiagnosticHandlers, pre_lto_bitcode_filename}; use errors::{FatalError, Handler}; @@ -24,6 +23,7 @@ use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config::{self, Lto}; use rustc::util::common::time_ext; use rustc_data_structures::fx::FxHashMap; +use rustc_codegen_utils::symbol_export; use time_graph::Timeline; use {ModuleCodegen, ModuleLlvm, ModuleKind}; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 02ef690b94233..cc4a3d2a85165 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -12,9 +12,6 @@ use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer, SerializedModule}; use back::link::{self, get_linker, remove}; -use back::command::Command; -use back::linker::LinkerInfo; -use back::symbol_export::ExportedSymbols; use base; use consts; use memmap; @@ -38,6 +35,9 @@ use rustc::util::common::{time_ext, time_depth, set_time_depth, print_time_passe use rustc_fs_util::{path2cstr, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::svh::Svh; +use rustc_codegen_utils::command::Command; +use rustc_codegen_utils::linker::LinkerInfo; +use rustc_codegen_utils::symbol_export::ExportedSymbols; use errors::{self, Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId}; use errors::emitter::{Emitter}; use syntax::attr; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 63a8ab077e5ae..f64cf0c7364dd 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -71,7 +71,6 @@ use back::bytecode::RLIB_BYTECODE_EXTENSION; pub use llvm_util::target_features; use std::any::Any; -use std::path::{PathBuf}; use std::sync::mpsc; use rustc_data_structures::sync::Lrc; @@ -87,20 +86,17 @@ use rustc::util::time_graph; use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::util::profiling::ProfileCategory; use rustc_mir::monomorphize; +use rustc_codegen_utils::{CompiledModule, ModuleKind}; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::svh::Svh; mod diagnostics; mod back { - pub use rustc_codegen_utils::symbol_names; mod archive; pub mod bytecode; - mod command; - pub mod linker; pub mod link; pub mod lto; - pub mod symbol_export; pub mod write; mod rpath; pub mod wasm; @@ -194,14 +190,14 @@ impl CodegenBackend for LlvmCodegenBackend { } fn provide(&self, providers: &mut ty::query::Providers) { - back::symbol_names::provide(providers); - back::symbol_export::provide(providers); + rustc_codegen_utils::symbol_export::provide(providers); + rustc_codegen_utils::symbol_names::provide(providers); base::provide(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers) { - back::symbol_export::provide_extern(providers); + rustc_codegen_utils::symbol_export::provide_extern(providers); base::provide_extern(providers); attributes::provide_extern(providers); } @@ -281,13 +277,6 @@ struct CachedModuleCodegen { source: WorkProduct, } -#[derive(Copy, Clone, Debug, PartialEq)] -enum ModuleKind { - Regular, - Metadata, - Allocator, -} - impl ModuleCodegen { fn into_compiled_module(self, emit_obj: bool, @@ -321,15 +310,6 @@ impl ModuleCodegen { } } -#[derive(Debug)] -struct CompiledModule { - name: String, - kind: ModuleKind, - object: Option, - bytecode: Option, - bytecode_compressed: Option, -} - struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, @@ -377,7 +357,7 @@ struct CodegenResults { crate_hash: Svh, metadata: rustc::middle::cstore::EncodedMetadata, windows_subsystem: Option, - linker_info: back::linker::LinkerInfo, + linker_info: rustc_codegen_utils::linker::LinkerInfo, crate_info: CrateInfo, } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index a1f4a323f849e..3a09e8e4b5606 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,9 +13,11 @@ test = false flate2 = "1.0" log = "0.4" +serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } +rustc_allocator = { path = "../librustc_allocator" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } diff --git a/src/librustc_codegen_llvm/back/command.rs b/src/librustc_codegen_utils/command.rs similarity index 100% rename from src/librustc_codegen_llvm/back/command.rs rename to src/librustc_codegen_utils/command.rs diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 03b3b20a4e772..89cf19d047216 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -30,8 +30,10 @@ extern crate flate2; #[macro_use] extern crate log; +extern crate serialize; #[macro_use] extern crate rustc; +extern crate rustc_allocator; extern crate rustc_target; extern crate rustc_mir; extern crate rustc_incremental; @@ -40,10 +42,16 @@ extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; extern crate rustc_metadata_utils; +use std::path::PathBuf; + +use rustc::session::Session; use rustc::ty::TyCtxt; +pub mod command; pub mod link; +pub mod linker; pub mod codegen_backend; +pub mod symbol_export; pub mod symbol_names; pub mod symbol_names_test; @@ -61,4 +69,43 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { } } +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum ModuleKind { + Regular, + Metadata, + Allocator, +} + +#[derive(Debug)] +pub struct CompiledModule { + pub name: String, + pub kind: ModuleKind, + pub object: Option, + pub bytecode: Option, + pub bytecode_compressed: Option, +} + +pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session) + -> PathBuf { + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let oslibname = format!("{}{}{}", + sess.target.target.options.staticlib_prefix, + name, + sess.target.target.options.staticlib_suffix); + let unixlibname = format!("lib{}.a", name); + + for path in search_paths { + debug!("looking for {} inside {:?}", name, path); + let test = path.join(&oslibname); + if test.exists() { return test } + if oslibname != unixlibname { + let test = path.join(&unixlibname); + if test.exists() { return test } + } + } + sess.fatal(&format!("could not find native static library `{}`, \ + perhaps an -L flag is missing?", name)); +} + __build_diagnostic_array! { librustc_codegen_utils, DIAGNOSTICS } diff --git a/src/librustc_codegen_llvm/back/linker.rs b/src/librustc_codegen_utils/linker.rs similarity index 98% rename from src/librustc_codegen_llvm/back/linker.rs rename to src/librustc_codegen_utils/linker.rs index e18c8b9dec463..c1f41fd509a14 100644 --- a/src/librustc_codegen_llvm/back/linker.rs +++ b/src/librustc_codegen_utils/linker.rs @@ -15,9 +15,7 @@ use std::io::prelude::*; use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; -use back::archive; -use back::command::Command; -use back::symbol_export; +use command::Command; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; use rustc::middle::dependency_format::Linkage; use rustc::session::Session; @@ -26,7 +24,6 @@ use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use serialize::{json, Encoder}; -use llvm_util; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. @@ -43,10 +40,13 @@ impl LinkerInfo { } } - pub fn to_linker<'a>(&'a self, - cmd: Command, - sess: &'a Session, - flavor: LinkerFlavor) -> Box { + pub fn to_linker<'a>( + &'a self, + cmd: Command, + sess: &'a Session, + flavor: LinkerFlavor, + target_cpu: &'a str, + ) -> Box { match flavor { LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => { @@ -70,6 +70,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: false, + target_cpu, }) as Box } @@ -82,6 +83,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: true, + target_cpu, }) as Box } @@ -144,6 +146,7 @@ pub struct GccLinker<'a> { hinted_static: bool, // Keeps track of the current hinting mode. // Link as ld is_ld: bool, + target_cpu: &'a str, } impl<'a> GccLinker<'a> { @@ -204,7 +207,8 @@ impl<'a> GccLinker<'a> { }; self.linker_arg(&format!("-plugin-opt={}", opt_level)); - self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess))); + let target_cpu = self.target_cpu; + self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu)); match self.sess.lto() { config::Lto::Thin | @@ -263,7 +267,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = archive::find_library(lib, search_path, &self.sess); + let lib = ::find_library(lib, search_path, &self.sess); self.linker_arg(&lib); } } @@ -898,7 +902,8 @@ impl<'a> Linker for EmLinker<'a> { fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); - let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); + let export_threshold = + ::symbol_export::crates_export_threshold(&[crate_type]); for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { symbols.push(symbol.symbol_name(tcx).to_string()); diff --git a/src/librustc_codegen_llvm/back/symbol_export.rs b/src/librustc_codegen_utils/symbol_export.rs similarity index 99% rename from src/librustc_codegen_llvm/back/symbol_export.rs rename to src/librustc_codegen_utils/symbol_export.rs index 6b1b0b94fd9d7..2d650f7f18d6f 100644 --- a/src/librustc_codegen_llvm/back/symbol_export.rs +++ b/src/librustc_codegen_utils/symbol_export.rs @@ -11,7 +11,7 @@ use rustc_data_structures::sync::Lrc; use std::sync::Arc; -use monomorphize::Instance; +use rustc::ty::Instance; use rustc::hir; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; From 9378705f8232536cf12f8b38cea8757599d65cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Oct 2018 17:53:12 +0200 Subject: [PATCH 19/37] submodules: update clippy from 5afdf8b7 to b1d03437 Changes: ```` new_ret_no_self: add sample from #3313 to Known Problems section. Support multiline comments and hopefully fix panic Check for comments in collapsible ifs Resolve ICE in needless range loop lint RIIR update_lints: Update changelog links Rename if_let_redundant_pattern_matching to redundant_pattern_matching Add lint for redundant pattern matching for explicit return boolean Fix issue #3322: reword help message for len_zero Simplify manual_memcpy suggestion in some cases Fix dogfood Update known problems for unnecessary_fold RIIR update_lints: Replace lint count in README.md Rename `active_lints` to `usable_lints` Add comment on WalkDir vs. fs::read_dir sort_by -> sort_by_key Some more documentation for clippy_dev Use `WalkDir` to also gather from subdirectories Avoid linting `boxed_local` on trait implementations. Website: Make lint categories linkable Restore clippy_dummy's placeholder name Swap order of methods in `needless_range_loop` suggestion in some cases Revert "Exclude pattern guards from unnecessary_fold lint" Exclude pattern guards from unnecessary_fold lint ```` --- src/Cargo.lock | 1 + src/tools/clippy | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 3361e81ecfe6d..dd21108352792 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -349,6 +349,7 @@ dependencies = [ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/tools/clippy b/src/tools/clippy index 5afdf8b78507d..b1d0343749bdc 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 5afdf8b78507ddf015d192858aef56e72c17de16 +Subproject commit b1d0343749bdc87e5cbbe7f1aeaa9d2a2c9dbc5b From 0f6e2741f692add6d1995b630e2073d18aa2b2ba Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Sun, 21 Oct 2018 18:53:09 +0100 Subject: [PATCH 20/37] Clarified code example The example was not as clear as it could be because it was making an assumption about the structure of the data in order to multiply the number of collection elements by the item size. This change demonstrates the idea more straightforwardly, without the calculation. --- src/libstd/primitive_docs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 7074928eaf6da..79ccd5939148b 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -322,8 +322,8 @@ mod prim_never { } /// let s = String::from("love: ❤️"); /// let v: Vec = s.chars().collect(); /// -/// assert_eq!(12, s.len() * std::mem::size_of::()); -/// assert_eq!(32, v.len() * std::mem::size_of::()); +/// assert_eq!(12, std::mem::size_of_val(&s[..])); +/// assert_eq!(32, std::mem::size_of_val(&v[..])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] mod prim_char { } From 9f7009628fcfdd6ba6bb8e8effb27abcac1cf13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=85dzio=C5=82ka?= Date: Sun, 21 Oct 2018 23:42:19 +0200 Subject: [PATCH 21/37] Fix a typo in the documentation of RangeInclusive --- src/libcore/ops/range.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 07ba285ea5cb3..fd3e50998fe8c 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -304,7 +304,7 @@ impl> RangeTo { } } -/// An range bounded inclusively below and above (`start..=end`). +/// A range bounded inclusively below and above (`start..=end`). /// /// The `RangeInclusive` `start..=end` contains all values with `x >= start` /// and `x <= end`. It is empty unless `start <= end`. From b0d3d3b959e34ecb6c0b7c29f22c77d8c301514d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sun, 21 Oct 2018 15:37:01 -0700 Subject: [PATCH 22/37] only issue "variant of the expected type" suggestion for enums Felix S. Klock II pointed out that this suggestion (introduced in pull-request #43178 / eac74104) was being issued for one-field-struct expected types (in which case it is misleading and outright wrong), even though it was only intended for one-field enum-variants (most notably, `Some`). Particularly tender-hearted code-historians may be inclined to show mercy towards the author of #43178 on the grounds that it's somewhat confusing that struct field definitions are given in a type called `ty::VariantDef`. Add a conditional to adhere to the original intent. (It would be possible to generalize to structs, but not obviously net desirable.) This adds a level of indentation, so the diff here is going to be easier to read in ignore-whitespace mode (`-w`). Resolves #55250. --- src/librustc_typeck/check/demand.rs | 53 +++++++++++---------- src/test/ui/did_you_mean/issue-42764.rs | 16 +++++++ src/test/ui/did_you_mean/issue-42764.stderr | 11 ++++- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index d82d36a1937bf..7773e2d570844 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -111,34 +111,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); - // If the expected type is an enum with any variants whose sole - // field is of the found type, suggest such variants. See Issue - // #42764. + // If the expected type is an enum (Issue #55250) with any variants whose + // sole field is of the found type, suggest such variants. (Issue #42764) if let ty::Adt(expected_adt, substs) = expected.sty { - let mut compatible_variants = expected_adt.variants - .iter() - .filter(|variant| variant.fields.len() == 1) - .filter_map(|variant| { - let sole_field = &variant.fields[0]; - let sole_field_ty = sole_field.ty(self.tcx, substs); - if self.can_coerce(expr_ty, sole_field_ty) { - let variant_path = self.tcx.item_path_str(variant.did); - Some(variant_path.trim_left_matches("std::prelude::v1::").to_string()) - } else { - None + if expected_adt.is_enum() { + let mut compatible_variants = expected_adt.variants + .iter() + .filter(|variant| variant.fields.len() == 1) + .filter_map(|variant| { + let sole_field = &variant.fields[0]; + let sole_field_ty = sole_field.ty(self.tcx, substs); + if self.can_coerce(expr_ty, sole_field_ty) { + let variant_path = self.tcx.item_path_str(variant.did); + Some(variant_path.trim_left_matches("std::prelude::v1::").to_string()) + } else { + None + } + }).peekable(); + + if compatible_variants.peek().is_some() { + let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); + let suggestions = compatible_variants + .map(|v| format!("{}({})", v, expr_text)).collect::>(); + err.span_suggestions_with_applicability( + expr.span, + "try using a variant of the expected type", + suggestions, + Applicability::MaybeIncorrect, + ); } - }).peekable(); - - if compatible_variants.peek().is_some() { - let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr)); - let suggestions = compatible_variants.map(|v| - format!("{}({})", v, expr_text)).collect::>(); - err.span_suggestions_with_applicability( - expr.span, - "try using a variant of the expected type", - suggestions, - Applicability::MaybeIncorrect, - ); } } diff --git a/src/test/ui/did_you_mean/issue-42764.rs b/src/test/ui/did_you_mean/issue-42764.rs index ff4bb428d5f5f..1c79499ba5902 100644 --- a/src/test/ui/did_you_mean/issue-42764.rs +++ b/src/test/ui/did_you_mean/issue-42764.rs @@ -20,4 +20,20 @@ fn main() { let n: usize = 42; this_function_expects_a_double_option(n); //~^ ERROR mismatched types + //~| HELP try using a variant of the expected type +} + + +// But don't issue the "try using a variant" help if the one-"variant" ADT is +// actually a one-field struct. + +struct Payload; + +struct Wrapper { payload: Payload } + +struct Context { wrapper: Wrapper } + +fn overton() { + let _c = Context { wrapper: Payload{} }; + //~^ ERROR mismatched types } diff --git a/src/test/ui/did_you_mean/issue-42764.stderr b/src/test/ui/did_you_mean/issue-42764.stderr index f1da920872d7c..e256a436affba 100644 --- a/src/test/ui/did_you_mean/issue-42764.stderr +++ b/src/test/ui/did_you_mean/issue-42764.stderr @@ -13,6 +13,15 @@ LL | this_function_expects_a_double_option(DoubleOption::FirstSome(n)); LL | this_function_expects_a_double_option(DoubleOption::AlternativeSome(n)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-42764.rs:37:33 + | +LL | let _c = Context { wrapper: Payload{} }; + | ^^^^^^^^^ expected struct `Wrapper`, found struct `Payload` + | + = note: expected type `Wrapper` + found type `Payload` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From c675111095244f4430fd1c15b2de53c9e5281cb0 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 22 Oct 2018 00:31:07 +0100 Subject: [PATCH 23/37] Correct trailing ellipsis in name_from_pat --- src/librustdoc/clean/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index db605e57735aa..2e6cc4bd54c61 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3632,7 +3632,7 @@ fn name_from_pat(p: &hir::Pat) -> String { fields.iter().map(|&Spanned { node: ref fp, .. }| format!("{}: {}", fp.ident, name_from_pat(&*fp.pat))) .collect::>().join(", "), - if etc { ", ..." } else { "" } + if etc { ", .." } else { "" } ) } PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) From 9f0a352999bfe4f265d6930a49efee7b80fe6ef5 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 15:45:03 +0200 Subject: [PATCH 24/37] Turn ICE for dangling pointers into error --- src/librustc_mir/interpret/memory.rs | 5 +++++ src/test/ui/consts/dangling-alloc-id-ice.rs | 15 +++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice.stderr | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice.stderr diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9adca6c429798..954616fe9fcd7 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -732,6 +732,11 @@ where if self.alloc_map.contains_key(&alloc) { // Not yet interned, so proceed recursively self.intern_static(alloc, mutability)?; + } else if self.dead_alloc_map.contains_key(&alloc) { + // danging pointer + return err!(ValidationFailure( + "encountered dangling pointer in final constant".into(), + )) } } Ok(()) diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs new file mode 100644 index 0000000000000..31fa23ae23221 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/55223 + +#![feature(const_let)] + +union Foo<'a> { + y: &'a (), + long_live_the_unit: &'static (), +} + +const FOO: &() = { //~ ERROR this constant cannot be used + let y = (); + unsafe { Foo { y: &y }.long_live_the_unit } +}; + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr new file mode 100644 index 0000000000000..df623f943addc --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -0,0 +1,13 @@ +error: this constant cannot be used + --> $DIR/dangling-alloc-id-ice.rs:10:1 + | +LL | / const FOO: &() = { //~ ERROR this constant cannot be used +LL | | let y = (); +LL | | unsafe { Foo { y: &y }.long_live_the_unit } +LL | | }; + | |__^ type validation failed: encountered dangling pointer in final constant + | + = note: #[deny(const_err)] on by default + +error: aborting due to previous error + From 0ba126217d4d349e5d9681bbb838c036adb55d18 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 22 Oct 2018 18:05:27 +0200 Subject: [PATCH 25/37] Reproduce the underlying issue nll (and thus the algorithm for actual promotion) don't know about some casts anymore --- .../consts/dangling-alloc-id-ice-2.nll.stderr | 30 +++++++++++++++++++ src/test/ui/consts/dangling-alloc-id-ice-2.rs | 10 +++++++ .../ui/consts/dangling-alloc-id-ice-2.stderr | 11 +++++++ 3 files changed, 51 insertions(+) create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.rs create mode 100644 src/test/ui/consts/dangling-alloc-id-ice-2.stderr diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr new file mode 100644 index 0000000000000..e6ae57796055f --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.nll.stderr @@ -0,0 +1,30 @@ +warning[E0716]: temporary value dropped while borrowed + --> $DIR/dangling-alloc-id-ice-2.rs:5:28 + | +LL | static MAP: Slice = Slice(&[ + | ___________________________-^ + | |___________________________| + | || +LL | || b"CloseEvent" as &'static [u8], +LL | || ]); + | || -- temporary value is freed at the end of this statement + | ||_| + | |__creates a temporary which is freed while still in use + | cast requires that borrow lasts for `'static` + | + = warning: This error has been downgraded to a warning for backwards compatibility with previous releases. + It represents potential unsoundness in your code. + This warning will become a hard error in the future. + +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +Some errors occurred: E0080, E0716. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs new file mode 100644 index 0000000000000..9af72c8dc0b83 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -0,0 +1,10 @@ +// https://github.com/rust-lang/rust/issues/55223 + +struct Slice(&'static [&'static [u8]]); + +static MAP: Slice = Slice(&[ + b"CloseEvent" as &'static [u8], +]); + + +fn main() {} diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.stderr b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr new file mode 100644 index 0000000000000..42df542f55cf5 --- /dev/null +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.stderr @@ -0,0 +1,11 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/dangling-alloc-id-ice-2.rs:5:1 + | +LL | / static MAP: Slice = Slice(&[ +LL | | b"CloseEvent" as &'static [u8], +LL | | ]); + | |___^ type validation failed: encountered dangling pointer in final constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 80a6b736acca2c109547e100d217fe5ca5f4ec30 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 23 Oct 2018 01:54:02 +0900 Subject: [PATCH 26/37] Unimplement ExactSizeIterator If root is not START_BLOCK, `basic_blocks().len() - visited` does not represent their exact size. --- src/librustc/mir/traversal.rs | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index db1bc3e7519c2..a1e2b7a06468d 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -34,6 +34,7 @@ pub struct Preorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, visited: BitSet, worklist: Vec, + root_is_start_block: bool, } impl<'a, 'tcx> Preorder<'a, 'tcx> { @@ -44,6 +45,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> { mir, visited: BitSet::new_empty(mir.basic_blocks().len()), worklist, + root_is_start_block: root == START_BLOCK, } } } @@ -75,15 +77,19 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { fn size_hint(&self) -> (usize, Option) { // All the blocks, minus the number of blocks we've visited. - let remaining = self.mir.basic_blocks().len() - self.visited.count(); + let upper = self.mir.basic_blocks().len() - self.visited.count(); - // We will visit all remaining blocks exactly once. - (remaining, Some(remaining)) + let lower = if self.root_is_start_block { + // We will visit all remaining blocks exactly once. + upper + } else { + self.worklist.len() + }; + + (lower, Some(upper)) } } -impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} - /// Postorder traversal of a graph. /// /// Postorder traversal is when each node is visited after all of it's @@ -105,7 +111,8 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, visited: BitSet, - visit_stack: Vec<(BasicBlock, Successors<'a>)> + visit_stack: Vec<(BasicBlock, Successors<'a>)>, + root_is_start_block: bool, } impl<'a, 'tcx> Postorder<'a, 'tcx> { @@ -113,7 +120,8 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { let mut po = Postorder { mir, visited: BitSet::new_empty(mir.basic_blocks().len()), - visit_stack: Vec::new() + visit_stack: Vec::new(), + root_is_start_block: root == START_BLOCK, }; @@ -214,15 +222,19 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { fn size_hint(&self) -> (usize, Option) { // All the blocks, minus the number of blocks we've visited. - let remaining = self.mir.basic_blocks().len() - self.visited.count(); + let upper = self.mir.basic_blocks().len() - self.visited.count(); - // We will visit all remaining blocks exactly once. - (remaining, Some(remaining)) + let lower = if self.root_is_start_block { + // We will visit all remaining blocks exactly once. + upper + } else { + self.visit_stack.len() + }; + + (lower, Some(upper)) } } -impl<'a, 'tcx> ExactSizeIterator for Postorder<'a, 'tcx> {} - /// Reverse postorder traversal of a graph /// /// Reverse postorder is the reverse order of a postorder traversal. From d2baf92769a0f97beaa17e90af9b2a0ae5ab9f0a Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 18 Oct 2018 19:09:49 +0200 Subject: [PATCH 27/37] Add note linking to Rust 2018 path semantics docs. This commit extends existing path suggestions to link to documentation on the changed semantics of `use` in Rust 2018. --- src/librustc_resolve/error_reporting.rs | 25 ++++--- src/librustc_resolve/resolve_imports.rs | 65 +++++++++++++------ .../local-path-suggestions-2018.stderr | 2 + 3 files changed, 63 insertions(+), 29 deletions(-) diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 74d1ae96e794f..4ee50bfca7897 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -24,7 +24,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); // If we don't have a path to suggest changes to, then return. if path.is_empty() { @@ -60,13 +60,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. path[0].name = keywords::SelfValue.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -83,13 +83,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].name = keywords::Crate.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some(( + path, + Some( + "`use` statements changed in Rust 2018; read more at \ + ".to_string() + ), + )) } else { None } @@ -106,13 +113,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].name = keywords::Super.name(); let result = self.resolve_path(None, &path, None, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { - Some(path) + Some((path, None)) } else { None } @@ -132,7 +139,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { &mut self, span: Span, mut path: Vec - ) -> Option> { + ) -> Option<(Vec, Option)> { // Need to clone else we can't call `resolve_path` without a borrow error. We also store // into a `BTreeMap` so we can get consistent ordering (and therefore the same diagnostic) // each time. @@ -157,7 +164,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}", name, path, result); if let PathResult::Module(..) = result { - return Some(path) + return Some((path, None)) } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index d5d772e135914..0b44863bc39a0 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -697,7 +697,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }); - } else if let Some((span, err)) = error { + } else if let Some((span, err, note)) = error { errors = true; if let SingleImport { source, ref result, .. } = import.subclass { @@ -725,7 +725,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { let path = import_path_to_string(&import.module_path[..], &import.subclass, span); - error_vec.push((span, path, err)); + error_vec.push((span, path, err, note)); seen_spans.insert(span); prev_root_id = import.root_id; } @@ -818,27 +818,45 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } - fn throw_unresolved_import_error(&self, error_vec: Vec<(Span, String, String)>, - span: Option) { + fn throw_unresolved_import_error( + &self, + error_vec: Vec<(Span, String, String, Option)>, + span: Option, + ) { let max_span_label_msg_count = 10; // upper limit on number of span_label message. - let (span, msg) = if error_vec.is_empty() { - (span.unwrap(), "unresolved import".to_string()) + let (span, msg, note) = if error_vec.is_empty() { + (span.unwrap(), "unresolved import".to_string(), None) } else { - let span = MultiSpan::from_spans(error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { elem.0 }) - .collect()); + let span = MultiSpan::from_spans( + error_vec.clone().into_iter() + .map(|elem: (Span, String, String, Option)| elem.0) + .collect() + ); + + let note: Option = error_vec.clone().into_iter() + .filter_map(|elem: (Span, String, String, Option)| elem.3) + .last(); + let path_vec: Vec = error_vec.clone().into_iter() - .map(|elem: (Span, String, String)| { format!("`{}`", elem.1) }) + .map(|elem: (Span, String, String, Option)| format!("`{}`", elem.1)) .collect(); let path = path_vec.join(", "); - let msg = format!("unresolved import{} {}", - if path_vec.len() > 1 { "s" } else { "" }, path); - (span, msg) + let msg = format!( + "unresolved import{} {}", + if path_vec.len() > 1 { "s" } else { "" }, + path + ); + + (span, msg, note) }; + let mut err = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg); for span_error in error_vec.into_iter().take(max_span_label_msg_count) { err.span_label(span_error.0, span_error.2); } + if let Some(note) = note { + err.note(¬e); + } err.emit(); } @@ -933,7 +951,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } // If appropriate, returns an error to report. - fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { + fn finalize_import( + &mut self, + directive: &'b ImportDirective<'b> + ) -> Option<(Span, String, Option)> { self.current_module = directive.parent; let ImportDirective { ref module_path, span, .. } = *directive; @@ -956,15 +977,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { return None; } PathResult::Failed(span, msg, true) => { - return if let Some(suggested_path) = self.make_path_suggestion( + return if let Some((suggested_path, note)) = self.make_path_suggestion( span, module_path.clone() ) { Some(( span, - format!("Did you mean `{}`?", names_to_string(&suggested_path[..])) + format!("Did you mean `{}`?", names_to_string(&suggested_path[..])), + note, )) } else { - Some((span, msg)) + Some((span, msg, None)) }; }, _ => return None, @@ -989,8 +1011,11 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { if let ModuleOrUniformRoot::Module(module) = module { if module.def_id() == directive.parent.def_id() { // Importing a module into itself is not allowed. - return Some((directive.span, - "Cannot glob-import a module into itself.".to_string())); + return Some(( + directive.span, + "Cannot glob-import a module into itself.".to_string(), + None, + )); } } if !is_prelude && @@ -1081,7 +1106,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { } } }; - Some((span, msg)) + Some((span, msg, None)) } else { // `resolve_ident_in_module` reported a privacy error. self.import_dummy_binding(directive); diff --git a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr index 97bf748881f29..2293f4b001749 100644 --- a/src/test/ui/rust-2018/local-path-suggestions-2018.stderr +++ b/src/test/ui/rust-2018/local-path-suggestions-2018.stderr @@ -3,6 +3,8 @@ error[E0432]: unresolved import `foo` | LL | use foo::Bar; | ^^^ Did you mean `crate::foo`? + | + = note: `use` statements changed in Rust 2018; read more at error[E0432]: unresolved import `foo` --> $DIR/local-path-suggestions-2018.rs:27:5 From e1e52eb5a0156839a71c0ffc5424e2160271170e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 17 Oct 2018 21:07:31 -0700 Subject: [PATCH 28/37] Suggest appropriate syntax on missing lifetime specifier in return type Suggest using `'static` when a lifetime is missing in the return type with a structured suggestion instead of a note. --- src/librustc/hir/lowering.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 55 ++++++++++++++++--- ...nd-lifetime-in-binding-only.elision.stderr | 6 +- ...und-lifetime-in-return-only.elision.stderr | 6 +- src/test/ui/foreign-fn-return-lifetime.fixed | 18 ++++++ src/test/ui/foreign-fn-return-lifetime.rs | 6 +- src/test/ui/foreign-fn-return-lifetime.stderr | 10 ++-- src/test/ui/issues/issue-13497.stderr | 6 +- src/test/ui/issues/issue-26638.stderr | 12 ++-- ...urn-type-requires-explicit-lifetime.stderr | 24 +++++--- .../lifetime-elision-return-type-trait.rs | 10 ++++ .../lifetime-elision-return-type-trait.stderr | 19 +++++++ .../underscore-lifetime-binders.stderr | 6 +- 13 files changed, 146 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/foreign-fn-return-lifetime.fixed create mode 100644 src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs create mode 100644 src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index cce872927b147..04a2308cead34 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1152,7 +1152,7 @@ impl<'a> LoweringContext<'a> { TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), TyKind::Rptr(ref region, ref mt) => { - let span = t.span.shrink_to_lo(); + let span = self.sess.source_map().next_point(t.span.shrink_to_lo()); let lifetime = match *region { Some(ref lt) => self.lower_lifetime(lt), None => self.elided_ref_lifetime(span), diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 98e80d333c1c8..86db74b78b983 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2238,7 +2238,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { if let Some(params) = error { if lifetime_refs.len() == 1 { - self.report_elision_failure(&mut err, params); + self.report_elision_failure(&mut err, params, span); } } @@ -2249,6 +2249,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], + span: Span, ) { let mut m = String::new(); let len = params.len(); @@ -2304,7 +2305,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from" ); - help!(db, "consider giving it a 'static lifetime"); + let msg = "consider giving it a 'static lifetime"; + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( + span, + msg, + "&'static ".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) + if snippet == "'_" => db.span_suggestion_with_applicability( + span, + msg, + "'static".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) => db.span_suggestion_with_applicability( + span, + msg, + format!("{} + 'static", snippet), + Applicability::MaybeIncorrect, + ), + Err(_) => db.help(msg), + }; } else if elided_len == 0 { help!( db, @@ -2312,11 +2335,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { an elided lifetime, but the lifetime cannot be derived from \ the arguments" ); - help!( - db, - "consider giving it an explicit bounded or 'static \ - lifetime" - ); + let msg = "consider giving it an explicit bounded or 'static lifetime"; + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( + span, + msg, + "&'static ".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) + if snippet == "'_" => db.span_suggestion_with_applicability( + span, + msg, + "'static".to_owned(), + Applicability::MachineApplicable, + ), + Ok(ref snippet) => db.span_suggestion_with_applicability( + span, + msg, + format!("{} + 'static", snippet), + Applicability::MaybeIncorrect, + ), + Err(_) => db.help(msg), + }; } else if elided_len == 1 { help!( db, diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 0a12aa76a785b..4336aaf71ba02 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-binding-only.rs:62:23 | LL | fn elision &i32>() { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index 8fefdfd4d19ef..fbc4df54225d5 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-return-only.rs:44:23 | LL | fn elision(_: fn() -> &i32) { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/foreign-fn-return-lifetime.fixed b/src/test/ui/foreign-fn-return-lifetime.fixed new file mode 100644 index 0000000000000..9fc35eae7052f --- /dev/null +++ b/src/test/ui/foreign-fn-return-lifetime.fixed @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +extern "C" { + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/ui/foreign-fn-return-lifetime.rs b/src/test/ui/foreign-fn-return-lifetime.rs index da77066150cc7..941e7e05a3635 100644 --- a/src/test/ui/foreign-fn-return-lifetime.rs +++ b/src/test/ui/foreign-fn-return-lifetime.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + extern "C" { - fn g(_: &u8) -> &u8; // OK - fn f() -> &u8; //~ ERROR missing lifetime specifier + pub fn g(_: &u8) -> &u8; // OK + pub fn f() -> &u8; //~ ERROR missing lifetime specifier } fn main() {} diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index ea15897b3d694..4e52d6044c4e9 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -1,11 +1,13 @@ error[E0106]: missing lifetime specifier - --> $DIR/foreign-fn-return-lifetime.rs:13:15 + --> $DIR/foreign-fn-return-lifetime.rs:15:19 | -LL | fn f() -> &u8; //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter +LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index ab6d041bd48d7..88b6a831d7e41 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-13497.rs:12:5 | LL | &str //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index cf6fcd9f01cc8..e4464b2dd313d 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -10,19 +10,23 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:14:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:17:22 | LL | fn parse_type_3() -> &str { unimplemented!() } - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error: aborting due to 3 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 30cff86ed1d40..9962dbc9812bd 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -2,10 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11 | LL | fn f() -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:33 @@ -27,28 +29,34 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20 | LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24 | LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49 | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { - | ^ expected lifetime parameter + | ^ + | | + | expected lifetime parameter + | help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments - = help: consider giving it an explicit bounded or 'static lifetime error: aborting due to 6 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs new file mode 100644 index 0000000000000..6b6e263b7fd1a --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -0,0 +1,10 @@ +trait Future { + type Item; + type Error; +} + +use std::error::Error; + +fn foo() -> impl Future> { + Ok(()) +} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr new file mode 100644 index 0000000000000..426941b949daa --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -0,0 +1,19 @@ +error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait` + | + = note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs` + +error[E0106]: missing lifetime specifier + --> $DIR/lifetime-elision-return-type-trait.rs:8:44 + | +LL | fn foo() -> impl Future> { + | ^^^^^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `Error + 'static` + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + +error: aborting due to 2 previous errors + +Some errors occurred: E0106, E0601. +For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index fc9f3e642d402..b0da67a7c346e 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -26,10 +26,12 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:24:29 | LL | fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here - | ^^ expected lifetime parameter + | ^^ + | | + | expected lifetime parameter + | help: consider giving it a 'static lifetime: `'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from - = help: consider giving it a 'static lifetime error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:30:35 From d0bd69a2d559177724df95463a79af9c2a2ad63d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Oct 2018 13:05:38 -0700 Subject: [PATCH 29/37] review comments --- src/librustc/middle/resolve_lifetime.rs | 99 ++++++++----------- ...nd-lifetime-in-binding-only.elision.stderr | 5 +- ...und-lifetime-in-return-only.elision.stderr | 5 +- src/test/ui/foreign-fn-return-lifetime.stderr | 5 +- src/test/ui/issues/issue-13497.stderr | 5 +- src/test/ui/issues/issue-26638.stderr | 10 +- ...urn-type-requires-explicit-lifetime.stderr | 20 +--- .../lifetime-elision-return-type-trait.stderr | 5 +- .../underscore-lifetime-binders.stderr | 5 +- 9 files changed, 54 insertions(+), 105 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 86db74b78b983..7547e8039158e 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2235,22 +2235,46 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }; let mut err = report_missing_lifetime_specifiers(self.tcx.sess, span, lifetime_refs.len()); + let mut add_label = true; if let Some(params) = error { if lifetime_refs.len() == 1 { - self.report_elision_failure(&mut err, params, span); + add_label = add_label && self.report_elision_failure(&mut err, params, span); } } + if add_label { + add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len()); + } err.emit(); } + fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool { + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(ref snippet) => { + let (sugg, applicability) = if &snippet[..] == "&" { + ("&'static ".to_owned(), Applicability::MachineApplicable) + } else if snippet == "'_" { + ("'static".to_owned(), Applicability::MachineApplicable) + } else { + (format!("{} + 'static", snippet), Applicability::MaybeIncorrect) + }; + db.span_suggestion_with_applicability(span, msg, sugg, applicability); + false + } + Err(_) => { + db.help(msg); + true + } + } + } + fn report_elision_failure( &mut self, db: &mut DiagnosticBuilder<'_>, params: &[ElisionFailureInfo], span: Span, - ) { + ) -> bool { let mut m = String::new(); let len = params.len(); @@ -2305,29 +2329,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { "this function's return type contains a borrowed value, but \ there is no value for it to be borrowed from" ); - let msg = "consider giving it a 'static lifetime"; - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( - span, - msg, - "&'static ".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) - if snippet == "'_" => db.span_suggestion_with_applicability( - span, - msg, - "'static".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) => db.span_suggestion_with_applicability( - span, - msg, - format!("{} + 'static", snippet), - Applicability::MaybeIncorrect, - ), - Err(_) => db.help(msg), - }; + self.suggest_lifetime(db, span, "consider giving it a 'static lifetime") } else if elided_len == 0 { help!( db, @@ -2336,28 +2338,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the arguments" ); let msg = "consider giving it an explicit bounded or 'static lifetime"; - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(ref snippet) if snippet == "&" => db.span_suggestion_with_applicability( - span, - msg, - "&'static ".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) - if snippet == "'_" => db.span_suggestion_with_applicability( - span, - msg, - "'static".to_owned(), - Applicability::MachineApplicable, - ), - Ok(ref snippet) => db.span_suggestion_with_applicability( - span, - msg, - format!("{} + 'static", snippet), - Applicability::MaybeIncorrect, - ), - Err(_) => db.help(msg), - }; + self.suggest_lifetime(db, span, msg) } else if elided_len == 1 { help!( db, @@ -2365,6 +2346,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the signature does not say which {} it is borrowed from", m ); + true } else { help!( db, @@ -2372,6 +2354,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { the signature does not say whether it is borrowed from {}", m ); + true } } @@ -2785,26 +2768,28 @@ fn insert_late_bound_lifetimes( } } -pub fn report_missing_lifetime_specifiers( +fn report_missing_lifetime_specifiers( sess: &Session, span: Span, count: usize, ) -> DiagnosticBuilder<'_> { - let mut err = struct_span_err!( + struct_span_err!( sess, span, E0106, "missing lifetime specifier{}", if count > 1 { "s" } else { "" } - ); + ) +} - let msg: Cow<'static, str> = if count > 1 { - format!("expected {} lifetime parameters", count).into() +fn add_missing_lifetime_specifiers_label( + err: &mut DiagnosticBuilder<'_>, + span: Span, + count: usize, +) { + if count > 1 { + err.span_label(span, format!("expected {} lifetime parameters", count)); } else { - "expected lifetime parameter".into() + err.span_label(span, "expected lifetime parameter"); }; - - err.span_label(span, msg); - - err } diff --git a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr index 4336aaf71ba02..6b9d4ebb2987d 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-binding-only.elision.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-binding-only.rs:62:23 | LL | fn elision &i32>() { - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr index fbc4df54225d5..7906f0a30e4eb 100644 --- a/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr +++ b/src/test/ui/associated-types/bound-lifetime-in-return-only.elision.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/bound-lifetime-in-return-only.rs:44:23 | LL | fn elision(_: fn() -> &i32) { - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/foreign-fn-return-lifetime.stderr b/src/test/ui/foreign-fn-return-lifetime.stderr index 4e52d6044c4e9..583487656f24d 100644 --- a/src/test/ui/foreign-fn-return-lifetime.stderr +++ b/src/test/ui/foreign-fn-return-lifetime.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/foreign-fn-return-lifetime.rs:15:19 | LL | pub fn f() -> &u8; //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/issues/issue-13497.stderr b/src/test/ui/issues/issue-13497.stderr index 88b6a831d7e41..e592452b89944 100644 --- a/src/test/ui/issues/issue-13497.stderr +++ b/src/test/ui/issues/issue-13497.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-13497.rs:12:5 | LL | &str //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index e4464b2dd313d..0ac6316f0dcf8 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -10,10 +10,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:14:40 | LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() } - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -21,10 +18,7 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:17:22 | LL | fn parse_type_3() -> &str { unimplemented!() } - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 9962dbc9812bd..4c7a1b5ea9ff0 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -2,10 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:12:11 | LL | fn f() -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `&'static` + | ^ help: consider giving it a 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from @@ -29,10 +26,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:31:20 | LL | fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -40,10 +34,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:44:24 | LL | fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments @@ -51,10 +42,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:50:49 | LL | fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize { - | ^ - | | - | expected lifetime parameter - | help: consider giving it an explicit bounded or 'static lifetime: `&'static` + | ^ help: consider giving it an explicit bounded or 'static lifetime: `&'static` | = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 426941b949daa..ab429b9df06cd 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -6,10 +6,7 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-trait.rs:8:44 | LL | fn foo() -> impl Future> { - | ^^^^^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `Error + 'static` + | ^^^^^ help: consider giving it a 'static lifetime: `Error + 'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index b0da67a7c346e..4319843291a20 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -26,10 +26,7 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:24:29 | LL | fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here - | ^^ - | | - | expected lifetime parameter - | help: consider giving it a 'static lifetime: `'static` + | ^^ help: consider giving it a 'static lifetime: `'static` | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from From dd91c8fc5a7c097c508cdffdd236adc64dae01c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Fri, 19 Oct 2018 10:43:43 -0700 Subject: [PATCH 30/37] [review comments] modify test and clean up code Co-Authored-By: estebank --- src/librustc/middle/resolve_lifetime.rs | 2 +- .../ui/lifetimes/lifetime-elision-return-type-trait.rs | 2 ++ .../lifetimes/lifetime-elision-return-type-trait.stderr | 9 ++------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 7547e8039158e..361abb1689619 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2252,7 +2252,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn suggest_lifetime(&self, db: &mut DiagnosticBuilder<'_>, span: Span, msg: &str) -> bool { match self.tcx.sess.source_map().span_to_snippet(span) { Ok(ref snippet) => { - let (sugg, applicability) = if &snippet[..] == "&" { + let (sugg, applicability) = if snippet == "&" { ("&'static ".to_owned(), Applicability::MachineApplicable) } else if snippet == "'_" { ("'static".to_owned(), Applicability::MachineApplicable) diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index 6b6e263b7fd1a..eb959bfbcb533 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -8,3 +8,5 @@ use std::error::Error; fn foo() -> impl Future> { Ok(()) } + +fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index ab429b9df06cd..b2a3d9a94361f 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `lifetime_elision_return_type_trait` - | - = note: consider adding a `main` function to `$DIR/lifetime-elision-return-type-trait.rs` - error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-trait.rs:8:44 | @@ -10,7 +6,6 @@ LL | fn foo() -> impl Future> { | = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0106, E0601. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`. From 4f2624cac90ee9145175d6e4b9c59b9ab7875a9c Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 22 Oct 2018 00:12:16 -0400 Subject: [PATCH 31/37] Fix Rustdoc ICE when checking blanket impls Fixes #55001, #54744 Previously, SelectionContext would unconditionally cache the selection result for an obligation. This worked fine for most users of SelectionContext, but it caused an issue when used by Rustdoc's blanket impl finder. The issue occured when SelectionContext chose a ParamCandidate which contained inference variables. Since inference variables can change between calls to select(), it's not safe to cache the selection result - the chosen candidate might not be applicable for future results, leading to an ICE when we try to run confirmation. This commit prevents SelectionContext from caching any ParamCandidate that contains inference variables. This should always be completely safe, as trait selection should never depend on a particular result being cached. I've also added some extra debug!() statements, which I found helpful in tracking down this bug. --- src/librustc/infer/combine.rs | 10 +++++++- src/librustc/infer/equate.rs | 3 +++ src/librustc/traits/select.rs | 35 ++++++++++++++++++++++++++++ src/librustdoc/clean/blanket_impl.rs | 11 +++++++-- src/test/rustdoc/issue-55001.rs | 31 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-55001.rs diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index de8f57ee79666..0ee03bc4c6e00 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -251,6 +251,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { dir: RelationDir) -> RelateResult<'tcx, Generalization<'tcx>> { + debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir); // Determine the ambient variance within which `ty` appears. // The surrounding equation is: // @@ -273,8 +274,15 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { root_ty: ty, }; - let ty = generalize.relate(&ty, &ty)?; + let ty = match generalize.relate(&ty, &ty) { + Ok(ty) => ty, + Err(e) => { + debug!("generalize: failure {:?}", e); + return Err(e); + } + }; let needs_wf = generalize.needs_wf; + debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf); Ok(Generalization { ty, needs_wf }) } } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 854960492c9bd..c7b5ddb83410f 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -74,6 +74,9 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> let infcx = self.fields.infcx; let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); + + debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); + match (&a.sty, &b.sty) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 39c623de677d3..3f4aa3a500d71 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1522,6 +1522,33 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .map(|v| v.get(tcx)) } + /// Determines whether can we safely cache the result + /// of selecting an obligation. This is almost always 'true', + /// except when dealing with certain ParamCandidates. + /// + /// Ordinarily, a ParamCandidate will contain no inference variables, + /// since it was usually produced directly from a DefId. However, + /// certain cases (currently only librustdoc's blanket impl finder), + /// a ParamEnv may be explicitly constructed with inference types. + /// When this is the case, we do *not* want to cache the resulting selection + /// candidate. This is due to the fact that it might not always be possible + /// to equate the obligation's trait ref and the candidate's trait ref, + /// if more constraints end up getting added to an inference variable. + /// + /// Because of this, we always want to re-run the full selection + /// process for our obligation the next time we see it, since + /// we might end up picking a different SelectionCandidate (or none at all) + fn can_cache_candidate(&self, + result: &SelectionResult<'tcx, SelectionCandidate<'tcx>> + ) -> bool { + match result { + Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => { + !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer())) + }, + _ => true + } + } + fn insert_candidate_cache( &mut self, param_env: ty::ParamEnv<'tcx>, @@ -1531,6 +1558,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ) { let tcx = self.tcx(); let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref; + + if !self.can_cache_candidate(&candidate) { + debug!("insert_candidate_cache(trait_ref={:?}, candidate={:?} -\ + candidate is not cacheable", trait_ref, candidate); + return; + + } + if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index b6bc8d603d5ac..57c7e2afd625e 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -50,6 +50,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { name: Option, ) -> Vec where F: Fn(DefId) -> Def { + debug!("get_blanket_impls(def_id={:?}, ...)", def_id); let mut impls = Vec::new(); if self.cx .tcx @@ -78,6 +79,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { } self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| { self.cx.tcx.infer_ctxt().enter(|infcx| { + debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}", + trait_def_id, impl_def_id); let t_generics = infcx.tcx.generics_of(impl_def_id); let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id) .expect("Cannot get impl trait"); @@ -104,8 +107,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { drop(obligations); debug!( - "invoking predicate_may_hold: {:?}", - trait_ref, + "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}", + param_env, trait_ref, ty ); let may_apply = match infcx.evaluate_obligation( &traits::Obligation::new( @@ -117,6 +120,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no }; + debug!("get_blanket_impls: found applicable impl: {}\ + for trait_ref={:?}, ty={:?}", + may_apply, trait_ref, ty); + if !may_apply { return } diff --git a/src/test/rustdoc/issue-55001.rs b/src/test/rustdoc/issue-55001.rs new file mode 100644 index 0000000000000..f6c7f9a3d082c --- /dev/null +++ b/src/test/rustdoc/issue-55001.rs @@ -0,0 +1,31 @@ +// Regression test for issue #55001. Previously, we would incorrectly +// cache certain trait selection results when checking for blanket impls, +// resulting in an ICE when we tried to confirm the cached ParamCandidate +// against an obligation. + +pub struct DefaultAllocator; +pub struct Standard; +pub struct Inner; + +pub trait Rand {} + +pub trait Distribution {} +pub trait Allocator {} + +impl Rand for T where Standard: Distribution {} + +impl Distribution> for Standard +where +DefaultAllocator: Allocator, +Standard: Distribution {} + +impl Distribution for Standard {} + + +pub struct Point +where DefaultAllocator: Allocator +{ + field: N +} + +fn main() {} From fda3326a5a34fd365e20f0dd2632cec27233d060 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 23 Oct 2018 17:13:59 +0900 Subject: [PATCH 32/37] Remove redundant clone --- src/librustc/hir/print.rs | 2 +- src/librustc/ich/caching_codemap_view.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 4 ++-- src/libsyntax/fold.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 08d46793d97bf..ad2fa48610b0e 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -180,7 +180,7 @@ impl<'a> State<'a> { State { s: pp::mk_printer(out, default_columns), cm: Some(cm), - comments: comments.clone(), + comments, literals: literals.unwrap_or_default().into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), diff --git a/src/librustc/ich/caching_codemap_view.rs b/src/librustc/ich/caching_codemap_view.rs index 97114779042af..fbf4297222f9b 100644 --- a/src/librustc/ich/caching_codemap_view.rs +++ b/src/librustc/ich/caching_codemap_view.rs @@ -44,7 +44,7 @@ impl<'cm> CachingSourceMapView<'cm> { CachingSourceMapView { source_map, - line_cache: [entry.clone(), entry.clone(), entry.clone()], + line_cache: [entry.clone(), entry.clone(), entry], time_stamp: 0, } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b29ee8f7cdce4..b266fbe0d1145 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -340,7 +340,7 @@ impl<'a, 'b, 'gcx, 'tcx> AssociatedTypeNormalizer<'a, 'b, 'gcx, 'tcx> { let value = self.selcx.infcx().resolve_type_vars_if_possible(value); if !value.has_projections() { - value.clone() + value } else { value.fold_with(self) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8289158387015..0acf711c238d2 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -967,7 +967,7 @@ impl<'tcx> PolyFnSig<'tcx> { self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) } pub fn output(&self) -> ty::Binder> { - self.map_bound_ref(|fn_sig| fn_sig.output().clone()) + self.map_bound_ref(|fn_sig| fn_sig.output()) } pub fn variadic(&self) -> bool { self.skip_binder().variadic diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 04a297d0a8317..77483ad184ba6 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1048,7 +1048,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, if let Some(constructors) = pat_constructors(cx, v[0], pcx) { debug!("is_useful - expanding constructors: {:#?}", constructors); split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) ).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { debug!("is_useful - expanding wildcard"); @@ -1096,7 +1096,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, if missing_ctors.is_empty() && !is_non_exhaustive { split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| { - is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness) + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) }).find(|result| result.is_useful()).unwrap_or(NotUseful) } else { let matrix = rows.iter().filter_map(|r| { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 95a2298ca757d..18d5970462f63 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -965,7 +965,7 @@ pub fn noop_fold_item_kind(i: ItemKind, folder: &mut T) -> ItemKind { polarity, defaultness, folder.fold_generics(generics), - ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref.clone())), + ifce.map(|trait_ref| folder.fold_trait_ref(trait_ref)), folder.fold_ty(ty), impl_items.move_flat_map(|item| folder.fold_impl_item(item)), ), From 2d960a561061d78d44c3c56d3aa0fa6975ca0ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?= =?UTF-8?q?e=CC=B6r=20Scherer?= Date: Tue, 23 Oct 2018 13:39:30 +0200 Subject: [PATCH 33/37] Update dangling-alloc-id-ice-2.rs --- src/test/ui/consts/dangling-alloc-id-ice-2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/dangling-alloc-id-ice-2.rs b/src/test/ui/consts/dangling-alloc-id-ice-2.rs index 9af72c8dc0b83..b4691641fc98f 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice-2.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice-2.rs @@ -1,4 +1,4 @@ -// https://github.com/rust-lang/rust/issues/55223 +// FIXME(#55223) this is just a reproduction test showing the wrong behavior struct Slice(&'static [&'static [u8]]); From 8d6ee8f54ad802231f1e09e4b4433ef84d8a4248 Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Tue, 23 Oct 2018 07:53:48 -0400 Subject: [PATCH 34/37] Do some copy editing on the release notes I was reading through the release notes to find something and noticed some small grammatical and consistency issues. --- RELEASES.md | 88 ++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 7ae7dc9935b6d..1d888731e94a2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -4,34 +4,34 @@ Version 1.30.0 (2018-10-25) Language -------- - [Procedural macros are now available.][52081] These kinds of macros allow for - more powerful code generation, there is a [new chapter available][proc-macros] - in Rust Programming Language book that goes further in depth. + more powerful code generation. There is a [new chapter available][proc-macros] + in the Rust Programming Language book that goes further in depth. - [You can now use keywords as identifiers using the raw identifiers - syntax (`r#`).][53236] e.g. `let r#for = true;` + syntax (`r#`),][53236] e.g. `let r#for = true;` - [Using anonymous parameters in traits is now deprecated with a warning and will be a hard error in the 2018 edition.][53272] - [You can now use `crate` in paths.][54404] This allows you to refer to the - crate root in the path. e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`. -- [Using a external crate now no longer requires being prefixed with `::`.][54404] - e.g. previously using a external crate in a module without a use statement - required `let json = ::serde_json::from_str(foo);` can now be written + crate root in the path, e.g. `use crate::foo;` refers to `foo` in `src/lib.rs`. +- [Using a external crate no longer requires being prefixed with `::`.][54404] + Previously, using a external crate in a module without a use statement + required `let json = ::serde_json::from_str(foo);` but can now be written as `let json = serde_json::from_str(foo);`. - [You can now apply the `#[used]` attribute to static items to prevent the - compiler from optimising them away even if they appear to be unused.][51363] + compiler from optimising them away, even if they appear to be unused,][51363] e.g. `#[used] static FOO: u32 = 1;` - [You can now import and reexport macros from other crates with the `use` syntax.][50911] Macros exported with `#[macro_export]` are now placed into the root module of the crate. If your macro relies on calling other local - macros it is recommended to export with the - `#[macro_export(local_inner_macros)]` attribute so that users won't have to - import those macros. -- [`mod.rs` files are now optional.][54146] Previously if you had a `foo` module + macros, it is recommended to export with the + `#[macro_export(local_inner_macros)]` attribute so users won't have to import + those macros. +- [`mod.rs` files are now optional.][54146] Previously, if you had a `foo` module with a `bar` submodule, you would have `src/foo/mod.rs` and `src/foo/bar.rs`. Now you can have `src/foo.rs` and `src/foo/bar.rs` to achieve the same effect. - [You can now catch visibility keywords (e.g. `pub`, `pub(crate)`) in macros using the `vis` specifier.][53370] -- [Non-macro attributes now allow all forms of literals not just - strings.][53044] e.g. Previously you would write `#[attr("true")]` you can now +- [Non-macro attributes now allow all forms of literals, not just + strings.][53044] Previously, you would write `#[attr("true")]`, and you can now write `#[attr(true)]`. - [You can now specify a function to handle a panic in the Rust runtime with the `#[panic_handler]` attribute.][51366] @@ -54,9 +54,9 @@ Stabilized APIs - [`Ipv6Addr::UNSPECIFIED`] - [`Iterator::find_map`] - The following methods are a replacement methods for `trim_left`, `trim_right`, - `trim_left_matches`, and `trim_right_matches`. Which will be deprecated - in 1.33.0. + The following methods are replacement methods for `trim_left`, `trim_right`, + `trim_left_matches`, and `trim_right_matches`, which will be deprecated + in 1.33.0: - [`str::trim_end_matches`] - [`str::trim_end`] - [`str::trim_start_matches`] @@ -76,12 +76,12 @@ Misc ---- - [`rustdoc` allows you to specify what edition to treat your code as with the `--edition` option.][54057] -- [`rustdoc` now has the `--color` (Specify whether to output color) and - `--error-format` (Specify error format e.g. `json`) options.][53003] +- [`rustdoc` now has the `--color` (specify whether to output color) and + `--error-format` (specify error format, e.g. `json`) options.][53003] - [We now distribute a `rust-gdbgui` script that invokes `gdbgui` with Rust debug symbols.][53774] - [Attributes from Rust tools such as `rustfmt` or `clippy` are now - available.][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item. + available,][53459] e.g. `#[rustfmt::skip]` will skip formatting the next item. [50911]: https://github.com/rust-lang/rust/pull/50911/ [51363]: https://github.com/rust-lang/rust/pull/51363/ @@ -153,7 +153,7 @@ Compiler Libraries --------- -- [`Once::call_once` now no longer requires `Once` to be `'static`.][52239] +- [`Once::call_once` no longer requires `Once` to be `'static`.][52239] - [`BuildHasherDefault` now implements `PartialEq` and `Eq`.][52402] - [`Box`, `Box`, and `Box` now implement `Clone`.][51912] - [Implemented `PartialEq<&str>` for `OsString` and `PartialEq` @@ -169,10 +169,10 @@ Stabilized APIs Cargo ----- -- [Cargo can silently fix some bad lockfiles ][cargo/5831] You can use - `--locked` to disable this behaviour. +- [Cargo can silently fix some bad lockfiles.][cargo/5831] You can use + `--locked` to disable this behavior. - [`cargo-install` will now allow you to cross compile an install - using `--target`][cargo/5614] + using `--target`.][cargo/5614] - [Added the `cargo-fix` subcommand to automatically move project code from 2015 edition to 2018.][cargo/5723] - [`cargo doc` can now optionally document private types using the @@ -184,15 +184,15 @@ Misc the specified level to that level.][52354] For example `--cap-lints warn` will demote `deny` and `forbid` lints to `warn`. - [`rustc` and `rustdoc` will now have the exit code of `1` if compilation - fails, and `101` if there is a panic.][52197] + fails and `101` if there is a panic.][52197] - [A preview of clippy has been made available through rustup.][51122] - You can install the preview with `rustup component add clippy-preview` + You can install the preview with `rustup component add clippy-preview`. Compatibility Notes ------------------- - [`str::{slice_unchecked, slice_unchecked_mut}` are now deprecated.][51807] Use `str::get_unchecked(begin..end)` instead. -- [`std::env::home_dir` is now deprecated for its unintuitive behaviour.][51656] +- [`std::env::home_dir` is now deprecated for its unintuitive behavior.][51656] Consider using the `home_dir` function from https://crates.io/crates/dirs instead. - [`rustc` will no longer silently ignore invalid data in target spec.][52330] @@ -432,7 +432,7 @@ Language be used as an identifier. - [The dyn syntax is now available.][49968] This syntax is equivalent to the bare `Trait` syntax, and should make it clearer when being used in tandem with - `impl Trait`. Since it is equivalent to the following syntax: + `impl Trait` because it is equivalent to the following syntax: `&Trait == &dyn Trait`, `&mut Trait == &mut dyn Trait`, and `Box == Box`. - [Attributes on generic parameters such as types and lifetimes are @@ -495,10 +495,10 @@ Cargo a different directory than `target` for placing compilation artifacts. - [Cargo will be adding automatic target inference for binaries, benchmarks, examples, and tests in the Rust 2018 edition.][cargo/5335] If your project specifies - specific targets e.g. using `[[bin]]` and have other binaries in locations + specific targets, e.g. using `[[bin]]`, and have other binaries in locations where cargo would infer a binary, Cargo will produce a warning. You can - disable this feature ahead of time by setting any of the following `autobins`, - `autobenches`, `autoexamples`, `autotests` to false. + disable this feature ahead of time by setting any of the following to false: + `autobins`, `autobenches`, `autoexamples`, `autotests`. - [Cargo will now cache compiler information.][cargo/5359] This can be disabled by setting `CARGO_CACHE_RUSTC_INFO=0` in your environment. @@ -514,8 +514,8 @@ Compatibility Notes work.][49896] e.g. `::core::prelude::v1::StrExt::is_empty("")` will not compile, `"".is_empty()` will still compile. - [`Debug` output on `atomic::{AtomicBool, AtomicIsize, AtomicPtr, AtomicUsize}` - will only print the inner type.][48553] e.g. - `print!("{:?}", AtomicBool::new(true))` will print `true` + will only print the inner type.][48553] E.g. + `print!("{:?}", AtomicBool::new(true))` will print `true`, not `AtomicBool(true)`. - [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you could enter higher numbers but they were not supported by LLVM. Up to 512MB @@ -578,7 +578,7 @@ Version 1.26.2 (2018-06-05) Compatibility Notes ------------------- -- [The borrow checker was fixed to avoid unsoundness when using match ergonomics][51117] +- [The borrow checker was fixed to avoid unsoundness when using match ergonomics.][51117] [51117]: https://github.com/rust-lang/rust/issues/51117 @@ -589,18 +589,18 @@ Version 1.26.1 (2018-05-29) Tools ----- -- [RLS now works on Windows][50646] -- [Rustfmt stopped badly formatting text in some cases][rustfmt/2695] +- [RLS now works on Windows.][50646] +- [Rustfmt stopped badly formatting text in some cases.][rustfmt/2695] Compatibility Notes -------- - [`fn main() -> impl Trait` no longer works for non-Termination - trait][50656] + trait.][50656] This reverts an accidental stabilization. -- [`NaN > NaN` no longer returns true in const-fn contexts][50812] -- [Prohibit using turbofish for `impl Trait` in method arguments][50950] +- [`NaN > NaN` no longer returns true in const-fn contexts.][50812] +- [Prohibit using turbofish for `impl Trait` in method arguments.][50950] [50646]: https://github.com/rust-lang/rust/issues/50646 [50656]: https://github.com/rust-lang/rust/pull/50656 @@ -616,18 +616,18 @@ Language - [Closures now implement `Copy` and/or `Clone` if all captured variables implement either or both traits.][49299] - [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813] -- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a +- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere a lifetime can be elided.][49458] - [`impl Trait` is now stable allowing you to have abstract types in returns - or in function parameters.][49255] e.g. `fn foo() -> impl Iterator` or + or in function parameters.][49255] E.g. `fn foo() -> impl Iterator` or `fn open(path: impl AsRef)`. - [Pattern matching will now automatically apply dereferences.][49394] - [128-bit integers in the form of `u128` and `i128` are now stable.][49101] - [`main` can now return `Result<(), E: Debug>`][49162] in addition to `()`. - [A lot of operations are now available in a const context.][46882] E.g. You can now index into constant arrays, reference and dereference into constants, - and use Tuple struct constructors. -- [Fixed entry slice patterns are now stable.][48516] e.g. + and use tuple struct constructors. +- [Fixed entry slice patterns are now stable.][48516] E.g. ```rust let points = [1, 2, 3, 4]; match points { @@ -1052,7 +1052,7 @@ Language Compiler -------- - [Enabled `TrapUnreachable` in LLVM which should mitigate the impact of - undefined behaviour.][45920] + undefined behavior.][45920] - [rustc now suggests renaming import if names clash.][45660] - [Display errors/warnings correctly when there are zero-width or wide characters.][45711] From 4972beaf65cad992a6ed791fdefe90e46c09aa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 22 Oct 2018 18:21:55 +0200 Subject: [PATCH 35/37] fix typos in various places --- src/bootstrap/bootstrap.py | 2 +- src/etc/lldb_rust_formatters.py | 2 +- src/liballoc/collections/btree/map.rs | 2 +- src/libcore/alloc.rs | 2 +- src/libcore/intrinsics.rs | 2 +- src/libcore/pin.rs | 2 +- src/libcore/ptr.rs | 2 +- src/librustc/hir/def_id.rs | 4 ++-- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/diagnostics.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/memory.rs | 6 +++--- src/librustc_mir/interpret/operand.rs | 4 ++-- src/librustc_mir/interpret/validity.rs | 4 ++-- src/librustc_passes/ast_validation.rs | 16 ++++++++-------- src/librustc_target/abi/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/once.rs | 4 ++-- src/libsyntax/config.rs | 4 ++-- src/test/run-pass/issues/issue-18804/main.rs | 2 +- .../ui/block-result/unexpected-return-on-unit.rs | 2 +- .../cfg-attr-multi-false.rs | 2 +- .../ui/nll/issue-21232-partial-init-and-use.rs | 2 +- ...52059-report-when-borrow-and-drop-conflict.rs | 2 +- src/test/ui/resolve/token-error-correct-2.rs | 2 +- src/test/ui/resolve/token-error-correct-3.rs | 2 +- src/test/ui/resolve/token-error-correct.rs | 2 +- .../syntax-ambiguity-2015.rs | 12 ++++++------ .../syntax-ambiguity-2015.stderr | 12 ++++++------ .../syntax-ambiguity-2018.rs | 12 ++++++------ .../syntax-ambiguity-2018.stderr | 12 ++++++------ .../rust-2018/edition-lint-infer-outlives.fixed | 2 +- .../ui/rust-2018/edition-lint-infer-outlives.rs | 2 +- src/test/ui/specialization/issue-52050.rs | 2 +- src/tools/tidy/src/pal.rs | 2 +- 43 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c27f4f056d747..ffc5adbebb34f 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -594,7 +594,7 @@ def exe_suffix(): return '' def bootstrap_binary(self): - """Return the path of the boostrap binary + """Return the path of the bootstrap binary >>> rb = RustBuild() >>> rb.build_dir = "build" diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py index 4427313f9e5b3..2bbd4372721cb 100644 --- a/src/etc/lldb_rust_formatters.py +++ b/src/etc/lldb_rust_formatters.py @@ -277,7 +277,7 @@ def print_std_string_val(val, internal_dict): #=-------------------------------------------------------------------------------------------------- def print_array_of_values(array_name, data_ptr_val, length, internal_dict): - """Prints a contigous memory range, interpreting it as values of the + """Prints a contiguous memory range, interpreting it as values of the pointee-type of data_ptr_val.""" data_ptr_type = data_ptr_val.type diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8c950cd06d9e3..24c8fd3a969ca 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -77,7 +77,7 @@ use self::Entry::*; /// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); /// movie_reviews.insert("Pulp Fiction", "Masterpiece."); /// movie_reviews.insert("The Godfather", "Very enjoyable."); -/// movie_reviews.insert("The Blues Brothers", "Eye lyked it alot."); +/// movie_reviews.insert("The Blues Brothers", "Eye lyked it a lot."); /// /// // check for a specific one. /// if !movie_reviews.contains_key("Les Misérables") { diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 35e4eea756d41..4efcaae59b012 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -518,7 +518,7 @@ pub unsafe trait GlobalAlloc { /// The block is described by the given `ptr` pointer and `layout`. /// /// If this returns a non-null pointer, then ownership of the memory block - /// referenced by `ptr` has been transferred to this alloctor. + /// referenced by `ptr` has been transferred to this allocator. /// The memory may or may not have been deallocated, /// and should be considered unusable (unless of course it was /// transferred back to the caller again via the return value of diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 56a24168e28d9..cceae9249e456 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1025,7 +1025,7 @@ extern "rust-intrinsic" { /// // to avoid problems in case something further down panics. /// src.set_len(0); /// - /// // The two regions cannot overlap becuase mutable references do + /// // The two regions cannot overlap because mutable references do /// // not alias, and two different vectors cannot own the same /// // memory. /// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 0224560af4c76..a03c080fb3f34 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -102,7 +102,7 @@ pub use marker::Unpin; /// value in place, preventing the value referenced by that pointer from being moved /// unless it implements [`Unpin`]. /// -/// See the [`pin` module] documentation for furthur explanation on pinning. +/// See the [`pin` module] documentation for further explanation on pinning. /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 1c761ba21b3ec..b699cb028842b 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -38,7 +38,7 @@ //! underlying object is live and no reference (just raw pointers) is used to //! access the same memory. //! -//! These axioms, along with careful use of [`offset`] for pointer arithmentic, +//! These axioms, along with careful use of [`offset`] for pointer arithmetic, //! are enough to correctly implement many useful things in unsafe code. Stronger guarantees //! will be provided eventually, as the [aliasing] rules are being determined. For more //! information, see the [book] as well as the section in the reference devoted diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index a09fd5df557f5..e378e1b8be0e9 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -40,7 +40,7 @@ impl ::std::fmt::Debug for CrateNum { match self { CrateNum::Index(id) => write!(fmt, "crate{}", id.private), CrateNum::Invalid => write!(fmt, "invalid crate"), - CrateNum::BuiltinMacros => write!(fmt, "bultin macros crate"), + CrateNum::BuiltinMacros => write!(fmt, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"), } } @@ -101,7 +101,7 @@ impl fmt::Display for CrateNum { match self { CrateNum::Index(id) => fmt::Display::fmt(&id.private, f), CrateNum::Invalid => write!(f, "invalid crate"), - CrateNum::BuiltinMacros => write!(f, "bultin macros crate"), + CrateNum::BuiltinMacros => write!(f, "builtin macros crate"), CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"), } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 4c2b2b2d41d1b..5054f52277870 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -632,7 +632,7 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result } //////////////////////////////////////////////////////////////////////////////// -// Methods to faciliate working with signed integers stored in a u128 +// Methods to facilitate working with signed integers stored in a u128 //////////////////////////////////////////////////////////////////////////////// pub fn sign_extend(value: u128, size: Size) -> u128 { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 62b5327ae4692..f1c5030c6419a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -469,7 +469,7 @@ pub enum BorrowKind { /// } /// /// This can't be a shared borrow because mutably borrowing (*x as Some).0 - /// should not prevent `if let None = x { ... }`, for example, becase the + /// should not prevent `if let None = x { ... }`, for example, because the /// mutating `(*x as Some).0` can't affect the discriminant of `x`. /// We can also report errors with this kind of borrow differently. Shallow, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index dc0039926448c..ea30752a820ee 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -412,7 +412,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { flags.push(("crate_local".to_owned(), None)); } - // Allow targetting all integers using `{integral}`, even if the exact type was resolved + // Allow targeting all integers using `{integral}`, even if the exact type was resolved if self_ty.is_integral() { flags.push(("_Self".to_owned(), Some("{integral}".to_owned()))); } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 169bd9a8466a0..2fe6a0377f81b 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -761,7 +761,7 @@ impl Builder<'a, 'll, 'tcx> { fty, asm, cons, volatile, alignstack, dia); Some(self.call(v, inputs, None)) } else { - // LLVM has detected an issue with our constaints, bail out + // LLVM has detected an issue with our constraints, bail out None } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7988de28b5d7b..e6e1367b592df 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -68,7 +68,7 @@ macro_rules! provide { let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() - .expect("CrateStore crated ata is not a CrateMetadata"); + .expect("CrateStore created data is not a CrateMetadata"); $compute })* diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index bc917140bbd67..9702e94a9e0f0 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -129,7 +129,7 @@ pub fn op_to_const<'tcx>( assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= op.layout.size.bytes()); let mut alloc = alloc.clone(); alloc.align = align; - // FIXME shouldnt it be the case that `mark_static_initialized` has already + // FIXME shouldn't it be the case that `mark_static_initialized` has already // interned this? I thought that is the entire point of that `FinishStatic` stuff? let alloc = ecx.tcx.intern_const_alloc(alloc); ConstValue::ByRef(ptr.alloc_id, alloc, ptr.offset) diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index bb3e4a8d8813f..56a9daf84f768 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -2279,7 +2279,7 @@ fn demo<'a>(s: &'a mut S<'a>) -> &'a mut String { let p = &mut *(*s).data; p } Note that this approach needs a reference to S with lifetime `'a`. Nothing shorter than `'a` will suffice: a shorter lifetime would imply -that after `demo` finishes excuting, something else (such as the +that after `demo` finishes executing, something else (such as the destructor!) could access `s.data` after the end of that shorter lifetime, which would again violate the `&mut`-borrow's exclusive access. diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 189388921650c..64ad4c2eec1e1 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -556,7 +556,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc )?; } } else { - // Uh, that shouln't happen... the function did not intend to return + // Uh, that shouldn't happen... the function did not intend to return return err!(Unreachable); } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 9adca6c429798..6fe490c6efc8f 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -94,7 +94,7 @@ impl<'a, 'b, 'c, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout } } -// FIXME: Really we shouldnt clone memory, ever. Snapshot machinery should instad +// FIXME: Really we shouldn't clone memory, ever. Snapshot machinery should instead // carefully copy only the reachable parts. impl<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> Clone for Memory<'a, 'mir, 'tcx, M> @@ -658,7 +658,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { } /// It is the caller's responsibility to handle undefined and pointer bytes. - /// However, this still checks that there are no relocations on the *egdes*. + /// However, this still checks that there are no relocations on the *edges*. #[inline] fn get_bytes_with_undef_and_ptr( &self, @@ -1098,7 +1098,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(()) } - /// Error if there are relocations overlapping with the egdes of the + /// Error if there are relocations overlapping with the edges of the /// given memory range. #[inline] fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 71b2f4b53a60c..021e2d58f84b1 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -357,14 +357,14 @@ fn from_known_layout<'tcx>( } impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { - /// Try reading a value in memory; this is interesting particularily for ScalarPair. + /// Try reading a value in memory; this is interesting particularly for ScalarPair. /// Return None if the layout does not permit loading this as a value. pub(super) fn try_read_value_from_mplace( &self, mplace: MPlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx, Option>> { if mplace.layout.is_unsized() { - // Dont touch unsized + // Don't touch unsized return Ok(None); } let (ptr, ptr_align) = mplace.to_scalar_ptr_align(); diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 38cf79d8fa0b9..ac1ba0edc3b3b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -230,7 +230,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ), } } - // non-ZST also have to be dereferencable + // non-ZST also have to be dereferenceable if size != Size::ZERO { let ptr = try_validation!(place.ptr.to_ptr(), "integer pointer in non-ZST reference", path); @@ -272,7 +272,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // FIXME: Check if the signature matches } // This should be all the primitive types - ty::Never => bug!("Uninhabited type should have been catched earlier"), + ty::Never => bug!("Uninhabited type should have been caught earlier"), _ => bug!("Unexpected primitive type {}", value.layout.ty) } Ok(()) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index f6ace57f5e0fb..0e9596244cd58 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -166,12 +166,12 @@ impl<'a> AstValidator<'a> { } } - /// With eRFC 2497, we need to check whether an expression is ambigious and warn or error + /// With eRFC 2497, we need to check whether an expression is ambiguous and warn or error /// depending on the edition, this function handles that. fn while_if_let_ambiguity(&self, expr: &P) { if let Some((span, op_kind)) = self.while_if_let_expr_ambiguity(&expr) { let mut err = self.err_handler().struct_span_err( - span, &format!("ambigious use of `{}`", op_kind.to_string()) + span, &format!("ambiguous use of `{}`", op_kind.to_string()) ); err.note( @@ -193,9 +193,9 @@ impl<'a> AstValidator<'a> { } /// With eRFC 2497 adding if-let chains, there is a requirement that the parsing of - /// `&&` and `||` in a if-let statement be unambigious. This function returns a span and - /// a `BinOpKind` (either `&&` or `||` depending on what was ambigious) if it is determined - /// that the current expression parsed is ambigious and will break in future. + /// `&&` and `||` in a if-let statement be unambiguous. This function returns a span and + /// a `BinOpKind` (either `&&` or `||` depending on what was ambiguous) if it is determined + /// that the current expression parsed is ambiguous and will break in future. fn while_if_let_expr_ambiguity(&self, expr: &P) -> Option<(Span, BinOpKind)> { debug!("while_if_let_expr_ambiguity: expr.node: {:?}", expr.node); match &expr.node { @@ -203,12 +203,12 @@ impl<'a> AstValidator<'a> { Some((expr.span, op.node)) }, ExprKind::Range(ref lhs, ref rhs, _) => { - let lhs_ambigious = lhs.as_ref() + let lhs_ambiguous = lhs.as_ref() .and_then(|lhs| self.while_if_let_expr_ambiguity(lhs)); - let rhs_ambigious = rhs.as_ref() + let rhs_ambiguous = rhs.as_ref() .and_then(|rhs| self.while_if_let_expr_ambiguity(rhs)); - lhs_ambigious.or(rhs_ambigious) + lhs_ambiguous.or(rhs_ambiguous) } _ => None, } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 6b28fd091748f..1a5d2801af0c5 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -430,7 +430,7 @@ impl Align { } /// Lower the alignment, if necessary, such that the given offset - /// is aligned to it (the offset is a multiple of the aligment). + /// is aligned to it (the offset is a multiple of the alignment). pub fn restrict_for_offset(self, offset: Size) -> Align { self.min(Align::max_for_offset(offset)) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1c562859bb48d..77151351d08a1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5198,7 +5198,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { // If no type arguments were provided, we have to infer them. // This case also occurs as a result of some malformed input, e.g. - // a lifetime argument being given instead of a type paramter. + // a lifetime argument being given instead of a type parameter. // Using inference instead of `Error` gives better error messages. self.var_for_def(span, param) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ec773e384af38..9990d2ee2b676 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -674,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( } // if may_define_existential_type // now register the bounds on the parameters of the existential type - // so the parameters given by the function need to fulfil them + // so the parameters given by the function need to fulfill them // ```rust // existential type Foo: 'static; // fn foo() -> Foo { .. *} diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c54d9e4b47578..05a83dd307c38 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -269,7 +269,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, // exactly one (non-phantom) field has changed its // type, which we will expect to be the pointer that // is becoming fat (we could probably generalize this - // to mutiple thin pointers of the same type becoming + // to multiple thin pointers of the same type becoming // fat, but we don't). In this case: // // - `extra` has type `T` before and type `T` after diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index d69ebc1762272..a7db372a0e20a 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -97,7 +97,7 @@ //! - A **multiprocessor** system executing multiple hardware threads //! at the same time: In multi-threaded scenarios, you can use two //! kinds of primitives to deal with synchronization: -//! - [memory fences] to ensure memory accesses are made visibile to +//! - [memory fences] to ensure memory accesses are made visible to //! other CPUs in the right order. //! - [atomic operations] to ensure simultaneous access to the same //! memory location doesn't lead to undefined behavior. diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 98845e457b25c..cf9698cb2a971 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -290,8 +290,8 @@ impl Once { } /// Returns true if some `call_once` call has completed - /// successfuly. Specifically, `is_completed` will return false in - /// the following situtations: + /// successfully. Specifically, `is_completed` will return false in + /// the following situations: /// * `call_once` was not called at all, /// * `call_once` was called, but has not yet completed, /// * the `Once` instance is poisoned diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index e611eb86dc1b3..d8fb20d425008 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -96,7 +96,7 @@ impl<'a> StripUnconfigured<'a> { /// when the configuration predicate is true, or otherwise expand into an /// empty list of attributes. /// - /// Gives a compiler warning when the `cfg_attr` contains no attribtes and + /// Gives a compiler warning when the `cfg_attr` contains no attributes and /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { @@ -138,7 +138,7 @@ impl<'a> StripUnconfigured<'a> { }; // Check feature gate and lint on zero attributes in source. Even if the feature is gated, - // we still compute as if it wasn't, since the emitted error will stop compilation futher + // we still compute as if it wasn't, since the emitted error will stop compilation further // along the compilation. match (expanded_attrs.len(), gate_cfg_attr_multi) { (0, false) => { diff --git a/src/test/run-pass/issues/issue-18804/main.rs b/src/test/run-pass/issues/issue-18804/main.rs index a3a5337077cc6..2abcd4b7ba99c 100644 --- a/src/test/run-pass/issues/issue-18804/main.rs +++ b/src/test/run-pass/issues/issue-18804/main.rs @@ -9,7 +9,7 @@ // except according to those terms. // run-pass -// Test for issue #18804, #[linkage] does not propagate thorugh generic +// Test for issue #18804, #[linkage] does not propagate through generic // functions. Failure results in a linker error. // ignore-asmjs no weak symbol support diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs index 3cf76365c77b1..b116888d63c10 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.rs +++ b/src/test/ui/block-result/unexpected-return-on-unit.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser (and don't spew +// Test that we do some basic error correction in the tokeniser (and don't spew // too many bogus errors). fn foo() -> usize { diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs index 84bd33fc0e7d3..ec4ee80b498a5 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -1,5 +1,5 @@ // Test that cfg_attr doesn't emit any attributes when the -// configuation variable is false. This mirrors `cfg-attr-multi-true.rs` +// configuration variable is false. This mirrors `cfg-attr-multi-true.rs` // compile-pass diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.rs b/src/test/ui/nll/issue-21232-partial-init-and-use.rs index e3ae4c0dcbe57..186ecc5482720 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.rs +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.rs @@ -66,7 +66,7 @@ impl R { fn new(f: F) -> Self { R { w: 0, f } } } // It got pretty monotonous writing the same code over and over, and I // feared I would forget details. So I abstracted some desiderata into // macros. But I left the initialization code inline, because that's -// where the errors for #54986 will be emited. +// where the errors for #54986 will be emitted. macro_rules! use_fully { (struct $s:expr) => { { diff --git a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs index fff73c6d0fa9c..eaa809d2b3706 100644 --- a/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs +++ b/src/test/ui/nll/issue-52059-report-when-borrow-and-drop-conflict.rs @@ -1,5 +1,5 @@ // rust-lang/rust#52059: Regardless of whether you are moving out of a -// Drop type or just introducing an inadvertant alias via a borrow of +// Drop type or just introducing an inadvertent alias via a borrow of // one of its fields, it is useful to be reminded of the significance // of the fact that the type implements Drop. diff --git a/src/test/ui/resolve/token-error-correct-2.rs b/src/test/ui/resolve/token-error-correct-2.rs index e49374f9ce649..55803e4034bf4 100644 --- a/src/test/ui/resolve/token-error-correct-2.rs +++ b/src/test/ui/resolve/token-error-correct-2.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser (and don't ICE). +// Test that we do some basic error correction in the tokeniser (and don't ICE). fn main() { if foo { diff --git a/src/test/ui/resolve/token-error-correct-3.rs b/src/test/ui/resolve/token-error-correct-3.rs index 8881b965f9480..fd4bbde28660e 100644 --- a/src/test/ui/resolve/token-error-correct-3.rs +++ b/src/test/ui/resolve/token-error-correct-3.rs @@ -10,7 +10,7 @@ // ignore-cloudabi no std::fs support -// Test that we do some basic error correcton in the tokeniser (and don't spew +// Test that we do some basic error correction in the tokeniser (and don't spew // too many bogus errors). pub mod raw { diff --git a/src/test/ui/resolve/token-error-correct.rs b/src/test/ui/resolve/token-error-correct.rs index 39c664e270c45..099ead93beb06 100644 --- a/src/test/ui/resolve/token-error-correct.rs +++ b/src/test/ui/resolve/token-error-correct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that we do some basic error correcton in the tokeniser. +// Test that we do some basic error correction in the tokeniser. fn main() { foo(bar(; diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs index 339d49104b021..31a34a9e6fbbb 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.rs @@ -19,22 +19,22 @@ fn main() { use std::ops::Range; if let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` if let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` while let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` if let true = false && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let true = (1 == 2) && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` // The following cases are not an error as parenthesis are used to // clarify intent: diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr index 8597294913f27..411cb99fbca19 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2015.stderr @@ -1,4 +1,4 @@ -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:21:47 | LL | if let Range { start: _, end: _ } = true..true && false { } @@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2015.rs:24:47 | LL | if let Range { start: _, end: _ } = true..true || false { } @@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:27:50 | LL | while let Range { start: _, end: _ } = true..true && false { } @@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2015.rs:30:50 | LL | while let Range { start: _, end: _ } = true..true || false { } @@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:33:19 | LL | if let true = false && false { } @@ -43,7 +43,7 @@ LL | if let true = false && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2015.rs:36:22 | LL | while let true = (1 == 2) && false { } diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs index baa90bcf8e971..99495717c3a89 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.rs @@ -19,22 +19,22 @@ fn main() { use std::ops::Range; if let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` if let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` while let Range { start: _, end: _ } = true..true && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let Range { start: _, end: _ } = true..true || false { } - //~^ ERROR ambigious use of `||` + //~^ ERROR ambiguous use of `||` if let true = false && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` while let true = (1 == 2) && false { } - //~^ ERROR ambigious use of `&&` + //~^ ERROR ambiguous use of `&&` // The following cases are not an error as parenthesis are used to // clarify intent: diff --git a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr index 86ee04747b29d..bd49abeb7b247 100644 --- a/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/syntax-ambiguity-2018.stderr @@ -1,4 +1,4 @@ -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:21:47 | LL | if let Range { start: _, end: _ } = true..true && false { } @@ -7,7 +7,7 @@ LL | if let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2018.rs:24:47 | LL | if let Range { start: _, end: _ } = true..true || false { } @@ -16,7 +16,7 @@ LL | if let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:27:50 | LL | while let Range { start: _, end: _ } = true..true && false { } @@ -25,7 +25,7 @@ LL | while let Range { start: _, end: _ } = true..true && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `||` +error: ambiguous use of `||` --> $DIR/syntax-ambiguity-2018.rs:30:50 | LL | while let Range { start: _, end: _ } = true..true || false { } @@ -34,7 +34,7 @@ LL | while let Range { start: _, end: _ } = true..true || false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:33:19 | LL | if let true = false && false { } @@ -43,7 +43,7 @@ LL | if let true = false && false { } = note: this will be a error until the `let_chains` feature is stabilized = note: see rust-lang/rust#53668 for more information -error: ambigious use of `&&` +error: ambiguous use of `&&` --> $DIR/syntax-ambiguity-2018.rs:36:22 | LL | while let true = (1 == 2) && false { } diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed index d70c847e9fe68..f13f8ef2bb4cf 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.fixed @@ -24,7 +24,7 @@ use std::fmt::{Debug, Display}; // • one generic parameter (T) bound inline // • one parameter (T) with a where clause // • two parameters (T and U), both bound inline -// • two paramters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), one bound inline, one with a where clause // • two parameters (T and U), both with where clauses // // —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1 diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs index 0e4436fe1632f..f47b3fcb9be9a 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives.rs +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives.rs @@ -24,7 +24,7 @@ use std::fmt::{Debug, Display}; // • one generic parameter (T) bound inline // • one parameter (T) with a where clause // • two parameters (T and U), both bound inline -// • two paramters (T and U), one bound inline, one with a where clause +// • two parameters (T and U), one bound inline, one with a where clause // • two parameters (T and U), both with where clauses // // —and for every permutation of 0, 1, or 2 lifetimes to outlive and 0 or 1 diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs index 70cdb4899c421..00d8d126e0573 100644 --- a/src/test/ui/specialization/issue-52050.rs +++ b/src/test/ui/specialization/issue-52050.rs @@ -12,7 +12,7 @@ // Regression test for #52050: when inserting the blanket impl `I` // into the tree, we had to replace the child node for `Foo`, which -// led to the struture of the tree being messed up. +// led to the structure of the tree being messed up. use std::iter::Iterator; diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index 69a4c09c2285d..3d5e18e37b070 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -163,7 +163,7 @@ fn check_cfgs(contents: &mut String, file: &Path, fn find_test_mod(contents: &str) -> usize { if let Some(mod_tests_idx) = contents.find("mod tests") { - // Also capture a previos line indicating "mod tests" in cfg-ed out + // Also capture a previous line indicating "mod tests" in cfg-ed out let prev_newline_idx = contents[..mod_tests_idx].rfind('\n').unwrap_or(mod_tests_idx); let prev_newline_idx = contents[..prev_newline_idx].rfind('\n'); if let Some(nl) = prev_newline_idx { From 3d9231c453a676ae298ab4e1ab2965ce77ba80da Mon Sep 17 00:00:00 2001 From: Kaz Wesley Date: Tue, 23 Oct 2018 09:39:33 -0700 Subject: [PATCH 36/37] Update stdsimd submodule Fixes a SSE2 bug. --- src/stdsimd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdsimd b/src/stdsimd index 307650500de5b..431766a3fbcfb 160000 --- a/src/stdsimd +++ b/src/stdsimd @@ -1 +1 @@ -Subproject commit 307650500de5b44dc1047dc9d15e449e09d92b57 +Subproject commit 431766a3fbcfb6dafb2d5a3866c1609bf44ee554 From f912fda9b631f980234b82cf6446c99aa74418b0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 23 Oct 2018 19:13:49 +0100 Subject: [PATCH 37/37] Add note on nonzero-sized uninhabited types --- src/librustc/ty/sty.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e017d3dd6df8e..eba9db60c3054 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1508,7 +1508,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// conservative: for some types that are uninhabited we return `false`, /// but we only return `true` for types that are definitely uninhabited. /// `ty.conservative_is_uninhabited` implies that any value of type `ty` - /// will be `Abi::Uninhabited`. + /// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero + /// size, to account for partial initialisation. See #49298 for details.) pub fn conservative_is_uninhabited(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { // FIXME(varkor): we can make this less conversative by substituting concrete // type arguments.