diff --git a/RELEASES.md b/RELEASES.md index e969b91b2b643..1f7ffb53d3cad 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -144,7 +144,7 @@ Compatibility Notes [`alloc::handle_alloc_error`]: https://doc.rust-lang.org/std/alloc/fn.handle_alloc_error.html [`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default [`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html -[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default +[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_default [`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html [`num::NonZeroUsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html [`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html diff --git a/src/Cargo.lock b/src/Cargo.lock index 8a94faf2c5294..5f0d96c9c052c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2219,6 +2219,7 @@ dependencies = [ "rustc 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", "syntax 0.0.0", @@ -2352,6 +2353,7 @@ dependencies = [ "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_metadata_utils 0.0.0", "rustc_target 0.0.0", "serialize 0.0.0", "syntax 0.0.0", @@ -2359,6 +2361,15 @@ dependencies = [ "syntax_pos 0.0.0", ] +[[package]] +name = "rustc_metadata_utils" +version = "0.0.0" +dependencies = [ + "rustc 0.0.0", + "syntax 0.0.0", + "syntax_pos 0.0.0", +] + [[package]] name = "rustc_mir" version = "0.0.0" @@ -2441,6 +2452,7 @@ dependencies = [ "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", + "rustc_metadata 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 724d3b741903f..dc0b0aaf0bb3c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -777,7 +777,7 @@ impl<'a> Builder<'a> { // compiler, but for tools we just use the precompiled libraries that // we've downloaded let use_snapshot = mode == Mode::ToolBootstrap; - assert!(!use_snapshot || stage == 0); + assert!(!use_snapshot || stage == 0 || self.local_rebuild); let maybe_sysroot = self.sysroot(compiler); let sysroot = if use_snapshot { diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index 16055078ad5eb..d876cb7f37a41 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -17,9 +17,11 @@ TOOLSTATE_FILE="$(realpath $2)" OS="$3" COMMIT="$(git rev-parse HEAD)" CHANGED_FILES="$(git diff --name-status HEAD HEAD^)" -SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))" -# ^ 1970 Jan 1st is a Thursday, and our release dates are also on Thursdays, -# thus we could divide by 604800 (7 days in seconds) directly. +SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))" +# ^ Number of days after the last promotion of beta. +# Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens. +# The Wednesday after this has value 0. +# We track this value to prevent regressing tools in the last week of the 6-week cycle. touch "$TOOLSTATE_FILE" @@ -98,7 +100,7 @@ change_toolstate() { if python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" changed; then echo 'Toolstate is not changed. Not updating.' else - if [ $SIX_WEEK_CYCLE -eq 5 ]; then + if [ $SIX_WEEK_CYCLE -ge 35 ]; then python2.7 "$CHECK_NOT" "$OS" "$TOOLSTATE_FILE" "_data/latest.json" regressed fi sed -i "1 a\\ diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins index 52a6a4d7087d1..43a66634d6d3c 160000 --- a/src/libcompiler_builtins +++ b/src/libcompiler_builtins @@ -1 +1 @@ -Subproject commit 52a6a4d7087d14a35d44a11c39c77fa79d71378d +Subproject commit 43a66634d6d3c99dcd0c814e5320bb93cfe59e05 diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 479c10c4ffbae..c8670e5ec34d3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -448,6 +448,12 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// `write_bytes`, or `copy`). Note that `*src = foo` counts as a use /// because it will attempt to drop the value previously at `*src`. /// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `read_volatile` and any write operation to the same location +/// is undefined behavior. +/// /// # Examples /// /// Basic usage: @@ -498,6 +504,12 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// +/// Just like in C, whether an operation is volatile has no bearing whatsoever +/// on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. In particular, +/// a race between a `write_volatile` and any other operation (reading or writing) +/// on the same location is undefined behavior. +/// /// # Examples /// /// Basic usage: @@ -1057,6 +1069,12 @@ impl *const T { /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `read_volatile` and any write operation to the same location + /// is undefined behavior. + /// /// # Examples /// /// Basic usage: @@ -1790,6 +1808,12 @@ impl *mut T { /// `write_bytes`, or `copy`). Note that `*self = foo` counts as a use /// because it will attempt to drop the value previously at `*self`. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `read_volatile` and any write operation to the same location + /// is undefined behavior. + /// /// # Examples /// /// Basic usage: @@ -2105,6 +2129,12 @@ impl *mut T { /// This is appropriate for initializing uninitialized memory, or overwriting /// memory that has previously been `read` from. /// + /// Just like in C, whether an operation is volatile has no bearing whatsoever + /// on questions involving concurrent access from multiple threads. Volatile + /// accesses behave exactly like non-atomic accesses in that regard. In particular, + /// a race between a `write_volatile` and any other operation (reading or writing) + /// on the same location is undefined behavior. + /// /// # Examples /// /// Basic usage: diff --git a/src/liblibc b/src/liblibc index b6d23ed45d729..8565755356f23 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit b6d23ed45d72918239c0bfac11dc547895e59b81 +Subproject commit 8565755356f23baf6b2df933ff734ce2f00c8d9b diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 54169acac46ac..0e84104245dcb 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -22,10 +22,9 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use hir::def; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; -use hir::map::definitions::{Definitions, DefKey, DefPathTable}; +use hir::map::definitions::{DefKey, DefPathTable}; use hir::svh::Svh; use ty::{self, TyCtxt}; use session::{Session, CrateDisambiguator}; @@ -34,8 +33,6 @@ use session::search_paths::PathKind; use std::any::Any; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::edition::Edition; -use syntax::ext::base::SyntaxExtension; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; @@ -140,11 +137,6 @@ pub struct ForeignModule { pub def_id: DefId, } -pub enum LoadedMacro { - MacroDef(ast::Item), - ProcMacro(Lrc), -} - #[derive(Copy, Clone, Debug)] pub struct ExternCrate { pub src: ExternCrateSource, @@ -221,9 +213,6 @@ pub trait MetadataLoader { pub trait CrateStore { fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc; - // access to the metadata loader - fn metadata_loader(&self) -> &dyn MetadataLoader; - // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; @@ -231,19 +220,11 @@ pub trait CrateStore { fn def_path_table(&self, cnum: CrateNum) -> Lrc; // "queries" used in resolve that aren't tracked for incremental compilation - fn visibility_untracked(&self, def: DefId) -> ty::Visibility; - fn export_macros_untracked(&self, cnum: CrateNum); - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind; fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition; - fn struct_field_names_untracked(&self, def: DefId) -> Vec; - fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec; - fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro; fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics; - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem; fn postorder_cnums_untracked(&self) -> Vec; // This is basically a 1-based range of ints, which is a little @@ -260,116 +241,6 @@ pub trait CrateStore { pub type CrateStoreDyn = dyn CrateStore + sync::Sync; -// FIXME: find a better place for this? -pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { - let mut err_count = 0; - { - let mut say = |s: &str| { - match (sp, sess) { - (_, None) => bug!("{}", s), - (Some(sp), Some(sess)) => sess.span_err(sp, s), - (None, Some(sess)) => sess.err(s), - } - err_count += 1; - }; - if s.is_empty() { - say("crate name must not be empty"); - } - for c in s.chars() { - if c.is_alphanumeric() { continue } - if c == '_' { continue } - say(&format!("invalid character `{}` in crate name: `{}`", c, s)); - } - } - - if err_count > 0 { - sess.unwrap().abort_if_errors(); - } -} - -/// A dummy crate store that does not support any non-local crates, -/// for test purposes. -pub struct DummyCrateStore; - -#[allow(unused_variables)] -impl CrateStore for DummyCrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc - { bug!("crate_data_as_rc_any") } - // item info - fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") } - fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics - { bug!("item_generics_cloned") } - - // trait/impl-item info - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem - { bug!("associated_item_cloned") } - - // crate metadata - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") } - fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator { - bug!("crate_disambiguator") - } - fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { bug!("crate_edition_untracked") } - - // resolve - fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") } - fn def_path(&self, def: DefId) -> hir_map::DefPath { - bug!("relative_def_path") - } - fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash { - bug!("def_path_hash") - } - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - bug!("def_path_table") - } - fn struct_field_names_untracked(&self, def: DefId) -> Vec { - bug!("struct_field_names") - } - fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec { - bug!("item_children") - } - fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") } - - fn crates_untracked(&self) -> Vec { vec![] } - - // utility functions - fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option { None } - fn encode_metadata<'a, 'tcx>(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta) - -> EncodedMetadata { - bug!("encode_metadata") - } - fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") } - fn postorder_cnums_untracked(&self) -> Vec { bug!("postorder_cnums_untracked") } - - // access to the metadata loader - fn metadata_loader(&self) -> &dyn MetadataLoader { bug!("metadata_loader") } -} - -pub trait CrateLoader { - fn process_extern_crate(&mut self, item: &ast::Item, defs: &Definitions) -> CrateNum; - - fn process_path_extern( - &mut self, - name: Symbol, - span: Span, - ) -> CrateNum; - - fn process_use_extern( - &mut self, - name: Symbol, - span: Span, - id: ast::NodeId, - defs: &Definitions, - ) -> CrateNum; - - fn postprocess(&mut self, krate: &ast::Crate); -} - // This method is used when generating the command line to pass through to // system linker. The linker expects undefined symbols on the left of the // command line to be defined in libraries on the right, not the other way diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 30f533285ddfd..a1f4a323f849e 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -20,3 +20,4 @@ rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } rustc_incremental = { path = "../librustc_incremental" } +rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index f59cf5832fcb4..3ff2388beea2a 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -37,6 +37,7 @@ extern crate rustc_incremental; extern crate syntax; extern crate syntax_pos; #[macro_use] extern crate rustc_data_structures; +extern crate rustc_metadata_utils; use rustc::ty::TyCtxt; diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index aabe931d79c57..b33482eb868ff 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -10,11 +10,12 @@ use rustc::session::config::{self, OutputFilenames, Input, OutputType}; use rustc::session::Session; -use rustc::middle::cstore::{self, LinkMeta}; +use rustc::middle::cstore::LinkMeta; use rustc::hir::svh::Svh; use std::path::{Path, PathBuf}; use syntax::{ast, attr}; use syntax_pos::Span; +use rustc_metadata_utils::validate_crate_name; pub fn out_filename(sess: &Session, crate_type: config::CrateType, @@ -61,7 +62,7 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - cstore::validate_crate_name(sess, &s, span); + validate_crate_name(sess, &s, span); s }; diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 5b1b2aadec563..c12fc22baf020 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -50,44 +50,22 @@ impl TinyList { #[inline] pub fn insert(&mut self, data: T) { - let current_head = mem::replace(&mut self.head, None); - - if let Some(current_head) = current_head { - let current_head = Box::new(current_head); - self.head = Some(Element { - data, - next: Some(current_head) - }); - } else { - self.head = Some(Element { - data, - next: None, - }) - } + self.head = Some(Element { + data, + next: mem::replace(&mut self.head, None).map(Box::new), + }); } #[inline] pub fn remove(&mut self, data: &T) -> bool { - let remove_head = if let Some(ref mut head) = self.head { - if head.data == *data { - Some(mem::replace(&mut head.next, None)) - } else { - None + self.head = match self.head { + Some(ref mut head) if head.data == *data => { + mem::replace(&mut head.next, None).map(|x| *x) } - } else { - return false + Some(ref mut head) => return head.remove_next(data), + None => return false, }; - - if let Some(remove_head) = remove_head { - if let Some(next) = remove_head { - self.head = Some(*next); - } else { - self.head = None; - } - return true - } - - self.head.as_mut().unwrap().remove_next(data) + true } #[inline] @@ -156,6 +134,8 @@ impl Element { #[cfg(test)] mod test { use super::*; + extern crate test; + use self::test::Bencher; #[test] fn test_contains_and_insert() { @@ -248,4 +228,41 @@ mod test { assert_eq!(list.len(), 0); } + + #[bench] + fn bench_insert_empty(b: &mut Bencher) { + b.iter(|| { + let mut list = TinyList::new(); + list.insert(1); + }) + } + + #[bench] + fn bench_insert_one(b: &mut Bencher) { + b.iter(|| { + let mut list = TinyList::new_single(0); + list.insert(1); + }) + } + + #[bench] + fn bench_remove_empty(b: &mut Bencher) { + b.iter(|| { + TinyList::new().remove(&1) + }); + } + + #[bench] + fn bench_remove_unknown(b: &mut Bencher) { + b.iter(|| { + TinyList::new_single(0).remove(&1) + }); + } + + #[bench] + fn bench_remove_one(b: &mut Bencher) { + b.iter(|| { + TinyList::new_single(1).remove(&1) + }); + } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f178f847aa51e..2c877e27e2ea7 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -20,7 +20,6 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::CrateStoreDyn; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, AllArenas, Resolutions, TyCtxt}; use rustc::traits; @@ -484,7 +483,7 @@ impl<'a> ::CompilerCalls<'a> for CompileController<'a> { codegen_backend: &dyn (::CodegenBackend), matches: &::getopts::Matches, sess: &Session, - cstore: &dyn (::CrateStore), + cstore: &CStore, input: &Input, odir: &Option, ofile: &Option, @@ -728,9 +727,9 @@ pub struct ExpansionResult { pub hir_forest: hir_map::Forest, } -pub struct InnerExpansionResult<'a> { +pub struct InnerExpansionResult<'a, 'b: 'a> { pub expanded_crate: ast::Crate, - pub resolver: Resolver<'a>, + pub resolver: Resolver<'a, 'b>, pub hir_forest: hir_map::Forest, } @@ -806,7 +805,7 @@ where /// Same as phase_2_configure_and_expand, but doesn't let you keep the resolver /// around -pub fn phase_2_configure_and_expand_inner<'a, F>( +pub fn phase_2_configure_and_expand_inner<'a, 'b: 'a, F>( sess: &'a Session, cstore: &'a CStore, mut krate: ast::Crate, @@ -815,9 +814,9 @@ pub fn phase_2_configure_and_expand_inner<'a, F>( addl_plugins: Option>, make_glob_map: MakeGlobMap, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a mut CrateLoader, + crate_loader: &'a mut CrateLoader<'b>, after_expand: F, -) -> Result, CompileIncomplete> +) -> Result, CompileIncomplete> where F: FnOnce(&ast::Crate) -> CompileResult, { @@ -1209,7 +1208,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>( codegen_backend: &dyn CodegenBackend, control: &CompileController, sess: &'tcx Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: hir_map::Map<'tcx>, mut analysis: ty::CrateAnalysis, resolutions: Resolutions, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index df641b8fbc0fe..556ee9f5716ea 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -20,6 +20,7 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] +#![feature(option_replace)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] @@ -78,7 +79,6 @@ use rustc::session::filesearch; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; -use rustc::middle::cstore::CrateStore; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc_metadata::dynamic_lib::DynamicLibrary; @@ -676,7 +676,7 @@ pub trait CompilerCalls<'a> { _: &dyn CodegenBackend, _: &getopts::Matches, _: &Session, - _: &dyn CrateStore, + _: &CStore, _: &Input, _: &Option, _: &Option) @@ -884,7 +884,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { codegen_backend: &dyn CodegenBackend, matches: &getopts::Matches, sess: &Session, - cstore: &dyn CrateStore, + cstore: &CStore, input: &Input, odir: &Option, ofile: &Option) @@ -990,7 +990,7 @@ pub fn enable_save_analysis(control: &mut CompileController) { impl RustcDefaultCalls { pub fn list_metadata(sess: &Session, - cstore: &dyn CrateStore, + cstore: &CStore, matches: &getopts::Matches, input: &Input) -> Compilation { @@ -1002,7 +1002,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - cstore.metadata_loader(), + &*cstore.metadata_loader, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 6433a93a317a6..3e74aef9e7345 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -20,11 +20,11 @@ use {abort_on_err, driver}; use rustc::ty::{self, TyCtxt, Resolutions, AllArenas}; use rustc::cfg; use rustc::cfg::graphviz::LabelledCFG; -use rustc::middle::cstore::CrateStoreDyn; use rustc::session::Session; use rustc::session::config::{Input, OutputFilenames}; use rustc_borrowck as borrowck; use rustc_borrowck::graphviz as borrowck_dot; +use rustc_metadata::cstore::CStore; use rustc_mir::util::{write_mir_pretty, write_mir_graphviz}; @@ -33,6 +33,7 @@ use syntax::fold::{self, Folder}; use syntax::print::{pprust}; use syntax::print::pprust::PrintState; use syntax::ptr::P; +use syntax::util::ThinVec; use syntax::util::small_vector::SmallVector; use syntax_pos::{self, FileName}; @@ -199,7 +200,7 @@ impl PpSourceMode { } fn call_with_pp_support_hir<'tcx, A, F>(&self, sess: &'tcx Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -650,18 +651,25 @@ impl UserIdentifiedItem { // [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop<'a> { within_static_or_const: bool, + nested_blocks: Option>, sess: &'a Session, } impl<'a> ReplaceBodyWithLoop<'a> { pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> { - ReplaceBodyWithLoop { within_static_or_const: false, sess } + ReplaceBodyWithLoop { + within_static_or_const: false, + nested_blocks: None, + sess + } } fn run R>(&mut self, is_const: bool, action: F) -> R { let old_const = mem::replace(&mut self.within_static_or_const, is_const); + let old_blocks = self.nested_blocks.take(); let ret = action(self); self.within_static_or_const = old_const; + self.nested_blocks = old_blocks; ret } @@ -739,42 +747,88 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { self.run(is_const, |s| fold::noop_fold_impl_item(i, s)) } + fn fold_anon_const(&mut self, c: ast::AnonConst) -> ast::AnonConst { + self.run(true, |s| fold::noop_fold_anon_const(c, s)) + } + fn fold_block(&mut self, b: P) -> P { - fn expr_to_block(rules: ast::BlockCheckMode, + fn stmt_to_block(rules: ast::BlockCheckMode, recovered: bool, - e: Option>, - sess: &Session) -> P { - P(ast::Block { - stmts: e.map(|e| { - ast::Stmt { - id: sess.next_node_id(), - span: e.span, - node: ast::StmtKind::Expr(e), - } - }) - .into_iter() - .collect(), + s: Option, + sess: &Session) -> ast::Block { + ast::Block { + stmts: s.into_iter().collect(), rules, id: sess.next_node_id(), span: syntax_pos::DUMMY_SP, recovered, - }) + } } - if !self.within_static_or_const { - - let empty_block = expr_to_block(BlockCheckMode::Default, false, None, self.sess); - let loop_expr = P(ast::Expr { - node: ast::ExprKind::Loop(empty_block, None), - id: self.sess.next_node_id(), + fn block_to_stmt(b: ast::Block, sess: &Session) -> ast::Stmt { + let expr = P(ast::Expr { + id: sess.next_node_id(), + node: ast::ExprKind::Block(P(b), None), span: syntax_pos::DUMMY_SP, - attrs: ast::ThinVec::new(), + attrs: ThinVec::new(), }); - expr_to_block(b.rules, b.recovered, Some(loop_expr), self.sess) + ast::Stmt { + id: sess.next_node_id(), + node: ast::StmtKind::Expr(expr), + span: syntax_pos::DUMMY_SP, + } + } - } else { + let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess); + let loop_expr = P(ast::Expr { + node: ast::ExprKind::Loop(P(empty_block), None), + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + attrs: ast::ThinVec::new(), + }); + + let loop_stmt = ast::Stmt { + id: self.sess.next_node_id(), + span: syntax_pos::DUMMY_SP, + node: ast::StmtKind::Expr(loop_expr), + }; + + if self.within_static_or_const { fold::noop_fold_block(b, self) + } else { + b.map(|b| { + let mut stmts = vec![]; + for s in b.stmts { + let old_blocks = self.nested_blocks.replace(vec![]); + + stmts.extend(self.fold_stmt(s).into_iter().filter(|s| s.is_item())); + + // we put a Some in there earlier with that replace(), so this is valid + let new_blocks = self.nested_blocks.take().unwrap(); + self.nested_blocks = old_blocks; + stmts.extend(new_blocks.into_iter().map(|b| block_to_stmt(b, &self.sess))); + } + + let mut new_block = ast::Block { + stmts, + ..b + }; + + if let Some(old_blocks) = self.nested_blocks.as_mut() { + //push our fresh block onto the cache and yield an empty block with `loop {}` + if !new_block.stmts.is_empty() { + old_blocks.push(new_block); + } + + stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess) + } else { + //push `loop {}` onto the end of our fresh block and yield that + new_block.stmts.push(loop_stmt); + + new_block + } + }) } } @@ -918,7 +972,7 @@ pub fn print_after_parsing(sess: &Session, } pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'tcx CrateStoreDyn, + cstore: &'tcx CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, @@ -1074,7 +1128,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, // with a different callback than the standard driver, so that isn't easy. // Instead, we call that function ourselves. fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session, - cstore: &'a CrateStoreDyn, + cstore: &'a CStore, hir_map: &hir_map::Map<'tcx>, analysis: &ty::CrateAnalysis, resolutions: &Resolutions, diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 338824d5efe4c..6142fe78149ce 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -20,3 +20,4 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } +rustc_metadata_utils = { path = "../librustc_metadata_utils" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 4f808dee61f21..b5b47fb35dc21 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -24,12 +24,13 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle; -use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; +use rustc_metadata_utils::validate_crate_name; + use std::ops::Deref; use std::path::PathBuf; use std::{cmp, fs}; @@ -1056,8 +1057,8 @@ impl<'a> CrateLoader<'a> { } } -impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { - fn postprocess(&mut self, krate: &ast::Crate) { +impl<'a> CrateLoader<'a> { + pub fn postprocess(&mut self, krate: &ast::Crate) { // inject the sanitizer runtime before the allocator runtime because all // sanitizers force the use of the `alloc_system` allocator self.inject_sanitizer_runtime(); @@ -1070,7 +1071,9 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - fn process_extern_crate(&mut self, item: &ast::Item, definitions: &Definitions) -> CrateNum { + pub fn process_extern_crate( + &mut self, item: &ast::Item, definitions: &Definitions, + ) -> CrateNum { match item.node { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", @@ -1113,7 +1116,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { } } - fn process_path_extern( + pub fn process_path_extern( &mut self, name: Symbol, span: Span, @@ -1137,7 +1140,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { cnum } - fn process_use_extern( + pub fn process_use_extern( &mut self, name: Symbol, span: Span, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index d93a7f9526e1a..2d3e3080c89e3 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -93,6 +93,11 @@ pub struct CStore { pub metadata_loader: Box, } +pub enum LoadedMacro { + MacroDef(ast::Item), + ProcMacro(Lrc), +} + impl CStore { pub fn new(metadata_loader: Box) -> CStore { CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e3a7918f8c589..916c0920e0b4b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cstore; +use cstore::{self, LoadedMacro}; use encoder; use link_args; use native_libs; @@ -17,8 +17,8 @@ use schema; use rustc::ty::query::QueryConfig; use rustc::middle::cstore::{CrateStore, DepKind, - MetadataLoader, LinkMeta, - LoadedMacro, EncodedMetadata, NativeLibraryKind}; + LinkMeta, + EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; @@ -411,36 +411,8 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { }; } -impl CrateStore for cstore::CStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { - self.get_crate_data(krate) - } - - fn metadata_loader(&self) -> &dyn MetadataLoader { - &*self.metadata_loader - } - - fn visibility_untracked(&self, def: DefId) -> ty::Visibility { - self.get_crate_data(def.krate).get_visibility(def.index) - } - - fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { - self.get_crate_data(def.krate).get_generics(def.index, sess) - } - - fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem - { - self.get_crate_data(def.krate).get_associated_item(def.index) - } - - fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind - { - let data = self.get_crate_data(cnum); - let r = *data.dep_kind.lock(); - r - } - - fn export_macros_untracked(&self, cnum: CrateNum) { +impl cstore::CStore { + pub fn export_macros_untracked(&self, cnum: CrateNum) { let data = self.get_crate_data(cnum); let mut dep_kind = data.dep_kind.lock(); if *dep_kind == DepKind::UnexportedMacrosOnly { @@ -448,69 +420,28 @@ impl CrateStore for cstore::CStore { } } - fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol - { - self.get_crate_data(cnum).name - } - - fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator - { - self.get_crate_data(cnum).root.disambiguator - } - - fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh - { - self.get_crate_data(cnum).root.hash + pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { + let data = self.get_crate_data(cnum); + let r = *data.dep_kind.lock(); + r } - fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition - { + pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { self.get_crate_data(cnum).root.edition } - /// Returns the `DefKey` for a given `DefId`. This indicates the - /// parent `DefId` as well as some idea of what kind of data the - /// `DefId` refers to. - fn def_key(&self, def: DefId) -> DefKey { - // Note: loading the def-key (or def-path) for a def-id is not - // a *read* of its metadata. This is because the def-id is - // really just an interned shorthand for a def-path, which is the - // canonical name for an item. - // - // self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).def_key(def.index) - } - - fn def_path(&self, def: DefId) -> DefPath { - // See `Note` above in `def_key()` for why this read is - // commented out: - // - // self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).def_path(def.index) - } - - fn def_path_hash(&self, def: DefId) -> DefPathHash { - self.get_crate_data(def.krate).def_path_hash(def.index) - } - - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - self.get_crate_data(cnum).def_path_table.clone() - } - - fn struct_field_names_untracked(&self, def: DefId) -> Vec - { + pub fn struct_field_names_untracked(&self, def: DefId) -> Vec { self.get_crate_data(def.krate).get_struct_field_names(def.index) } - fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec - { + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate) .each_child_of_item(def_id.index, |child| result.push(child), sess); result } - fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { + pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); @@ -559,6 +490,64 @@ impl CrateStore for cstore::CStore { }) } + pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem { + self.get_crate_data(def.krate).get_associated_item(def.index) + } +} + +impl CrateStore for cstore::CStore { + fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { + self.get_crate_data(krate) + } + + fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { + self.get_crate_data(def.krate).get_generics(def.index, sess) + } + + fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol + { + self.get_crate_data(cnum).name + } + + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator + { + self.get_crate_data(cnum).root.disambiguator + } + + fn crate_hash_untracked(&self, cnum: CrateNum) -> hir::svh::Svh + { + self.get_crate_data(cnum).root.hash + } + + /// Returns the `DefKey` for a given `DefId`. This indicates the + /// parent `DefId` as well as some idea of what kind of data the + /// `DefId` refers to. + fn def_key(&self, def: DefId) -> DefKey { + // Note: loading the def-key (or def-path) for a def-id is not + // a *read* of its metadata. This is because the def-id is + // really just an interned shorthand for a def-path, which is the + // canonical name for an item. + // + // self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).def_key(def.index) + } + + fn def_path(&self, def: DefId) -> DefPath { + // See `Note` above in `def_key()` for why this read is + // commented out: + // + // self.dep_graph.read(DepNode::MetaData(def)); + self.get_crate_data(def.krate).def_path(def.index) + } + + fn def_path_hash(&self, def: DefId) -> DefPathHash { + self.get_crate_data(def.krate).def_path_hash(def.index) + } + + fn def_path_table(&self, cnum: CrateNum) -> Lrc { + self.get_crate_data(cnum).def_path_table.clone() + } + fn crates_untracked(&self) -> Vec { let mut result = vec![]; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 5cba0387d17bb..798b631989bd5 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -37,6 +37,7 @@ extern crate serialize as rustc_serialize; // used by deriving extern crate rustc_errors as errors; extern crate syntax_ext; extern crate proc_macro; +extern crate rustc_metadata_utils; #[macro_use] extern crate rustc; diff --git a/src/librustc_metadata_utils/Cargo.toml b/src/librustc_metadata_utils/Cargo.toml new file mode 100644 index 0000000000000..4a5e20376bfb5 --- /dev/null +++ b/src/librustc_metadata_utils/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_metadata_utils" +version = "0.0.0" + +[lib] +name = "rustc_metadata_utils" +path = "lib.rs" +crate-type = ["dylib"] + +[dependencies] +rustc = { path = "../librustc" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata_utils/lib.rs b/src/librustc_metadata_utils/lib.rs new file mode 100644 index 0000000000000..a1e5150390ac1 --- /dev/null +++ b/src/librustc_metadata_utils/lib.rs @@ -0,0 +1,42 @@ +// 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. + +#[macro_use] +extern crate rustc; +extern crate syntax_pos; + +use rustc::session::Session; +use syntax_pos::Span; + +pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option) { + let mut err_count = 0; + { + let mut say = |s: &str| { + match (sp, sess) { + (_, None) => bug!("{}", s), + (Some(sp), Some(sess)) => sess.span_err(sp, s), + (None, Some(sess)) => sess.err(s), + } + err_count += 1; + }; + if s.is_empty() { + say("crate name must not be empty"); + } + for c in s.chars() { + if c.is_alphanumeric() { continue } + if c == '_' { continue } + say(&format!("invalid character `{}` in crate name: `{}`", c, s)); + } + } + + if err_count > 0 { + sess.unwrap().abort_if_errors(); + } +} diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index e2ac7dde55854..aabed6686858f 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -10,13 +10,14 @@ use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; +use rustc::mir::VarBindingForm; use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; -use rustc::mir::VarBindingForm; use rustc::ty; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; +use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; use super::borrow_set::BorrowData; @@ -30,12 +31,17 @@ use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_of_moved_or_uninitialized( &mut self, - _context: Context, + context: Context, desired_action: InitializationRequiringAction, (place, span): (&Place<'tcx>, Span), mpi: MovePathIndex, curr_move_out: &FlowAtLocation>, ) { + let use_spans = self + .move_spans(place, context.loc) + .or_else(|| self.borrow_spans(span, context.loc)); + let span = use_spans.args_or_use(); + let mois = self.move_data.path_map[mpi] .iter() .filter(|moi| curr_move_out.contains(moi)) @@ -58,16 +64,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; - let mut err = self.tcx - .cannot_act_on_uninitialized_variable( - span, - desired_action.as_noun(), - &self - .describe_place_with_options(place, IncludingDowncast(true)) - .unwrap_or("_".to_owned()), - Origin::Mir, - ); + let mut err = self.tcx.cannot_act_on_uninitialized_variable( + span, + desired_action.as_noun(), + &self + .describe_place_with_options(place, IncludingDowncast(true)) + .unwrap_or("_".to_owned()), + Origin::Mir, + ); err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + err.buffer(&mut self.errors_buffer); } else { let msg = ""; //FIXME: add "partially " or "collaterally " @@ -82,11 +93,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut is_loop_move = false; for moi in &mois { - let move_msg = ""; //FIXME: add " (into closure)" - let move_span = self - .mir - .source_info(self.move_data.moves[**moi].source) - .span; + let move_out = self.move_data.moves[**moi]; + let moved_place = &self.move_data.move_paths[move_out.path].place; + + let move_spans = self.move_spans(moved_place, move_out.source); + let move_span = move_spans.args_or_use(); + + let move_msg = if move_spans.for_closure() { + " into closure" + } else { + "" + }; + if span == move_span { err.span_label( span, @@ -95,8 +113,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { is_loop_move = true; } else { err.span_label(move_span, format!("value moved{} here", move_msg)); + move_spans.var_span_label(&mut err, "variable moved due to use in closure"); }; } + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use in closure", desired_action.as_noun()), + ); + if !is_loop_move { err.span_label( span, @@ -150,7 +175,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_move_out_while_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; @@ -162,16 +187,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Some(name) => format!("`{}`", name), None => "value".to_owned(), }; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + let move_spans = self.move_spans(place, context.loc); + let span = move_spans.args_or_use(); + let mut err = tcx.cannot_move_when_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); - err.span_label( - self.retrieve_borrow_span(borrow), - format!("borrow of {} occurs here", borrow_msg), - ); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); + + borrow_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + + move_spans.var_span_label(&mut err, "move occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); err.buffer(&mut self.errors_buffer); } @@ -179,92 +213,38 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(super) fn report_use_while_mutably_borrowed( &mut self, context: Context, - (place, span): (&Place<'tcx>, Span), + (place, _span): (&Place<'tcx>, Span), borrow: &BorrowData<'tcx>, ) { let tcx = self.tcx; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + // Conflicting borrows are reported separately, so only check for move + // captures. + let use_spans = self.move_spans(place, context.loc); + let span = use_spans.var_or_use(); + let mut err = tcx.cannot_use_when_mutably_borrowed( span, &self.describe_place(place).unwrap_or("_".to_owned()), - self.retrieve_borrow_span(borrow), + borrow_span, &self .describe_place(&borrow.borrowed_place) .unwrap_or("_".to_owned()), Origin::Mir, ); - self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); - } - - /// Finds the span of arguments of a closure (within `maybe_closure_span`) and its usage of - /// the local assigned at `location`. - /// This is done by searching in statements succeeding `location` - /// and originating from `maybe_closure_span`. - pub(super) fn find_closure_span( - &self, - maybe_closure_span: Span, - location: Location, - ) -> Option<(Span, Span)> { - use rustc::hir::ExprKind::Closure; - use rustc::mir::AggregateKind; - - let local = match self.mir[location.block] - .statements - .get(location.statement_index) - { - Some(&Statement { - kind: StatementKind::Assign(Place::Local(local), _), - .. - }) => local, - _ => return None, - }; - - for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { - if maybe_closure_span != stmt.source_info.span { - break; - } + borrow_spans.var_span_label(&mut err, { + let place = &borrow.borrowed_place; + let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { - if let AggregateKind::Closure(def_id, _) = **kind { - debug!("find_closure_span: found closure {:?}", places); + format!("borrow occurs due to use of `{}` in closure", desc_place) + }); - return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { - let args_span = if let Closure(_, _, _, span, _) = - self.tcx.hir.expect_expr(node_id).node - { - span - } else { - return None; - }; - - self.tcx - .with_freevars(node_id, |freevars| { - for (v, place) in freevars.iter().zip(places) { - match *place { - Operand::Copy(Place::Local(l)) - | Operand::Move(Place::Local(l)) if local == l => - { - debug!( - "find_closure_span: found captured local {:?}", - l - ); - return Some(v.span); - } - _ => {} - } - } - None - }) - .map(|var_span| (args_span, var_span)) - } else { - None - }; - } - } - } - - None + self.explain_why_borrow_contains_point(context, borrow, None, &mut err); + err.buffer(&mut self.errors_buffer); } pub(super) fn report_conflicting_borrow( @@ -274,14 +254,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, ) { - let issued_span = self.retrieve_borrow_span(issued_borrow); + let issued_spans = self.retrieve_borrow_spans(issued_borrow); + let issued_span = issued_spans.args_or_use(); - let new_closure_span = self.find_closure_span(span, context.loc); - let span = new_closure_span.map(|(args, _)| args).unwrap_or(span); - let old_closure_span = self.find_closure_span(issued_span, issued_borrow.reserve_location); - let issued_span = old_closure_span - .map(|(args, _)| args) - .unwrap_or(issued_span); + let borrow_spans = self.borrow_spans(span, context.loc); + let span = borrow_spans.args_or_use(); let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); let tcx = self.tcx; @@ -368,23 +345,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) => unreachable!(), }; - if let Some((_, var_span)) = old_closure_span { - let place = &issued_borrow.borrowed_place; - let desc_place = self.describe_place(place).unwrap_or("_".to_owned()); - - err.span_label( - var_span, + if issued_spans == borrow_spans { + borrow_spans.var_span_label( + &mut err, format!( - "previous borrow occurs due to use of `{}` in closure", + "borrows occur due to use of `{}` in closure", desc_place ), ); - } + } else { + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_place(borrow_place).unwrap_or("_".to_owned()); + issued_spans.var_span_label( + &mut err, + format!( + "first borrow occurs due to use of `{}` in closure", + borrow_place_desc + ), + ); - if let Some((_, var_span)) = new_closure_span { - err.span_label( - var_span, - format!("borrow occurs due to use of `{}` in closure", desc_place), + borrow_spans.var_span_label( + &mut err, + format!("second borrow occurs due to use of `{}` in closure", desc_place), ); } @@ -407,7 +389,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .last() .unwrap(); - let borrow_span = self.mir.source_info(borrow.reserve_location).span; + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.var_or_use(); + let proper_span = match *root_place { Place::Local(local) => self.mir.local_decls[local].source_info.span, _ => drop_span, @@ -427,30 +411,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.access_place_error_reported .insert((root_place.clone(), borrow_span)); - match &self.describe_place(&borrow.borrowed_place) { - Some(name) => { - self.report_local_value_does_not_live_long_enough( - context, - name, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - kind.map(|k| (k, place_span.0)), - ); - } - None => { - self.report_temporary_value_does_not_live_long_enough( - context, - &scope_tree, - &borrow, - drop_span, - borrow_span, - proper_span, - ); - } - } + let mut err = match &self.describe_place(&borrow.borrowed_place) { + Some(name) => self.report_local_value_does_not_live_long_enough( + context, + name, + &scope_tree, + &borrow, + drop_span, + borrow_span, + proper_span, + kind.map(|k| (k, place_span.0)), + ), + None => self.report_temporary_value_does_not_live_long_enough( + context, + &scope_tree, + &borrow, + drop_span, + borrow_span, + proper_span, + ), + }; + + borrow_spans.args_span_label(&mut err, "value captured here"); + + err.buffer(&mut self.errors_buffer); } fn report_local_value_does_not_live_long_enough( @@ -463,7 +447,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow_span: Span, _proper_span: Span, kind_place: Option<(WriteKind, &Place<'tcx>)>, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -481,7 +465,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); self.explain_why_borrow_contains_point(context, borrow, kind_place, &mut err); - err.buffer(&mut self.errors_buffer); + err } fn report_temporary_value_does_not_live_long_enough( @@ -492,7 +476,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, _borrow_span: Span, proper_span: Span, - ) { + ) -> DiagnosticBuilder<'cx> { debug!( "report_temporary_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -507,7 +491,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(drop_span, "temporary value only lives until here"); self.explain_why_borrow_contains_point(context, borrow, None, &mut err); - err.buffer(&mut self.errors_buffer); + err } pub(super) fn report_illegal_mutation_of_borrowed( @@ -516,14 +500,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), loan: &BorrowData<'tcx>, ) { + let loan_spans = self.retrieve_borrow_spans(loan); + let loan_span = loan_spans.args_or_use(); + let tcx = self.tcx; let mut err = tcx.cannot_assign_to_borrowed( span, - self.retrieve_borrow_span(loan), + loan_span, &self.describe_place(place).unwrap_or("_".to_owned()), Origin::Mir, ); + loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure"); + self.explain_why_borrow_contains_point(context, loan, None, &mut err); err.buffer(&mut self.errors_buffer); @@ -556,12 +545,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // PATTERN;) then make the error refer to that local, rather than the // place being assigned later. let (place_description, assigned_span) = match local_decl { - Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Clear), .. }) - | Some(LocalDecl { is_user_variable: Some(ClearCrossCrate::Set( - BindingForm::Var(VarBindingForm { - opt_match_place: None, .. - }))), ..}) - | Some(LocalDecl { is_user_variable: None, .. }) + Some(LocalDecl { + is_user_variable: Some(ClearCrossCrate::Clear), + .. + }) + | Some(LocalDecl { + is_user_variable: + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: None, + .. + }))), + .. + }) + | Some(LocalDecl { + is_user_variable: None, + .. + }) | None => (self.describe_place(place), assigned_span), Some(decl) => (self.describe_place(err_place), decl.source_info.span), }; @@ -647,8 +646,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Projection(ref proj) => { match proj.elem { ProjectionElem::Deref => { - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -666,8 +665,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &including_downcast, )?; } else if let Place::Local(local) = proj.base { - if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) - = self.mir.local_decls[local].is_user_variable { + if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) = + self.mir.local_decls[local].is_user_variable + { self.append_place_to_string( &proj.base, buf, @@ -708,8 +708,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ProjectionElem::Field(field, _ty) => { autoderef = true; - let upvar_field_projection = place.is_upvar_field_projection( - self.mir, &self.tcx); + let upvar_field_projection = + place.is_upvar_field_projection(self.mir, &self.tcx); if let Some(field) = upvar_field_projection { let var_index = field.index(); let name = self.mir.upvar_decls[var_index].debug_name.to_string(); @@ -810,7 +810,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ty::TyAdt(def, _) => if def.is_enum() { field.index().to_string() } else { - def.non_enum_variant().fields[field.index()].ident.to_string() + def.non_enum_variant().fields[field.index()] + .ident + .to_string() }, ty::TyTuple(_) => field.index().to_string(), ty::TyRef(_, ty, _) | ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => { @@ -839,11 +841,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - // Retrieve span of given borrow from the current MIR representation - crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { - self.mir.source_info(borrow.reserve_location).span - } - // Retrieve type of a place for the current MIR representation fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { match place { @@ -860,3 +857,205 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } + +// The span(s) associated to a use of a place. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub(super) enum UseSpans { + // The access is caused by capturing a variable for a closure. + ClosureUse { + // The span of the args of the closure, including the `move` keyword if + // it's present. + args_span: Span, + // The span of the first use of the captured variable inside the closure. + var_span: Span + }, + // This access has a single span associated to it: common case. + OtherUse(Span), +} + +impl UseSpans { + pub(super) fn args_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { + args_span: span, .. + } + | UseSpans::OtherUse(span) => span, + } + } + + pub(super) fn var_or_use(self) -> Span { + match self { + UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span, + } + } + + // Add a span label to the arguments of the closure, if it exists. + pub(super) fn args_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { args_span, .. } = self { + err.span_label(args_span, message); + } + } + + // Add a span label to the use of the captured variable, if it exists. + pub(super) fn var_span_label(self, err: &mut DiagnosticBuilder, message: impl Into) { + if let UseSpans::ClosureUse { var_span, .. } = self { + err.span_label(var_span, message); + } + } + + pub(super) fn for_closure(self) -> bool { + match self { + UseSpans::ClosureUse { .. } => true, + UseSpans::OtherUse(_) => false, + } + } + + pub(super) fn or_else(self, if_other: F) -> Self + where + F: FnOnce() -> Self, + { + match self { + closure @ UseSpans::ClosureUse { .. } => closure, + UseSpans::OtherUse(_) => if_other(), + } + } +} + +impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + /// Finds the spans associated to a move or copy of move_place at location. + pub(super) fn move_spans( + &self, + moved_place: &Place<'tcx>, // Could also be an upvar. + location: Location, + ) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let stmt = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(stmt) => stmt, + None => return OtherUse(self.mir.source_info(location).span), + }; + + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_move_span: found closure {:?}", places); + + if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + if let Closure(_, _, _, args_span, _) = self.tcx.hir.expect_expr(node_id).node { + if let Some(var_span) = self.tcx.with_freevars(node_id, |freevars| { + for (v, place) in freevars.iter().zip(places) { + match place { + Operand::Copy(place) | Operand::Move(place) + if moved_place == place => + { + debug!( + "find_closure_move_span: found captured local {:?}", + place + ); + return Some(v.span); + } + _ => {} + } + } + None + }) { + return ClosureUse { + args_span, + var_span, + }; + } + } + } + } + } + + return OtherUse(stmt.source_info.span); + } + + /// Finds the span of arguments of a closure (within `maybe_closure_span`) + /// and its usage of the local assigned at `location`. + /// This is done by searching in statements succeeding `location` + /// and originating from `maybe_closure_span`. + pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpans { + use self::UseSpans::*; + use rustc::hir::ExprKind::Closure; + use rustc::mir::AggregateKind; + + let local = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) => local, + _ => return OtherUse(use_span), + }; + + if self.mir.local_kind(local) != LocalKind::Temp { + // operands are always temporaries. + return OtherUse(use_span); + } + + for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { + if let StatementKind::Assign(_, Rvalue::Aggregate(ref kind, ref places)) = stmt.kind { + if let AggregateKind::Closure(def_id, _) = **kind { + debug!("find_closure_borrow_span: found closure {:?}", places); + + return if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { + let args_span = if let Closure(_, _, _, span, _) = + self.tcx.hir.expect_expr(node_id).node + { + span + } else { + return OtherUse(use_span); + }; + + self.tcx + .with_freevars(node_id, |freevars| { + for (v, place) in freevars.iter().zip(places) { + match *place { + Operand::Copy(Place::Local(l)) + | Operand::Move(Place::Local(l)) + if local == l => + { + debug!( + "find_closure_borrow_span: found captured local \ + {:?}", + l + ); + return Some(v.span); + } + _ => {} + } + } + None + }).map(|var_span| ClosureUse { + args_span, + var_span, + }).unwrap_or(OtherUse(use_span)) + } else { + OtherUse(use_span) + }; + } + } + + if use_span != stmt.source_info.span { + break; + } + } + + OtherUse(use_span) + } + + /// Helper to retrieve span(s) of given borrow from the current MIR + /// representation + pub(super) fn retrieve_borrow_spans(&self, borrow: &BorrowData) -> UseSpans { + let span = self.mir.source_info(borrow.reserve_location).span; + self.borrow_spans(span, borrow.reserve_location) + } +} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4596c7be1c557..320d3a4720321 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1542,7 +1542,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if borrow_of_local_data(&borrow.borrowed_place) { let err = self.tcx .cannot_borrow_across_generator_yield( - self.retrieve_borrow_span(borrow), + self.retrieve_borrow_spans(borrow).var_or_use(), yield_span, Origin::Mir, ); diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index cd2de3247cfba..e8862320ddf3f 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -160,7 +160,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { let act; let acted_on; - let span = match error_access { AccessKind::Move => { err = self.tcx @@ -180,31 +179,23 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { act = "borrow as mutable"; acted_on = "borrowed as mutable"; - let closure_span = self.find_closure_span(span, location); - if let Some((args, var)) = closure_span { - err = self.tcx.cannot_borrow_path_as_mutable_because( - args, - &item_msg, - &reason, - Origin::Mir, - ); - err.span_label( - var, - format!( - "mutable borrow occurs due to use of `{}` in closure", - self.describe_place(access_place).unwrap(), - ), - ); - args - } else { - err = self.tcx.cannot_borrow_path_as_mutable_because( - span, - &item_msg, - &reason, - Origin::Mir, - ); - span - } + let borrow_spans = self.borrow_spans(span, location); + let borrow_span = borrow_spans.args_or_use(); + err = self.tcx.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + Origin::Mir, + ); + borrow_spans.var_span_label( + &mut err, + format!( + "mutable borrow occurs due to use of `{}` in closure", + // always Some() if the message is printed. + self.describe_place(access_place).unwrap_or(String::new()), + ) + ); + borrow_span } }; diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index d98bba72f7a33..5098b24adc367 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -62,18 +62,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); match find_use::find(mir, regioncx, tcx, region_sub, context.loc) { - Some(Cause::LiveVar(_local, location)) => { - if self.is_borrow_location_in_loop(context.loc) { - err.span_label( - mir.source_info(location).span, - "borrow used here in later iteration of loop".to_string(), - ); + Some(Cause::LiveVar(local, location)) => { + let span = mir.source_info(location).span; + let spans = self.move_spans(&Place::Local(local), location) + .or_else(|| self.borrow_spans(span, location)); + let message = if self.is_borrow_location_in_loop(context.loc) { + if spans.for_closure() { + "borrow captured here by closure in later iteration of loop" + } else { + "borrow used here in later iteration of loop" + } } else { - err.span_label( - mir.source_info(location).span, - "borrow later used here".to_string(), - ); - } + if spans.for_closure() { + "borrow later captured here by closure" + } else { + "borrow later used here" + } + }; + err.span_label(spans.var_or_use(), message); } Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name { diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 2d6b6cea03019..0a53361df6e95 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -203,8 +203,15 @@ pub trait BorrowckErrors<'cx>: Sized + Copy { desc, OGN = o ); - err.span_label(old_loan_span, "first closure is constructed here"); - err.span_label(new_loan_span, "second closure is constructed here"); + if old_loan_span == new_loan_span { + err.span_label( + old_loan_span, + "closures are constructed here in different iterations of loop" + ); + } else { + err.span_label(old_loan_span, "first closure is constructed here"); + err.span_label(new_loan_span, "second closure is constructed here"); + } if let Some(old_load_end_span) = old_load_end_span { err.span_label(old_load_end_span, "borrow from first closure ends here"); } diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 4c8d42cf02f98..837340f70fce7 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -17,3 +17,4 @@ arena = { path = "../libarena" } rustc_errors = { path = "../librustc_errors" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index ab4d15d0b9040..c782f2072b9aa 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,10 +21,11 @@ use {PerNS, Resolver, ResolverArenas}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; -use rustc::middle::cstore::LoadedMacro; use rustc::hir::def::*; use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; +use rustc::middle::cstore::CrateStore; +use rustc_metadata::cstore::LoadedMacro; use std::cell::Cell; use rustc_data_structures::sync::Lrc; @@ -86,7 +87,7 @@ struct LegacyMacroImports { imports: Vec<(Name, Span)>, } -impl<'a> Resolver<'a> { +impl<'a, 'cl> Resolver<'a, 'cl> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. pub fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) @@ -776,13 +777,13 @@ impl<'a> Resolver<'a> { } } -pub struct BuildReducedGraphVisitor<'a, 'b: 'a> { - pub resolver: &'a mut Resolver<'b>, +pub struct BuildReducedGraphVisitor<'a, 'b: 'a, 'c: 'b> { + pub resolver: &'a mut Resolver<'b, 'c>, pub legacy_scope: LegacyScope<'b>, pub expansion: Mark, } -impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { +impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> { fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> { let mark = id.placeholder_to_mark(); self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark); @@ -806,7 +807,7 @@ macro_rules! method { } } -impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { +impl<'a, 'b, 'cl> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b, 'cl> { method!(visit_impl_item: ast::ImplItem, ast::ImplItemKind::Macro, walk_impl_item); method!(visit_expr: ast::Expr, ast::ExprKind::Mac, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::Mac, walk_pat); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 4c12591c83207..e1b059d2b733f 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -31,8 +31,8 @@ use syntax::visit::{self, Visitor}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; -struct UnusedImportCheckVisitor<'a, 'b: 'a> { - resolver: &'a mut Resolver<'b>, +struct UnusedImportCheckVisitor<'a, 'b: 'a, 'd: 'b> { + resolver: &'a mut Resolver<'b, 'd>, /// All the (so far) unused imports, grouped path list unused_imports: NodeMap>, base_id: ast::NodeId, @@ -40,21 +40,21 @@ struct UnusedImportCheckVisitor<'a, 'b: 'a> { } // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. -impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> { - type Target = Resolver<'b>; +impl<'a, 'b, 'd> Deref for UnusedImportCheckVisitor<'a, 'b, 'd> { + type Target = Resolver<'b, 'd>; - fn deref<'c>(&'c self) -> &'c Resolver<'b> { + fn deref<'c>(&'c self) -> &'c Resolver<'b, 'd> { &*self.resolver } } -impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> { - fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { +impl<'a, 'b, 'd> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'd> { + fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'd> { &mut *self.resolver } } -impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { +impl<'a, 'b, 'd> UnusedImportCheckVisitor<'a, 'b, 'd> { // We have information about whether `use` (import) directives are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) { @@ -77,7 +77,7 @@ impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { } } -impl<'a, 'b> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b> { +impl<'a, 'b, 'cl> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'cl> { fn visit_item(&mut self, item: &'a ast::Item) { self.item_span = item.span; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9c58d2c1f0b0c..a7fcc89f6b974 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,6 +26,7 @@ extern crate arena; #[macro_use] extern crate rustc; extern crate rustc_data_structures; +extern crate rustc_metadata; pub use rustc::hir::def::{Namespace, PerNS}; @@ -34,7 +35,7 @@ use self::RibKind::*; use rustc::hir::map::{Definitions, DefCollector}; use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; -use rustc::middle::cstore::{CrateStore, CrateLoader}; +use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; @@ -44,6 +45,9 @@ use rustc::ty; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; +use rustc_metadata::creader::CrateLoader; +use rustc_metadata::cstore::CStore; + use syntax::codemap::CodeMap; use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; @@ -687,7 +691,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { } /// This thing walks the whole crate in DFS manner, visiting each item, resolving names as it goes. -impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { +impl<'a, 'tcx, 'cl> Visitor<'tcx> for Resolver<'a, 'cl> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); } @@ -1176,7 +1180,7 @@ impl<'a> NameBinding<'a> { } } - fn get_macro(&self, resolver: &mut Resolver<'a>) -> Lrc { + fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc { resolver.get_macro(self.def_ignoring_ambiguity()) } @@ -1291,9 +1295,9 @@ impl PrimitiveTypeTable { /// The main resolver class. /// /// This is the visitor that walks the whole crate. -pub struct Resolver<'a> { +pub struct Resolver<'a, 'b: 'a> { session: &'a Session, - cstore: &'a dyn CrateStore, + cstore: &'a CStore, pub definitions: Definitions, @@ -1389,7 +1393,7 @@ pub struct Resolver<'a> { /// true if `#![feature(use_extern_macros)]` use_extern_macros: bool, - crate_loader: &'a mut dyn CrateLoader, + crate_loader: &'a mut CrateLoader<'b>, macro_names: FxHashSet, macro_prelude: FxHashMap>, pub all_macros: FxHashMap, @@ -1473,7 +1477,7 @@ impl<'a> ResolverArenas<'a> { } } -impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { +impl<'a, 'b: 'a, 'cl: 'b> ty::DefIdTree for &'a Resolver<'b, 'cl> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, @@ -1484,7 +1488,7 @@ impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. -impl<'a> hir::lowering::Resolver for Resolver<'a> { +impl<'a, 'cl> hir::lowering::Resolver for Resolver<'a, 'cl> { fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool) { self.resolve_hir_path_cb(path, is_value, |resolver, span, error| resolve_error(resolver, span, error)) @@ -1537,7 +1541,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader> Resolver<'a, 'crateloader> { /// Rustdoc uses this to resolve things in a recoverable way. ResolutionError<'a> /// isn't something that can be returned because it can't be made to live that long, /// and also it's a private type. Fortunately rustdoc doesn't need to know the error, @@ -1603,15 +1607,15 @@ impl<'a> Resolver<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { pub fn new(session: &'a Session, - cstore: &'a dyn CrateStore, + cstore: &'a CStore, krate: &Crate, crate_name: &str, make_glob_map: MakeGlobMap, - crate_loader: &'a mut dyn CrateLoader, + crate_loader: &'a mut CrateLoader<'crateloader>, arenas: &'a ResolverArenas<'a>) - -> Resolver<'a> { + -> Resolver<'a, 'crateloader> { let root_def_id = DefId::local(CRATE_DEF_INDEX); let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name()); let graph_root = arenas.alloc_module(ModuleData { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 60a6bcf499db4..993874d7c0be8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -18,6 +18,7 @@ use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex, use rustc::hir::def::{Def, Export}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; +use rustc::middle::cstore::CrateStore; use syntax::ast::{self, Name, Ident}; use syntax::attr::{self, HasAttrs}; use syntax::errors::DiagnosticBuilder; @@ -117,7 +118,7 @@ impl<'a> MacroBinding<'a> { } } -impl<'a> base::Resolver for Resolver<'a> { +impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { fn next_node_id(&mut self) -> ast::NodeId { self.session.next_node_id() } @@ -135,9 +136,11 @@ impl<'a> base::Resolver for Resolver<'a> { } fn eliminate_crate_var(&mut self, item: P) -> P { - struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span); + struct EliminateCrateVar<'b, 'a: 'b, 'crateloader: 'a>( + &'b mut Resolver<'a, 'crateloader>, Span + ); - impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { + impl<'a, 'b, 'crateloader> Folder for EliminateCrateVar<'a, 'b, 'crateloader> { fn fold_path(&mut self, path: ast::Path) -> ast::Path { match self.fold_qpath(None, path) { (None, path) => path, @@ -387,7 +390,7 @@ impl<'a> base::Resolver for Resolver<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'cl> Resolver<'a, 'cl> { fn report_proc_macro_stub(&self, span: Span) { self.session.span_err(span, "can't use a procedural macro from the same crate that defines it"); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index b6ad2f316a0a2..a3a9b938bbd6f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -123,7 +123,7 @@ impl<'a> NameResolution<'a> { } } -impl<'a> Resolver<'a> { +impl<'a, 'crateloader> Resolver<'a, 'crateloader> { fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) -> &'a RefCell> { *module.resolutions.borrow_mut().entry((ident.modern(), ns)) @@ -402,7 +402,7 @@ impl<'a> Resolver<'a> { // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F) -> T - where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T + where F: FnOnce(&mut Resolver<'a, 'crateloader>, &mut NameResolution<'a>) -> T { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. @@ -453,30 +453,30 @@ impl<'a> Resolver<'a> { } } -pub struct ImportResolver<'a, 'b: 'a> { - pub resolver: &'a mut Resolver<'b>, +pub struct ImportResolver<'a, 'b: 'a, 'c: 'a + 'b> { + pub resolver: &'a mut Resolver<'b, 'c>, } -impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> { - type Target = Resolver<'b>; - fn deref(&self) -> &Resolver<'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::Deref for ImportResolver<'a, 'b, 'c> { + type Target = Resolver<'b, 'c>; + fn deref(&self) -> &Resolver<'b, 'c> { self.resolver } } -impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> { - fn deref_mut(&mut self) -> &mut Resolver<'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ::std::ops::DerefMut for ImportResolver<'a, 'b, 'c> { + fn deref_mut(&mut self) -> &mut Resolver<'b, 'c> { self.resolver } } -impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> { +impl<'a, 'b: 'a, 'c: 'a + 'b> ty::DefIdTree for &'a ImportResolver<'a, 'b, 'c> { fn parent(self, id: DefId) -> Option { self.resolver.parent(id) } } -impl<'a, 'b:'a> ImportResolver<'a, 'b> { +impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> { // Import resolution // // This is a fixed-point algorithm. We resolve imports until our efforts diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index c30d6817b4664..23056218269b6 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -13,6 +13,7 @@ use rustc::traits::{self, auto_trait as auto}; use rustc::ty::{self, ToPredicate, TypeFoldable}; use rustc::ty::subst::Subst; use rustc::infer::InferOk; +use rustc::middle::cstore::CrateStore; use std::fmt::Debug; use syntax_pos::DUMMY_SP; @@ -20,13 +21,13 @@ use core::DocAccessLevels; use super::*; -pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a> { - pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>, +pub struct AutoTraitFinder<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, pub f: auto::AutoTraitFinder<'a, 'tcx>, } -impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> Self { +impl<'a, 'tcx, 'rcx, 'cstore> AutoTraitFinder<'a, 'tcx, 'rcx, 'cstore> { + pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self { let f = auto::AutoTraitFinder::new(&cx.tcx); AutoTraitFinder { cx, f } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9245ef3cf507b..8b4df1b7b7d21 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -19,7 +19,7 @@ use syntax_pos::Span; use rustc::hir; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::DefId; -use rustc::middle::cstore::LoadedMacro; +use rustc_metadata::cstore::LoadedMacro; use rustc::ty; use rustc::util::nodemap::FxHashSet; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 45566230fdaae..4512a33ec4a21 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -145,7 +145,7 @@ pub struct Crate { pub masked_crates: FxHashSet, } -impl<'a, 'tcx, 'rcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> Clean for visit_ast::RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { fn clean(&self, cx: &DocContext) -> Crate { use ::visit_lib::LibEmbargoVisitor; diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 769c9804a355a..84741f12ad183 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -13,7 +13,6 @@ use rustc_driver::{self, driver, target_features, abort_on_err}; use rustc::session::{self, config}; use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use rustc::hir::def::Def; -use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt, AllArenas}; use rustc::hir::map as hir_map; @@ -49,13 +48,13 @@ pub use rustc::session::search_paths::SearchPaths; pub type ExternalPaths = FxHashMap, clean::TypeKind)>; -pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { +pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - pub resolver: &'a RefCell>, + pub resolver: &'a RefCell>, /// The stack of module NodeIds up till this point pub mod_ids: RefCell>, pub crate_name: Option, - pub cstore: Rc, + pub cstore: Rc, pub populated_all_crate_impls: Cell, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -87,7 +86,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { pub all_traits: Vec, } -impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> DocContext<'a, 'tcx, 'rcx, 'cstore> { pub fn sess(&self) -> &session::Session { &self.tcx.sess } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index b4342f4749185..faca264ea1006 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -33,7 +33,7 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t background: rgba(0, 0, 0, 0); } -.docblock p > code, .docblock-short p > code { +.docblock code, .docblock-short code { background-color: #2A2A2A; } pre { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index e84e3cb56636e..5725a41d939d5 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -35,7 +35,7 @@ h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.t background: rgba(0, 0, 0, 0); } -.docblock p > code, .docblock-short p > code { +.docblock code, .docblock-short code { background-color: #F5F5F5; } pre { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0a4955f4fbd10..dda97cfdb2c4b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -290,7 +290,7 @@ fn opts() -> Vec { "edition to use when compiling rust code (default: 2015)", "EDITION") }), - unstable("color", |o| { + stable("color", |o| { o.optopt("", "color", "Configure coloring of output: @@ -299,7 +299,7 @@ fn opts() -> Vec { never = never colorize output", "auto|always|never") }), - unstable("error-format", |o| { + stable("error-format", |o| { o.optopt("", "error-format", "How errors and other messages are produced", diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 287913d2cc9b8..e2c935e2f6921 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -38,10 +38,10 @@ use doctree::*; // also, is there some reason that this doesn't use the 'visit' // framework from syntax? -pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> { +pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { pub module: Module, pub attrs: hir::HirVec, - pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>, + pub cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore>, view_item_stack: FxHashSet, inlining: bool, /// Is the current module and all of its parents public? @@ -49,8 +49,10 @@ pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> { exact_paths: Option>>, } -impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { - pub fn new(cx: &'a core::DocContext<'a, 'tcx, 'rcx>) -> RustdocVisitor<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { + pub fn new( + cx: &'a core::DocContext<'a, 'tcx, 'rcx, 'cstore> + ) -> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> { // If the root is re-exported, terminate all recursion. let mut stack = FxHashSet(); stack.insert(ast::CRATE_NODE_ID); diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 4c773fc1dd78b..10a4e69dcc6cd 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -22,8 +22,8 @@ use clean::{AttributesExt, NestedAttributesExt}; /// Similar to `librustc_privacy::EmbargoVisitor`, but also takes /// specific rustdoc annotations into account (i.e. `doc(hidden)`) -pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a> { - cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>, +pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> { + cx: &'a ::core::DocContext<'a, 'tcx, 'rcx, 'cstore>, // Accessibility levels for reachable nodes access_levels: RefMut<'a, AccessLevels>, // Previous accessibility level, None means unreachable @@ -32,8 +32,10 @@ pub struct LibEmbargoVisitor<'a, 'tcx: 'a, 'rcx: 'a> { visited_mods: FxHashSet, } -impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> { - pub fn new(cx: &'a ::core::DocContext<'a, 'tcx, 'rcx>) -> LibEmbargoVisitor<'a, 'tcx, 'rcx> { +impl<'a, 'tcx, 'rcx, 'cstore> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> { + pub fn new( + cx: &'a ::core::DocContext<'a, 'tcx, 'rcx, 'cstore> + ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> { LibEmbargoVisitor { cx, access_levels: cx.access_levels.borrow_mut(), diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5348c9a0f3498..92bda923ec2c5 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ alloc_system = { path = "../liballoc_system" } panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } -libc = { path = "../rustc/libc_shim" } +libc = { path = "../rustc/libc_shim", features = ["align"] } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } diff --git a/src/libstd/future.rs b/src/libstd/future.rs index c1cc36f3b419a..12ea1ea9f9d49 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -108,9 +108,9 @@ where #[unstable(feature = "gen_future", issue = "50547")] /// Polls a future in the current thread-local task context. -pub fn poll_in_task_cx(f: &mut PinMut) -> Poll +pub fn poll_in_task_cx(f: PinMut) -> Poll where F: Future { - get_task_cx(|cx| f.reborrow().poll(cx)) + get_task_cx(|cx| f.poll(cx)) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3c01de2e997c9..aa0f6b318227f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -254,6 +254,8 @@ #![feature(collections_range)] #![feature(compiler_builtins_lib)] #![feature(const_fn)] +#![feature(const_int_ops)] +#![feature(const_ip)] #![feature(core_intrinsics)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] @@ -292,6 +294,7 @@ #![feature(rand)] #![feature(raw)] #![feature(rustc_attrs)] +#![feature(rustc_const_unstable)] #![feature(std_internals)] #![feature(stdsimd)] #![feature(shrink_to)] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index a96e2ba21345b..f15494c5fd7f5 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -227,14 +227,17 @@ macro_rules! eprintln { macro_rules! await { ($e:expr) => { { let mut pinned = $e; - let mut pinned = unsafe { $crate::mem::PinMut::new_unchecked(&mut pinned) }; loop { - match $crate::future::poll_in_task_cx(&mut pinned) { - // FIXME(cramertj) prior to stabilizing await, we have to ensure that this - // can't be used to create a generator on stable via `|| await!()`. - $crate::task::Poll::Pending => yield, - $crate::task::Poll::Ready(x) => break x, + if let $crate::task::Poll::Ready(x) = + $crate::future::poll_in_task_cx(unsafe { + $crate::mem::PinMut::new_unchecked(&mut pinned) + }) + { + break x; } + // FIXME(cramertj) prior to stabilizing await, we have to ensure that this + // can't be used to create a generator on stable via `|| await!()`. + yield } } } } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index fcec8d06853f6..341757aeb75a5 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -17,7 +17,6 @@ use cmp::Ordering; use fmt; use hash; use mem; -use net::{hton, ntoh}; use sys::net::netc as c; use sys_common::{AsInner, FromInner}; @@ -340,18 +339,21 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::new(127, 0, 0, 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { + #[rustc_const_unstable(feature = "const_ip")] + pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr { Ipv4Addr { inner: c::in_addr { - s_addr: hton(((a as u32) << 24) | - ((b as u32) << 16) | - ((c as u32) << 8) | - (d as u32)), + s_addr: u32::to_be( + ((a as u32) << 24) | + ((b as u32) << 16) | + ((c as u32) << 8) | + (d as u32) + ), } } } - /// Creates a new IPv4 address with the address pointing to localhost: 127.0.0.1. + /// An IPv4 address with the address pointing to localhost: 127.0.0.1. /// /// # Examples /// @@ -359,17 +361,15 @@ impl Ipv4Addr { /// #![feature(ip_constructors)] /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::localhost(); + /// let addr = Ipv4Addr::LOCALHOST; /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)); /// ``` #[unstable(feature = "ip_constructors", reason = "requires greater scrutiny before stabilization", issue = "44582")] - pub fn localhost() -> Ipv4Addr { - Ipv4Addr::new(127, 0, 0, 1) - } + pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1); - /// Creates a new IPv4 address representing an unspecified address: 0.0.0.0 + /// An IPv4 address representing an unspecified address: 0.0.0.0 /// /// # Examples /// @@ -377,15 +377,29 @@ impl Ipv4Addr { /// #![feature(ip_constructors)] /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::unspecified(); + /// let addr = Ipv4Addr::UNSPECIFIED; /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0)); /// ``` #[unstable(feature = "ip_constructors", reason = "requires greater scrutiny before stabilization", issue = "44582")] - pub fn unspecified() -> Ipv4Addr { - Ipv4Addr::new(0, 0, 0, 0) - } + pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0); + + /// An IPv4 address representing the broadcast address: 255.255.255.255 + /// + /// # Examples + /// + /// ``` + /// #![feature(ip_constructors)] + /// use std::net::Ipv4Addr; + /// + /// let addr = Ipv4Addr::BROADCAST; + /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255)); + /// ``` + #[unstable(feature = "ip_constructors", + reason = "requires greater scrutiny before stabilization", + issue = "44582")] + pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255); /// Returns the four eight-bit integers that make up this address. /// @@ -399,7 +413,7 @@ impl Ipv4Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn octets(&self) -> [u8; 4] { - let bits = ntoh(self.inner.s_addr); + let bits = u32::from_be(self.inner.s_addr); [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] } @@ -573,8 +587,7 @@ impl Ipv4Addr { /// ``` #[stable(since = "1.7.0", feature = "ip_17")] pub fn is_broadcast(&self) -> bool { - self.octets()[0] == 255 && self.octets()[1] == 255 && - self.octets()[2] == 255 && self.octets()[3] == 255 + self == &Self::BROADCAST } /// Returns [`true`] if this address is in a range designated for documentation. @@ -763,7 +776,7 @@ impl PartialOrd for Ipv4Addr { #[stable(feature = "rust1", since = "1.0.0")] impl Ord for Ipv4Addr { fn cmp(&self, other: &Ipv4Addr) -> Ordering { - ntoh(self.inner.s_addr).cmp(&ntoh(other.inner.s_addr)) + u32::from_be(self.inner.s_addr).cmp(&u32::from_be(other.inner.s_addr)) } } @@ -856,21 +869,27 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, - h: u16) -> Ipv6Addr { - let mut addr: c::in6_addr = unsafe { mem::zeroed() }; - addr.s6_addr = [(a >> 8) as u8, a as u8, - (b >> 8) as u8, b as u8, - (c >> 8) as u8, c as u8, - (d >> 8) as u8, d as u8, - (e >> 8) as u8, e as u8, - (f >> 8) as u8, f as u8, - (g >> 8) as u8, g as u8, - (h >> 8) as u8, h as u8]; - Ipv6Addr { inner: addr } + #[rustc_const_unstable(feature = "const_ip")] + pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, + g: u16, h: u16) -> Ipv6Addr { + Ipv6Addr { + inner: c::in6_addr { + s6_addr: [ + (a >> 8) as u8, a as u8, + (b >> 8) as u8, b as u8, + (c >> 8) as u8, c as u8, + (d >> 8) as u8, d as u8, + (e >> 8) as u8, e as u8, + (f >> 8) as u8, f as u8, + (g >> 8) as u8, g as u8, + (h >> 8) as u8, h as u8 + ], + } + } + } - /// Creates a new IPv6 address representing localhost: `::1`. + /// An IPv6 address representing localhost: `::1`. /// /// # Examples /// @@ -878,17 +897,15 @@ impl Ipv6Addr { /// #![feature(ip_constructors)] /// use std::net::Ipv6Addr; /// - /// let addr = Ipv6Addr::localhost(); + /// let addr = Ipv6Addr::LOCALHOST; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` #[unstable(feature = "ip_constructors", reason = "requires greater scrutiny before stabilization", issue = "44582")] - pub fn localhost() -> Ipv6Addr { - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1) - } + pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); - /// Creates a new IPv6 address representing the unspecified address: `::` + /// An IPv6 address representing the unspecified address: `::` /// /// # Examples /// @@ -896,15 +913,13 @@ impl Ipv6Addr { /// #![feature(ip_constructors)] /// use std::net::Ipv6Addr; /// - /// let addr = Ipv6Addr::unspecified(); + /// let addr = Ipv6Addr::UNSPECIFIED; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); /// ``` #[unstable(feature = "ip_constructors", reason = "requires greater scrutiny before stabilization", issue = "44582")] - pub fn unspecified() -> Ipv6Addr { - Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0) - } + pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); /// Returns the eight 16-bit segments that make up this address. /// @@ -1846,18 +1861,20 @@ mod tests { #[test] fn ipv4_from_constructors() { - assert_eq!(Ipv4Addr::localhost(), Ipv4Addr::new(127, 0, 0, 1)); - assert!(Ipv4Addr::localhost().is_loopback()); - assert_eq!(Ipv4Addr::unspecified(), Ipv4Addr::new(0, 0, 0, 0)); - assert!(Ipv4Addr::unspecified().is_unspecified()); + assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1)); + assert!(Ipv4Addr::LOCALHOST.is_loopback()); + assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0)); + assert!(Ipv4Addr::UNSPECIFIED.is_unspecified()); + assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255)); + assert!(Ipv4Addr::BROADCAST.is_broadcast()); } #[test] fn ipv6_from_contructors() { - assert_eq!(Ipv6Addr::localhost(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); - assert!(Ipv6Addr::localhost().is_loopback()); - assert_eq!(Ipv6Addr::unspecified(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); - assert!(Ipv6Addr::unspecified().is_unspecified()); + assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + assert!(Ipv6Addr::LOCALHOST.is_loopback()); + assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + assert!(Ipv6Addr::UNSPECIFIED.is_unspecified()); } #[test] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 10282ecb65883..3abc260b45868 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -178,6 +178,10 @@ impl Once { /// happens-before relation between the closure and code executing after the /// return). /// + /// If the given closure recusively invokes `call_once` on the same `Once` + /// instance the exact behavior is not specified, allowed outcomes are + /// a panic or a deadlock. + /// /// # Examples /// /// ``` diff --git a/src/llvm b/src/llvm index 03684905101f0..e19f07f5a6e55 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 03684905101f0b7e49dfe530e54dc1aeac6ef0fb +Subproject commit e19f07f5a6e5546ab4f6ea951e3c6b8627edeaa7 diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml index e77897d643313..81ace038b2a9e 100644 --- a/src/rustc/libc_shim/Cargo.toml +++ b/src/rustc/libc_shim/Cargo.toml @@ -37,3 +37,4 @@ compiler_builtins = { path = "../compiler_builtins_shim" } # outside rustc. See https://github.com/rust-lang/libc/search?l=Rust&q=stdbuild&type=&utf8=%E2%9C%93. stdbuild = [] default = ["stdbuild"] +align = [] diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger index 1722211c9e89f..7da830e1125ba 100644 --- a/src/rustllvm/llvm-rebuild-trigger +++ b/src/rustllvm/llvm-rebuild-trigger @@ -1,4 +1,4 @@ # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # The actual contents of this file do not matter, but to trigger a change on the # build bots then the contents should be changed so git updates the mtime. -2018-07-12 \ No newline at end of file +2018-08-02 diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index b3a6fb4d590ae..cc2b6c641e90c 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -21,12 +21,13 @@ extern crate rustc_driver; extern crate rustc_codegen_utils; extern crate syntax; extern crate rustc_errors as errors; +extern crate rustc_metadata; -use rustc::middle::cstore::CrateStore; use rustc::session::Session; use rustc::session::config::{self, Input}; use rustc_driver::{driver, CompilerCalls, Compilation}; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_metadata::cstore::CStore; use syntax::ast; use std::path::PathBuf; @@ -51,7 +52,7 @@ impl<'a> CompilerCalls<'a> for TestCalls<'a> { _: &CodegenBackend, _: &getopts::Matches, _: &Session, - _: &CrateStore, + _: &CStore, _: &Input, _: &Option, _: &Option) diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs new file mode 100644 index 0000000000000..3acf4af5fd247 --- /dev/null +++ b/src/test/rustdoc/traits-in-bodies.rs @@ -0,0 +1,29 @@ +// 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. + +//prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it +//didn't see that `SomeStruct` implemented `Clone` + +//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test +//reflects that + +pub struct Bounded(T); + +pub struct SomeStruct; + +fn asdf() -> Bounded { + impl Clone for SomeStruct { + fn clone(&self) -> SomeStruct { + SomeStruct + } + } + + Bounded(SomeStruct) +} diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index a4f8e8b408ba5..6186c3839193d 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -77,11 +77,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:24:24 | LL | let c1 = to_fn_mut(|| x = 4); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -92,11 +92,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:36:24 | LL | let c1 = to_fn_mut(|| set(&mut x)); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -107,11 +107,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:44:24 | LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once @@ -122,11 +122,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:52:24 | LL | let c1 = to_fn_mut(|| x = 5); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here ... @@ -137,11 +137,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) --> $DIR/borrowck-closures-two-mut.rs:65:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - previous borrow occurs due to use of `x` in closure + | -- - first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here ... diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr index b15f156b7c201..426419a7b3b7f 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-1.nll.stderr @@ -1,8 +1,10 @@ error[E0597]: `books` does not live long enough - --> $DIR/borrowck-escaping-closure-error-1.rs:23:11 + --> $DIR/borrowck-escaping-closure-error-1.rs:23:14 | LL | spawn(|| books.push(4)); - | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | -- ^^^^^ borrowed value does not live long enough + | | + | value captured here LL | //~^ ERROR E0373 LL | } | - `books` dropped here while still borrowed diff --git a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr index 8c643973af67b..d5f3a0ed6d82e 100644 --- a/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr +++ b/src/test/ui/borrowck/borrowck-escaping-closure-error-2.nll.stderr @@ -1,8 +1,10 @@ error[E0597]: `books` does not live long enough - --> $DIR/borrowck-escaping-closure-error-2.rs:21:14 + --> $DIR/borrowck-escaping-closure-error-2.rs:21:17 | LL | Box::new(|| books.push(4)) - | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | -- ^^^^^ borrowed value does not live long enough + | | + | value captured here LL | //~^ ERROR E0373 LL | } | - `books` dropped here while still borrowed diff --git a/src/test/ui/error-codes/E0504.nll.stderr b/src/test/ui/error-codes/E0504.nll.stderr index ec30bb306fc3f..6f4823326ffa6 100644 --- a/src/test/ui/error-codes/E0504.nll.stderr +++ b/src/test/ui/error-codes/E0504.nll.stderr @@ -1,17 +1,16 @@ error[E0505]: cannot move out of `fancy_num` because it is borrowed --> $DIR/E0504.rs:19:13 | -LL | let fancy_ref = &fancy_num; - | ---------- borrow of `fancy_num` occurs here +LL | let fancy_ref = &fancy_num; + | ---------- borrow of `fancy_num` occurs here LL | -LL | let x = move || { - | _____________^ -LL | | println!("child function: {}", fancy_num.num); //~ ERROR E0504 -LL | | }; - | |_____^ move out of `fancy_num` occurs here +LL | let x = move || { + | ^^^^^^^ move out of `fancy_num` occurs here +LL | println!("child function: {}", fancy_num.num); //~ ERROR E0504 + | --------- move occurs due to use in closure ... -LL | println!("main function: {}", fancy_ref.num); - | ------------- borrow later used here +LL | println!("main function: {}", fancy_ref.num); + | ------------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/issue-11192.nll.stderr b/src/test/ui/issue-11192.nll.stderr index d5a67083a23b8..a7e6c9f2b3371 100644 --- a/src/test/ui/issue-11192.nll.stderr +++ b/src/test/ui/issue-11192.nll.stderr @@ -5,7 +5,7 @@ LL | let mut test = |foo: &Foo| { | ----------- mutable borrow occurs here LL | println!("access {}", foo.x); LL | ptr = box Foo { x: ptr.x + 1 }; - | --- previous borrow occurs due to use of `ptr` in closure + | --- first borrow occurs due to use of `ptr` in closure ... LL | test(&*ptr); | -----^^^^^- diff --git a/src/test/ui/issue-11873.nll.stderr b/src/test/ui/issue-11873.nll.stderr index c12cbbfdd53a1..bf4fed06dee21 100644 --- a/src/test/ui/issue-11873.nll.stderr +++ b/src/test/ui/issue-11873.nll.stderr @@ -2,7 +2,9 @@ error[E0505]: cannot move out of `v` because it is borrowed --> $DIR/issue-11873.rs:14:14 | LL | let mut f = || v.push(2); - | ------------ borrow of `v` occurs here + | -- - borrow occurs due to use in closure + | | + | borrow of `v` occurs here LL | let _w = v; //~ ERROR: cannot move out of `v` | ^ move out of `v` occurs here LL | diff --git a/src/test/ui/issue-18783.nll.stderr b/src/test/ui/issue-18783.nll.stderr index 6bb7b4229d747..8acdc73bf0e68 100644 --- a/src/test/ui/issue-18783.nll.stderr +++ b/src/test/ui/issue-18783.nll.stderr @@ -2,11 +2,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time --> $DIR/issue-18783.rs:17:21 | LL | c.push(Box::new(|| y = 0)); - | -- - previous borrow occurs due to use of `y` in closure + | -- - first borrow occurs due to use of `y` in closure | | | first mutable borrow occurs here LL | c.push(Box::new(|| y = 0)); - | ^^ - borrow occurs due to use of `y` in closure + | ^^ - second borrow occurs due to use of `y` in closure | | | second mutable borrow occurs here LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time @@ -17,11 +17,11 @@ error[E0499]: cannot borrow `y` as mutable more than once at a time --> $DIR/issue-18783.rs:26:29 | LL | Push::push(&c, Box::new(|| y = 0)); - | -- - previous borrow occurs due to use of `y` in closure + | -- - first borrow occurs due to use of `y` in closure | | | first mutable borrow occurs here LL | Push::push(&c, Box::new(|| y = 0)); - | ^^ - borrow occurs due to use of `y` in closure + | ^^ - second borrow occurs due to use of `y` in closure | | | second mutable borrow occurs here LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time diff --git a/src/test/ui/issue-24357.nll.stderr b/src/test/ui/issue-24357.nll.stderr index f601a6fbc8850..e35f443548d90 100644 --- a/src/test/ui/issue-24357.nll.stderr +++ b/src/test/ui/issue-24357.nll.stderr @@ -2,7 +2,9 @@ error[E0382]: use of moved value: `x` --> $DIR/issue-24357.rs:16:12 | LL | let f = move || { let y = x; }; - | ---------------------- value moved here + | ------- - variable moved due to use in closure + | | + | value moved into closure here LL | //~^ NOTE value moved (into closure) here LL | let z = x; | ^ value used here after move diff --git a/src/test/ui/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issue-27282-move-match-input-into-guard.stderr index d264bf8d2734d..91c51bcd05825 100644 --- a/src/test/ui/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issue-27282-move-match-input-into-guard.stderr @@ -1,11 +1,13 @@ error[E0505]: cannot move out of `b` because it is borrowed - --> $DIR/issue-27282-move-match-input-into-guard.rs:26:16 + --> $DIR/issue-27282-move-match-input-into-guard.rs:26:17 | LL | match b { | - borrow of `b` occurs here LL | &mut false => {}, LL | _ if { (|| { let bar = b; *bar = false; })(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `b` occurs here + | ^^ - move occurs due to use in closure + | | + | move out of `b` occurs here ... LL | &mut true => { println!("You might think we should get here"); }, | --------- borrow later used here @@ -14,7 +16,9 @@ error[E0382]: use of moved value: `*b` --> $DIR/issue-27282-move-match-input-into-guard.rs:29:14 | LL | _ if { (|| { let bar = b; *bar = false; })(); - | ----------------------------------- value moved here + | -- - variable moved due to use in closure + | | + | value moved into closure here ... LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr index fb11090c222d0..a9d9651fb2a35 100644 --- a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr +++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr @@ -5,7 +5,7 @@ LL | match x { | - borrow occurs here ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | closure construction occurs here ... diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr index 6e643d30185f9..582d0fd678c07 100644 --- a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr +++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr @@ -5,7 +5,7 @@ LL | match x { | - borrow occurs here ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | closure construction occurs here ... diff --git a/src/test/ui/issue-4335.nll.stderr b/src/test/ui/issue-4335.nll.stderr index 40d7838a80325..4ccd24fa45921 100644 --- a/src/test/ui/issue-4335.nll.stderr +++ b/src/test/ui/issue-4335.nll.stderr @@ -5,10 +5,12 @@ LL | id(Box::new(|| *v)) | ^^ cannot move out of captured variable in an `FnMut` closure error[E0597]: `v` does not live long enough - --> $DIR/issue-4335.rs:16:17 + --> $DIR/issue-4335.rs:16:21 | LL | id(Box::new(|| *v)) - | ^^^^^ borrowed value does not live long enough + | -- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `v` dropped here while still borrowed diff --git a/src/test/ui/issue-6801.nll.stderr b/src/test/ui/issue-6801.nll.stderr index 5436397c68ead..3ca2f39470da7 100644 --- a/src/test/ui/issue-6801.nll.stderr +++ b/src/test/ui/issue-6801.nll.stderr @@ -2,7 +2,9 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/issue-6801.rs:29:13 | LL | let sq = || { *x * *x }; - | -------------- borrow of `x` occurs here + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here LL | LL | twice(x); //~ ERROR: cannot move out of | ^ move out of `x` occurs here diff --git a/src/test/ui/nll/closure-access-spans.rs b/src/test/ui/nll/closure-access-spans.rs new file mode 100644 index 0000000000000..b49436fabcf74 --- /dev/null +++ b/src/test/ui/nll/closure-access-spans.rs @@ -0,0 +1,68 @@ +// 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. + +// check that accesses due to a closure capture give a special note + +#![feature(nll)] + +fn closure_imm_capture_conflict(mut x: i32) { + let r = &mut x; + || x; //~ ERROR + r.use_mut(); +} + +fn closure_mut_capture_conflict(mut x: i32) { + let r = &mut x; + || x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_unique_capture_conflict(mut x: &mut i32) { + let r = &mut x; + || *x = 2; //~ ERROR + r.use_mut(); +} + +fn closure_copy_capture_conflict(mut x: i32) { + let r = &mut x; + move || x; //~ ERROR + r.use_ref(); +} + +fn closure_move_capture_conflict(mut x: String) { + let r = &x; + || x; //~ ERROR + r.use_ref(); +} + +fn closure_imm_capture_moved(mut x: String) { + let r = x; + || x.len(); //~ ERROR +} + +fn closure_mut_capture_moved(mut x: String) { + let r = x; + || x = String::new(); //~ ERROR +} + +fn closure_unique_capture_moved(x: &mut String) { + let r = x; + || *x = String::new(); //~ ERROR +} + +fn closure_move_capture_moved(x: &mut String) { + let r = x; + || x; //~ ERROR +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr new file mode 100644 index 0000000000000..0042b5d7d529b --- /dev/null +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -0,0 +1,110 @@ +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-access-spans.rs:17:5 + | +LL | let r = &mut x; + | ------ mutable borrow occurs here +LL | || x; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-access-spans.rs:23:5 + | +LL | let r = &mut x; + | ------ first mutable borrow occurs here +LL | || x = 2; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | second mutable borrow occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0500]: closure requires unique access to `x` but it is already borrowed + --> $DIR/closure-access-spans.rs:29:5 + | +LL | let r = &mut x; + | ------ borrow occurs here +LL | || *x = 2; //~ ERROR + | ^^ - second borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | r.use_mut(); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-access-spans.rs:35:13 + | +LL | let r = &mut x; + | ------ borrow of `x` occurs here +LL | move || x; //~ ERROR + | ^ use of borrowed `x` +LL | r.use_ref(); + | - borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-access-spans.rs:41:5 + | +LL | let r = &x; + | -- borrow of `x` occurs here +LL | || x; //~ ERROR + | ^^ - move occurs due to use in closure + | | + | move out of `x` occurs here +LL | r.use_ref(); + | - borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:47:5 + | +LL | let r = x; + | - value moved here +LL | || x.len(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:52:5 + | +LL | let r = x; + | - value moved here +LL | || x = String::new(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-access-spans.rs:57:5 + | +LL | let r = x; + | - value moved here +LL | || *x = String::new(); //~ ERROR + | ^^ - borrow occurs due to use in closure + | | + | value borrowed here after move + | + = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait + +error[E0382]: use of moved value: `x` + --> $DIR/closure-access-spans.rs:62:5 + | +LL | let r = x; + | - value moved here +LL | || x; //~ ERROR + | ^^ - use occurs due to use in closure + | | + | value used here after move + | + = note: move occurs because `x` has type `&mut std::string::String`, which does not implement the `Copy` trait + +error: aborting due to 9 previous errors + +Some errors occurred: E0382, E0499, E0500, E0502, E0503, E0505. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/closure-borrow-spans.rs b/src/test/ui/nll/closure-borrow-spans.rs new file mode 100644 index 0000000000000..d62dc27dade8f --- /dev/null +++ b/src/test/ui/nll/closure-borrow-spans.rs @@ -0,0 +1,112 @@ +// 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. + +// check that existing borrows due to a closure capture give a special note + +#![feature(nll)] + +fn move_while_borrowed(x: String) { + let f = || x.len(); + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed(mut x: i32) { + let f = || x; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed() { + let f; + { + let x = 1; + f = || x; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed(mut x: i32) { + let f = || x; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_mut() { + let f; + { + let mut x = 1; + f = || x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_mut(mut x: i32) { + let f = || x = 0; + x = 1; //~ ERROR + f.use_ref(); +} + +fn copy_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = x; //~ ERROR + f.use_ref(); +} + +fn borrow_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + let y = &x; //~ ERROR + f.use_ref(); +} + +fn borrow_mut_while_borrowed_unique(mut x: &mut i32) { + let f = || *x = 0; + let y = &mut x; //~ ERROR + f.use_ref(); +} + +fn drop_while_borrowed_unique() { + let mut z = 1; + let f; + { + let x = &mut z; + f = || *x = 0; //~ ERROR + } + f.use_ref(); +} + +fn assign_while_borrowed_unique(x: &mut i32) { + let f = || *x = 0; + *x = 1; //~ ERROR + f.use_ref(); +} + +fn main() {} + +trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } } +impl Fake for T { } diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr new file mode 100644 index 0000000000000..1b9420b3c0bf3 --- /dev/null +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -0,0 +1,172 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:17:13 + | +LL | let f = || x.len(); + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ move out of `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/closure-borrow-spans.rs:23:13 + | +LL | let f = || x; + | -- - first borrow occurs due to use of `x` in closure + | | + | immutable borrow occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ mutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:31:16 + | +LL | f = || x; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:38:5 + | +LL | let f = || x; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0503]: cannot use `x` because it was mutably borrowed + --> $DIR/closure-borrow-spans.rs:44:13 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use of `x` in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ use of borrowed `x` +LL | f.use_ref(); + | - borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/closure-borrow-spans.rs:50:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | mutable borrow occurs here +LL | let y = &x; //~ ERROR + | ^^ immutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closure-borrow-spans.rs:56:13 + | +LL | let f = || x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | first mutable borrow occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ second mutable borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:64:16 + | +LL | f = || x = 0; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:71:5 + | +LL | let f = || x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | x = 1; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:77:13 + | +LL | let f = || *x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `x` occurs here +LL | let y = x; //~ ERROR + | ^ move out of `x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:83:13 + | +LL | let f = || *x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &x; //~ ERROR + | ^^ borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access + --> $DIR/closure-borrow-spans.rs:89:13 + | +LL | let f = || *x = 0; + | -- - first borrow occurs due to use of `x` in closure + | | + | closure construction occurs here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ borrow occurs here +LL | f.use_ref(); + | - borrow later used here + +error[E0597]: `x` does not live long enough + --> $DIR/closure-borrow-spans.rs:98:17 + | +LL | f = || *x = 0; //~ ERROR + | -- ^ borrowed value does not live long enough + | | + | value captured here +LL | } + | - `x` dropped here while still borrowed +LL | f.use_ref(); + | - borrow later used here + +error[E0506]: cannot assign to `*x` because it is borrowed + --> $DIR/closure-borrow-spans.rs:105:5 + | +LL | let f = || *x = 0; + | -- - borrow occurs due to use in closure + | | + | borrow of `*x` occurs here +LL | *x = 1; //~ ERROR + | ^^^^^^ assignment to borrowed `*x` occurs here +LL | f.use_ref(); + | - borrow later used here + +error: aborting due to 14 previous errors + +Some errors occurred: E0499, E0501, E0502, E0503, E0505, E0506, E0597. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/nll/closure-captures.rs b/src/test/ui/nll/closure-captures.rs index 03a22bb79a86b..16385ca2499cc 100644 --- a/src/test/ui/nll/closure-captures.rs +++ b/src/test/ui/nll/closure-captures.rs @@ -13,7 +13,7 @@ #![allow(unused)] #![feature(nll)] -// Should have one error per assigment +// Should have one error per assignment fn one_closure(x: i32) { || diff --git a/src/test/ui/nll/closure-move-spans.rs b/src/test/ui/nll/closure-move-spans.rs new file mode 100644 index 0000000000000..7e836275c8bff --- /dev/null +++ b/src/test/ui/nll/closure-move-spans.rs @@ -0,0 +1,33 @@ +// 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. + +// check that moves due to a closure capture give a special note + +#![feature(nll)] + +fn move_after_move(x: String) { + || x; + let y = x; //~ ERROR +} + +fn borrow_after_move(x: String) { + || x; + let y = &x; //~ ERROR +} + +fn borrow_mut_after_move(mut x: String) { + || x; + let y = &mut x; //~ ERROR +} + +fn fn_ref(f: F) -> F { f } +fn fn_mut(f: F) -> F { f } + +fn main() {} diff --git a/src/test/ui/nll/closure-move-spans.stderr b/src/test/ui/nll/closure-move-spans.stderr new file mode 100644 index 0000000000000..80b7b4246a747 --- /dev/null +++ b/src/test/ui/nll/closure-move-spans.stderr @@ -0,0 +1,39 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closure-move-spans.rs:17:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = x; //~ ERROR + | ^ value used here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:22:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &x; //~ ERROR + | ^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `x` + --> $DIR/closure-move-spans.rs:27:13 + | +LL | || x; + | -- - variable moved due to use in closure + | | + | value moved into closure here +LL | let y = &mut x; //~ ERROR + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs index 598839f872e01..ce44903e6e6a8 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs @@ -27,8 +27,8 @@ fn test() { { let y = 22; - let mut closure = || { //~ ERROR `y` does not live long enough [E0597] - let mut closure1 = || p = &y; + let mut closure = || { + let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] closure1(); }; diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index bf12800e58d71..ed2ae2f27b57b 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -1,7 +1,7 @@ note: External requirements --> $DIR/escape-upvar-nested.rs:31:32 | -LL | let mut closure1 = || p = &y; +LL | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] | ^^^^^^^^^ | = note: defining type: DefId(0/1:10 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [ @@ -16,9 +16,9 @@ LL | let mut closure1 = || p = &y; note: External requirements --> $DIR/escape-upvar-nested.rs:30:27 | -LL | let mut closure = || { //~ ERROR `y` does not live long enough [E0597] +LL | let mut closure = || { | ___________________________^ -LL | | let mut closure1 = || p = &y; +LL | | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] LL | | closure1(); LL | | }; | |_________^ @@ -47,20 +47,18 @@ LL | | } = note: defining type: DefId(0/0:3 ~ escape_upvar_nested[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough - --> $DIR/escape-upvar-nested.rs:30:27 + --> $DIR/escape-upvar-nested.rs:31:40 | -LL | let mut closure = || { //~ ERROR `y` does not live long enough [E0597] - | ___________________________^ -LL | | let mut closure1 = || p = &y; -LL | | closure1(); -LL | | }; - | |_________^ borrowed value does not live long enough +LL | let mut closure = || { + | -- value captured here +LL | let mut closure1 = || p = &y; //~ ERROR `y` does not live long enough [E0597] + | ^ borrowed value does not live long enough ... -LL | } - | - `y` dropped here while still borrowed +LL | } + | - `y` dropped here while still borrowed LL | -LL | deref(p); - | - borrow later used here +LL | deref(p); + | - borrow later used here error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index 4b0dad3bda022..8db56deeb1f7a 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -28,10 +28,12 @@ LL | | } = note: defining type: DefId(0/0:3 ~ escape_upvar_ref[317d]::test[0]) with substs [] error[E0597]: `y` does not live long enough - --> $DIR/escape-upvar-ref.rs:33:27 + --> $DIR/escape-upvar-ref.rs:33:35 | LL | let mut closure = || p = &y; - | ^^^^^^^^^ borrowed value does not live long enough + | -- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed diff --git a/src/test/ui/nll/closure-use-spans.rs b/src/test/ui/nll/closure-use-spans.rs new file mode 100644 index 0000000000000..7ab382a96bbb4 --- /dev/null +++ b/src/test/ui/nll/closure-use-spans.rs @@ -0,0 +1,33 @@ +// 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. + +// check that liveness due to a closure capture gives a special note + +#![feature(nll)] + +fn use_as_borrow_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + || *y; +} + +fn use_as_borrow_mut_capture(mut x: i32) { + let y = &mut x; + x = 0; //~ ERROR + || *y = 1; +} + +fn use_as_move_capture(mut x: i32) { + let y = &x; + x = 0; //~ ERROR + move || *y; +} + +fn main() {} diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr new file mode 100644 index 0000000000000..7e5f9621d0955 --- /dev/null +++ b/src/test/ui/nll/closure-use-spans.stderr @@ -0,0 +1,33 @@ +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:17:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y; + | - borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:23:5 + | +LL | let y = &mut x; + | ------ borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | || *y = 1; + | - borrow later captured here by closure + +error[E0506]: cannot assign to `x` because it is borrowed + --> $DIR/closure-use-spans.rs:29:5 + | +LL | let y = &x; + | -- borrow of `x` occurs here +LL | x = 0; //~ ERROR + | ^^^^^ assignment to borrowed `x` occurs here +LL | move || *y; + | - borrow later captured here by closure + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0506`. diff --git a/src/test/ui/nll/closures-in-loops.rs b/src/test/ui/nll/closures-in-loops.rs new file mode 100644 index 0000000000000..c6113f3a9c50a --- /dev/null +++ b/src/test/ui/nll/closures-in-loops.rs @@ -0,0 +1,36 @@ +// 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. + +// Test messages where a closure capture conflicts with itself because it's in +// a loop. + +#![feature(nll)] + +fn repreated_move(x: String) { + for i in 0..10 { + || x; //~ ERROR + } +} + +fn repreated_mut_borrow(mut x: String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| x = String::new()); //~ ERROR + } +} + +fn repreated_unique_borrow(x: &mut String) { + let mut v = Vec::new(); + for i in 0..10 { + v.push(|| *x = String::new()); //~ ERROR + } +} + +fn main() {} diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr new file mode 100644 index 0000000000000..9758a80362000 --- /dev/null +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -0,0 +1,30 @@ +error[E0382]: use of moved value: `x` + --> $DIR/closures-in-loops.rs:18:9 + | +LL | || x; //~ ERROR + | ^^ - use occurs due to use in closure + | | + | value moved into closure here in previous iteration of loop + | + = note: move occurs because `x` has type `std::string::String`, which does not implement the `Copy` trait + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/closures-in-loops.rs:25:16 + | +LL | v.push(|| x = String::new()); //~ ERROR + | ^^ - borrows occur due to use of `x` in closure + | | + | mutable borrow starts here in previous iteration of loop + +error[E0524]: two closures require unique access to `x` at the same time + --> $DIR/closures-in-loops.rs:32:16 + | +LL | v.push(|| *x = String::new()); //~ ERROR + | ^^ - borrows occur due to use of `x` in closure + | | + | closures are constructed here in different iterations of loop + +error: aborting due to 3 previous errors + +Some errors occurred: E0382, E0499, E0524. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr index 269bc368305cb..2ecfe03e7de62 100644 --- a/src/test/ui/nll/issue-51268.stderr +++ b/src/test/ui/nll/issue-51268.stderr @@ -8,7 +8,7 @@ LL | self.thing.bar(|| { | || LL | || //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502] LL | || &self.number; - | || ---- previous borrow occurs due to use of `self` in closure + | || ---- first borrow occurs due to use of `self` in closure LL | || }); | || ^ | ||__________| diff --git a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr index ae7193ef4fa79..d0d6bd4c78570 100644 --- a/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr +++ b/src/test/ui/region-borrow-params-issue-29793-small.nll.stderr @@ -1,44 +1,54 @@ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:19:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:19:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:19:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:19:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:34:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:34:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:34:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:65:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:65:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed @@ -50,10 +60,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:65:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:65:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed @@ -65,10 +77,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:76:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:76:34 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `x` dropped here while still borrowed @@ -80,10 +94,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:76:17 + --> $DIR/region-borrow-params-issue-29793-small.rs:76:45 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | }; | - `y` dropped here while still borrowed @@ -95,10 +111,12 @@ LL | fn g<'a>(x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:100:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:100:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -110,10 +128,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:100:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:100:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -125,10 +145,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:114:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:114:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -140,10 +162,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:114:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:114:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -155,10 +179,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:142:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:142:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -170,10 +196,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:142:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:142:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -185,10 +213,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:157:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:157:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -200,10 +230,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:157:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:157:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -215,10 +247,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:185:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:185:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -230,10 +264,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:185:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:185:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed @@ -245,10 +281,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `x` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:199:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:199:38 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `x` dropped here while still borrowed @@ -260,10 +298,12 @@ LL | fn g<'a>(&self, x: usize, y:usize) -> Box usize + 'a> { | ^^ error[E0597]: `y` does not live long enough - --> $DIR/region-borrow-params-issue-29793-small.rs:199:21 + --> $DIR/region-borrow-params-issue-29793-small.rs:199:49 | LL | let f = |t: bool| if t { x } else { y }; // (separate errors for `x` vs `y`) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough + | --------- ^ borrowed value does not live long enough + | | + | value captured here ... LL | } | - `y` dropped here while still borrowed diff --git a/src/test/ui/regions-nested-fns-2.nll.stderr b/src/test/ui/regions-nested-fns-2.nll.stderr index 13e34d85210a7..1b5bb7d500779 100644 --- a/src/test/ui/regions-nested-fns-2.nll.stderr +++ b/src/test/ui/regions-nested-fns-2.nll.stderr @@ -1,13 +1,14 @@ error[E0597]: `y` does not live long enough - --> $DIR/regions-nested-fns-2.rs:16:9 + --> $DIR/regions-nested-fns-2.rs:18:25 | -LL | / |z| { -LL | | //~^ ERROR E0373 -LL | | if false { &y } else { z } -LL | | }); - | |_________^ borrowed value does not live long enough -LL | } - | - `y` dropped here while still borrowed +LL | |z| { + | --- value captured here +LL | //~^ ERROR E0373 +LL | if false { &y } else { z } + | ^ borrowed value does not live long enough +LL | }); +LL | } + | - `y` dropped here while still borrowed | = note: borrowed value must be valid for the static lifetime... diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr index b3563f1b6203c..c7dbc043cdaee 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr @@ -8,7 +8,7 @@ LL | f(Box::new(|| { | | LL | | //~^ ERROR: cannot borrow `f` as mutable more than once LL | | f((Box::new(|| {}))) - | | - borrow occurs due to use of `f` in closure + | | - second borrow occurs due to use of `f` in closure LL | | })); | |_______- borrow later used here @@ -37,18 +37,17 @@ LL | foo(f); error[E0505]: cannot move out of `f` because it is borrowed --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16 | -LL | f(Box::new(|a| { - | _____-__________^ - | | | - | |_____borrow of `f` occurs here - | || -LL | || foo(f); -LL | || //~^ ERROR cannot move `f` into closure because it is borrowed -LL | || //~| ERROR cannot move out of captured outer variable in an `FnMut` closure -LL | || }), 3); - | ||_____^____- borrow later used here - | |_____| - | move out of `f` occurs here +LL | f(Box::new(|a| { + | - ^^^ move out of `f` occurs here + | | + | _____borrow of `f` occurs here + | | +LL | | foo(f); + | | - move occurs due to use in closure +LL | | //~^ ERROR cannot move `f` into closure because it is borrowed +LL | | //~| ERROR cannot move out of captured outer variable in an `FnMut` closure +LL | | }), 3); + | |__________- borrow later used here error: aborting due to 5 previous errors diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr index 1753f710b8842..c14cb7098933f 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr @@ -11,19 +11,18 @@ LL | bad.join(); | --- borrow later used here error[E0597]: `y` does not live long enough - --> $DIR/send-is-not-static-ensures-scoping.rs:29:16 + --> $DIR/send-is-not-static-ensures-scoping.rs:30:22 | -LL | scoped(|| { - | ________________^ -LL | | let _z = y; -LL | | //~^ ERROR `y` does not live long enough -LL | | }) - | |_________^ borrowed value does not live long enough -LL | }; - | - `y` dropped here while still borrowed +LL | scoped(|| { + | -- value captured here +LL | let _z = y; + | ^ borrowed value does not live long enough +... +LL | }; + | - `y` dropped here while still borrowed LL | -LL | bad.join(); - | --- borrow later used here +LL | bad.join(); + | --- borrow later used here error: aborting due to 2 previous errors diff --git a/src/tools/lld b/src/tools/lld index 8214ccf861d53..f76ea3ca16ed2 160000 --- a/src/tools/lld +++ b/src/tools/lld @@ -1 +1 @@ -Subproject commit 8214ccf861d538671b0a1436dbf4538dc4a64d09 +Subproject commit f76ea3ca16ed22dde8ef929db74a4b4df6f2f899