diff --git a/configure b/configure index fd0397e5f87c5..59a3c1c828d4e 100755 --- a/configure +++ b/configure @@ -645,7 +645,6 @@ valopt datadir "${CFG_PREFIX}/share" "install data" valopt infodir "${CFG_PREFIX}/share/info" "install additional info" valopt llvm-root "" "set LLVM root" valopt python "" "set path to python" -valopt nodejs "" "set path to nodejs" valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located" valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple" valopt android-cross-path "" "Android NDK standalone path (deprecated)" @@ -762,9 +761,6 @@ if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then err "Found $python_version, but Python 2.7 is required" fi -# Checking for node, but not required -probe CFG_NODEJS nodejs node - # If we have no git directory then we are probably a tarball distribution # and shouldn't attempt to load submodules if [ ! -e ${CFG_SRC_DIR}.git ] diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index a70a15b383ccc..cdbbc229bc84e 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -104,8 +104,7 @@ fn main() { let is_panic_abort = args.windows(2).any(|a| { &*a[0] == "--crate-name" && &*a[1] == "panic_abort" }); - // FIXME(stage0): remove this `stage != "0"` condition - if is_panic_abort && stage != "0" { + if is_panic_abort { cmd.arg("-C").arg("panic=abort"); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9de438cfa7d50..16dbcae99fa1d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -25,7 +25,7 @@ use std::process::Command; use build_helper::output; use filetime::FileTime; -use util::{exe, staticlib, libdir, mtime, is_dylib, copy}; +use util::{exe, libdir, mtime, is_dylib, copy}; use {Build, Compiler, Mode}; /// Build the standard library. @@ -40,20 +40,6 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { let libdir = build.sysroot_libdir(compiler, target); let _ = fs::remove_dir_all(&libdir); t!(fs::create_dir_all(&libdir)); - // FIXME(stage0) remove this `if` after the next snapshot - // The stage0 compiler still passes the `-lcompiler-rt` flag to the linker but now `bootstrap` - // never builds a `libcopmiler-rt.a`! We'll fill the hole by simply copying stage0's - // `libcompiler-rt.a` to where the stage1's one is expected (though we could as well just use - // an empty `.a` archive). Note that the symbols of that stage0 `libcompiler-rt.a` won't make - // it to the final binary because now `libcore.rlib` also contains the symbols that - // `libcompiler-rt.a` provides. Since that rlib appears first in the linker arguments, its - // symbols are used instead of `libcompiler-rt.a`'s. - if compiler.stage == 0 { - let rtlib = &staticlib("compiler-rt", target); - let src = build.rustc.parent().unwrap().parent().unwrap().join("lib").join("rustlib") - .join(target).join("lib").join(rtlib); - copy(&src, &libdir.join(rtlib)); - } // Some platforms have startup objects that may be required to produce the // libstd dynamic library, for example. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0f69bcfbb649d..a8434c3efb358 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -396,9 +396,6 @@ impl Config { self.rustc = Some(PathBuf::from(value).join("bin/rustc")); self.cargo = Some(PathBuf::from(value).join("bin/cargo")); } - "CFG_NODEJS" if value.len() > 0 => { - self.nodejs = Some(PathBuf::from(value)); - } _ => {} } } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 05c35543e3e5b..962d0666f69f1 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -40,17 +40,23 @@ pub fn check(build: &mut Build) { panic!("PATH contains invalid character '\"'"); } } - let mut need_cmd = |cmd: &OsStr| { - if !checked.insert(cmd.to_owned()) { - return - } + let have_cmd = |cmd: &OsStr| { for path in env::split_paths(&path).map(|p| p.join(cmd)) { if fs::metadata(&path).is_ok() || fs::metadata(path.with_extension("exe")).is_ok() { - return + return Some(path); } } - panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); + return None; + }; + + let mut need_cmd = |cmd: &OsStr| { + if !checked.insert(cmd.to_owned()) { + return + } + if have_cmd(cmd).is_none() { + panic!("\n\ncouldn't find required command: {:?}\n\n", cmd); + } }; // If we've got a git directory we're gona need git to update @@ -75,8 +81,13 @@ pub fn check(build: &mut Build) { need_cmd("python".as_ref()); - // If a manual nodejs was added to the config, - // of if a nodejs install is detected through config, use it. + // Look for the nodejs command, needed for emscripten testing + if let Some(node) = have_cmd("node".as_ref()) { + build.config.nodejs = Some(node); + } else if let Some(node) = have_cmd("nodejs".as_ref()) { + build.config.nodejs = Some(node); + } + if let Some(ref s) = build.config.nodejs { need_cmd(s.as_ref()); } diff --git a/src/doc/book/syntax-index.md b/src/doc/book/syntax-index.md index 0259db221b6bc..1e05b01d30d46 100644 --- a/src/doc/book/syntax-index.md +++ b/src/doc/book/syntax-index.md @@ -61,7 +61,6 @@ * `-` (`- expr`): arithmetic negation. Overloadable (`Neg`). * `-=` (`var -= expr`): arithmetic subtraction & assignment. Overloadable (`SubAssign`). * `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures]. -* `-> !` (`fn(…) -> !`, `|…| -> !`): diverging function or closure. See [Diverging Functions]. * `.` (`expr.ident`): member access. See [Structs], [Method Syntax]. * `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal. * `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)]. @@ -159,6 +158,10 @@ * `/*!…*/`: inner block doc comment. See [Comments]. * `/**…*/`: outer block doc comment. See [Comments]. + + +* `!`: always empty Never type. See [Diverging Functions]. + * `()`: empty tuple (*a.k.a.* unit), both literal and type. diff --git a/src/doc/grammar.md b/src/doc/grammar.md index be64379b516e7..690d44cc2cb7b 100644 --- a/src/doc/grammar.md +++ b/src/doc/grammar.md @@ -764,6 +764,13 @@ bound-list := bound | bound '+' bound-list bound := path | lifetime ``` +### Never type +An empty type + +```antlr +never_type : "!" ; +``` + ### Object types **FIXME:** grammar? diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 5f9ccd1820ca6..e3c92fc1aa830 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -127,7 +127,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// } /// ``` -#[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Arc { ptr: Shared>, @@ -153,7 +152,6 @@ impl, U: ?Sized> CoerceUnsized> for Arc {} /// nodes behind strong `Arc` pointers, and then storing the parent pointers /// as `Weak` pointers. -#[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "arc_weak", since = "1.4.0")] pub struct Weak { ptr: Shared>, diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index c6453da3f4697..31491106d97ee 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -88,7 +88,6 @@ #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unique)] -#![cfg_attr(stage0, feature(unsafe_no_drop_flag))] #![feature(unsize)] #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 23542215fa890..e153507956b9f 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -44,7 +44,6 @@ use core::cmp; /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. -#[cfg_attr(stage0, unsafe_no_drop_flag)] pub struct RawVec { ptr: Unique, cap: usize, diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index e0f635f195bcd..4a4de419f2ede 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -252,7 +252,6 @@ struct RcBox { /// that you have to call them as e.g. `Rc::get_mut(&value)` instead of /// `value.get_mut()`. This avoids conflicts with methods of the inner /// type `T`. -#[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Rc { ptr: Shared>, @@ -873,7 +872,6 @@ impl From for Rc { /// /// [rc]: struct.Rc.html /// [downgrade]: struct.Rc.html#method.downgrade -#[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "rc_weak", since = "1.4.0")] pub struct Weak { ptr: Shared>, diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index c5a921693475a..990de541b6783 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -52,7 +52,6 @@ #![feature(step_by)] #![feature(unicode)] #![feature(unique)] -#![cfg_attr(stage0, feature(unsafe_no_drop_flag))] #![cfg_attr(test, feature(rand, test))] #![no_std] diff --git a/src/libcollections/macros.rs b/src/libcollections/macros.rs index d6a8362d58182..3115be00a4d72 100644 --- a/src/libcollections/macros.rs +++ b/src/libcollections/macros.rs @@ -68,7 +68,9 @@ macro_rules! vec { } /// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See `std::fmt` for more information. +/// See [`std::fmt`][fmt] for more information. +/// +/// [fmt]: ../std/fmt/index.html /// /// # Examples /// diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f8b4a92df2c5d..e868a542d55fd 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -268,7 +268,6 @@ use super::range::RangeArgument; /// Vec does not currently guarantee the order in which elements are dropped /// (the order has changed in the past, and may change again). /// -#[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Vec { buf: RawVec, diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs index fbcf5204d2537..4a703b3da68f6 100644 --- a/src/libcompiler_builtins/lib.rs +++ b/src/libcompiler_builtins/lib.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![cfg_attr(not(stage0), feature(compiler_builtins))] +#![feature(compiler_builtins)] #![no_std] -#![cfg_attr(not(stage0), compiler_builtins)] +#![compiler_builtins] #![unstable(feature = "compiler_builtins_lib", reason = "internal implementation detail of rustc right now", issue = "0")] diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0b800cacfc19a..d72b18ae345ce 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -129,13 +129,6 @@ pub struct AssertParamIsClone { _field: ::marker::PhantomData reason = "deriving hack, should not be public", issue = "0")] pub struct AssertParamIsCopy { _field: ::marker::PhantomData } -#[cfg(stage0)] -#[doc(hidden)] -#[inline(always)] -#[unstable(feature = "derive_clone_copy", - reason = "deriving hack, should not be public", - issue = "0")] -pub fn assert_receiver_is_clone(_: &T) {} #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: ?Sized> Clone for &'a T { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 6c4da2a88510d..e844a158484af 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -194,14 +194,12 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. pub fn assume(b: bool); - #[cfg(not(stage0))] /// Hints to the compiler that branch condition is likely to be true. /// Returns the value passed to it. /// /// Any use other than with `if` statements will probably not have an effect. pub fn likely(b: bool) -> bool; - #[cfg(not(stage0))] /// Hints to the compiler that branch condition is likely to be false. /// Returns the value passed to it. /// diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 107cf9b6cae6b..4e83cc328f826 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -32,7 +32,6 @@ use ty::{self, Ty, TyCtxt}; use mir::repr::Mir; use mir::mir_map::MirMap; use session::Session; -use session::config::PanicStrategy; use session::search_paths::PathKind; use util::nodemap::{NodeSet, DefIdMap}; use std::path::PathBuf; @@ -46,6 +45,7 @@ use syntax_pos::Span; use rustc_back::target::Target; use hir; use hir::intravisit::Visitor; +use rustc_back::PanicStrategy; pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index c6908e11ed209..159b7256c7a27 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -64,9 +64,10 @@ use hir::def_id::CrateNum; use session; -use session::config::{self, PanicStrategy}; +use session::config; use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; use util::nodemap::FnvHashMap; +use rustc_back::PanicStrategy; /// A list of dependencies for a certain crate type. /// @@ -357,7 +358,7 @@ fn verify_ok(sess: &session::Session, list: &[Linkage]) { // only one, but we perform validation here that all the panic strategy // compilation modes for the whole DAG are valid. if let Some((cnum, found_strategy)) = panic_runtime { - let desired_strategy = sess.opts.cg.panic.clone(); + let desired_strategy = sess.panic_strategy(); // First up, validate that our selected panic runtime is indeed exactly // our same strategy. diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index c2f275e6deaf8..aa75c7a572bc5 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -10,10 +10,11 @@ //! Validity checking for weak lang items -use session::config::{self, PanicStrategy}; +use session::config; use session::Session; use middle::lang_items; +use rustc_back::PanicStrategy; use syntax::ast; use syntax::parse::token::InternedString; use syntax_pos::Span; @@ -92,7 +93,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { // symbols. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. let mut whitelisted = HashSet::new(); - if sess.opts.cg.panic != PanicStrategy::Unwind { + if sess.panic_strategy() != PanicStrategy::Unwind { whitelisted.insert(lang_items::EhPersonalityLangItem); whitelisted.insert(lang_items::EhUnwindResumeLangItem); } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e906c24df0ff1..f8b06bf2e9762 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -19,6 +19,7 @@ pub use self::DebugInfoLevel::*; use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; +use rustc_back::PanicStrategy; use rustc_back::target::Target; use lint; use middle::cstore; @@ -492,21 +493,6 @@ impl Passes { } } -#[derive(Clone, PartialEq, Hash, RustcEncodable, RustcDecodable)] -pub enum PanicStrategy { - Unwind, - Abort, -} - -impl PanicStrategy { - pub fn desc(&self) -> &str { - match *self { - PanicStrategy::Unwind => "unwind", - PanicStrategy::Abort => "abort", - } - } -} - /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all /// at once. The goal of this macro is to define an interface that can be /// programmatically used by the option parser in order to initialize the struct @@ -620,7 +606,8 @@ macro_rules! options { #[allow(dead_code)] mod $mod_set { - use super::{$struct_name, Passes, SomePasses, AllPasses, PanicStrategy}; + use super::{$struct_name, Passes, SomePasses, AllPasses}; + use rustc_back::PanicStrategy; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -732,10 +719,10 @@ macro_rules! options { } } - fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool { + fn parse_panic_strategy(slot: &mut Option, v: Option<&str>) -> bool { match v { - Some("unwind") => *slot = PanicStrategy::Unwind, - Some("abort") => *slot = PanicStrategy::Abort, + Some("unwind") => *slot = Some(PanicStrategy::Unwind), + Some("abort") => *slot = Some(PanicStrategy::Abort), _ => return false } true @@ -809,7 +796,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], "set the inlining threshold for"), - panic: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, + panic: Option = (None, parse_panic_strategy, [TRACKED], "panic strategy to compile crate with"), } @@ -1665,9 +1652,10 @@ mod dep_tracking { use std::collections::BTreeMap; use std::hash::{Hash, SipHasher}; use std::path::PathBuf; - use super::{Passes, PanicStrategy, CrateType, OptLevel, DebugInfoLevel, + use super::{Passes, CrateType, OptLevel, DebugInfoLevel, OutputTypes, Externs, ErrorOutputType}; use syntax::feature_gate::UnstableFeatures; + use rustc_back::PanicStrategy; pub trait DepTrackingHash { fn hash(&self, &mut SipHasher, ErrorOutputType); @@ -1706,6 +1694,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); + impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(CrateType); @@ -1772,7 +1761,8 @@ mod tests { use std::iter::FromIterator; use std::path::PathBuf; use std::rc::Rc; - use super::{OutputType, OutputTypes, Externs, PanicStrategy}; + use super::{OutputType, OutputTypes, Externs}; + use rustc_back::PanicStrategy; use syntax::{ast, attr}; use syntax::parse::token::InternedString; use syntax::codemap::dummy_spanned; @@ -2318,7 +2308,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.cg.panic = PanicStrategy::Abort; + opts.cg.panic = Some(PanicStrategy::Abort); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 268dbd70bb5bb..f706bab32c80a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -15,7 +15,7 @@ use lint; use middle::cstore::CrateStore; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, PanicStrategy}; +use session::config::DebugInfoLevel; use ty::tls; use util::nodemap::{NodeMap, FnvHashMap}; use util::common::duration_to_secs_str; @@ -33,6 +33,7 @@ use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; use syntax_pos::{Span, MultiSpan}; +use rustc_back::PanicStrategy; use rustc_back::target::Target; use rustc_data_structures::flock; use llvm; @@ -42,6 +43,7 @@ use std::cell::{self, Cell, RefCell}; use std::collections::HashMap; use std::env; use std::ffi::CString; +use std::io::Write; use std::rc::Rc; use std::fmt; use std::time::Duration; @@ -306,9 +308,13 @@ impl Session { pub fn lto(&self) -> bool { self.opts.cg.lto } + /// Returns the panic strategy for this compile session. If the user explicitly selected one + /// using '-C panic', use that, otherwise use the panic strategy defined by the target. + pub fn panic_strategy(&self) -> PanicStrategy { + self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy) + } pub fn no_landing_pads(&self) -> bool { - self.opts.debugging_opts.no_landing_pads || - self.opts.cg.panic == PanicStrategy::Abort + self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort } pub fn unstable_options(&self) -> bool { self.opts.debugging_opts.unstable_options @@ -449,7 +455,8 @@ pub fn build_session(sopts: config::Options, local_crate_source_file, registry, cstore, - Rc::new(codemap::CodeMap::new())) + Rc::new(codemap::CodeMap::new()), + None) } pub fn build_session_with_codemap(sopts: config::Options, @@ -457,7 +464,8 @@ pub fn build_session_with_codemap(sopts: config::Options, local_crate_source_file: Option, registry: errors::registry::Registry, cstore: Rc CrateStore<'a>>, - codemap: Rc) + codemap: Rc, + emitter_dest: Option>) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -470,14 +478,21 @@ pub fn build_session_with_codemap(sopts: config::Options, .unwrap_or(true); let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug; - let emitter: Box = match sopts.error_format { - config::ErrorOutputType::HumanReadable(color_config) => { + let emitter: Box = match (sopts.error_format, emitter_dest) { + (config::ErrorOutputType::HumanReadable(color_config), None) => { Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()))) } - config::ErrorOutputType::Json => { + (config::ErrorOutputType::HumanReadable(_), Some(dst)) => { + Box::new(EmitterWriter::new(dst, + Some(codemap.clone()))) + } + (config::ErrorOutputType::Json, None) => { Box::new(JsonEmitter::stderr(Some(registry), codemap.clone())) } + (config::ErrorOutputType::Json, Some(dst)) => { + Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone())) + } }; let diagnostic_handler = diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0c7c387b67ea3..b1f80455dd98b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -17,7 +17,7 @@ use hir::TraitMap; use hir::def::DefMap; use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use hir::map as ast_map; -use hir::map::{DefKey, DefPath, DefPathData, DisambiguatedDefPathData}; +use hir::map::{DefKey, DefPathData, DisambiguatedDefPathData}; use middle::free_region::FreeRegionMap; use middle::region::RegionMaps; use middle::resolve_lifetime; @@ -546,8 +546,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn retrace_path(self, path: &DefPath) -> Option { - debug!("retrace_path(path={:?}, krate={:?})", path, self.crate_name(path.krate)); + pub fn retrace_path(self, + krate: CrateNum, + path_data: &[DisambiguatedDefPathData]) + -> Option { + debug!("retrace_path(path={:?}, krate={:?})", path_data, self.crate_name(krate)); let root_key = DefKey { parent: None, @@ -557,22 +560,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }, }; - let root_index = self.def_index_for_def_key(path.krate, root_key) + let root_index = self.def_index_for_def_key(krate, root_key) .expect("no root key?"); debug!("retrace_path: root_index={:?}", root_index); let mut index = root_index; - for data in &path.data { + for data in path_data { let key = DefKey { parent: Some(index), disambiguated_data: data.clone() }; debug!("retrace_path: key={:?}", key); - match self.def_index_for_def_key(path.krate, key) { + match self.def_index_for_def_key(krate, key) { Some(i) => index = i, None => return None, } } - Some(DefId { krate: path.krate, index: index }) + Some(DefId { krate: krate, index: index }) } pub fn type_parameter_def(self, diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index f7ae47d2e5e56..c0f358ca8017b 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -45,8 +45,36 @@ extern crate libc; extern crate serialize; #[macro_use] extern crate log; +extern crate serialize as rustc_serialize; // used by deriving + pub mod tempdir; pub mod sha2; pub mod target; pub mod slice; pub mod dynamic_lib; + +use serialize::json::{Json, ToJson}; + +#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] +pub enum PanicStrategy { + Unwind, + Abort, +} + +impl PanicStrategy { + pub fn desc(&self) -> &str { + match *self { + PanicStrategy::Unwind => "unwind", + PanicStrategy::Abort => "abort", + } + } +} + +impl ToJson for PanicStrategy { + fn to_json(&self) -> Json { + match *self { + PanicStrategy::Abort => "abort".to_json(), + PanicStrategy::Unwind => "unwind".to_json(), + } + } +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 087078021a188..3eddd911749e5 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -50,6 +50,8 @@ use std::default::Default; use std::io::prelude::*; use syntax::abi::Abi; +use PanicStrategy; + mod android_base; mod apple_base; mod apple_ios_base; @@ -347,6 +349,9 @@ pub struct TargetOptions { /// Maximum integer size in bits that this target can perform atomic /// operations on. pub max_atomic_width: u64, + + /// Panic strategy: "unwind" or "abort" + pub panic_strategy: PanicStrategy, } impl Default for TargetOptions { @@ -396,6 +401,7 @@ impl Default for TargetOptions { has_elf_tls: false, obj_is_bitcode: false, max_atomic_width: 0, + panic_strategy: PanicStrategy::Unwind, } } } @@ -474,6 +480,19 @@ impl Target { .map(|o| o.as_u64() .map(|s| base.options.$key_name = s)); } ); + ($key_name:ident, PanicStrategy) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match s { + "unwind" => base.options.$key_name = PanicStrategy::Unwind, + "abort" => base.options.$key_name = PanicStrategy::Abort, + _ => return Some(Err(format!("'{}' is not a valid value for \ + panic-strategy. Use 'unwind' or 'abort'.", + s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); ($key_name:ident, list) => ( { let name = (stringify!($key_name)).replace("_", "-"); obj.find(&name[..]).map(|o| o.as_array() @@ -534,6 +553,7 @@ impl Target { key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(max_atomic_width, u64); + try!(key!(panic_strategy, PanicStrategy)); Ok(base) } @@ -676,6 +696,7 @@ impl ToJson for Target { target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(max_atomic_width); + target_option_val!(panic_strategy); Json::Object(d) } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 5089af892859b..5ac4512fe3900 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -74,6 +74,7 @@ use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType}; use rustc::session::config::nightly_options; +use rustc::session::early_error; use rustc::lint::Lint; use rustc::lint; use rustc_metadata::loader; @@ -93,8 +94,6 @@ use std::str; use std::sync::{Arc, Mutex}; use std::thread; -use rustc::session::early_error; - use syntax::{ast, json}; use syntax::codemap::{CodeMap, FileLoader, RealFileLoader}; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; @@ -131,17 +130,18 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { } } -pub fn run(args: Vec) -> isize { +pub fn run(run_compiler: F) -> isize + where F: FnOnce() -> (CompileResult, Option) + Send + 'static +{ monitor(move || { - let (result, session) = run_compiler(&args, &mut RustcDefaultCalls); + let (result, session) = run_compiler(); if let Err(err_count) = result { if err_count > 0 { match session { Some(sess) => sess.fatal(&abort_msg(err_count)), None => { let emitter = - errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, - None); + errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None); let handler = errors::Handler::with_emitter(true, false, Box::new(emitter)); handler.emit(&MultiSpan::new(), &abort_msg(err_count), @@ -155,20 +155,15 @@ pub fn run(args: Vec) -> isize { 0 } -pub fn run_compiler<'a>(args: &[String], - callbacks: &mut CompilerCalls<'a>) - -> (CompileResult, Option) { - run_compiler_with_file_loader(args, callbacks, box RealFileLoader) -} - // Parse args and run the compiler. This is the primary entry point for rustc. // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. -pub fn run_compiler_with_file_loader<'a, L>(args: &[String], - callbacks: &mut CompilerCalls<'a>, - loader: Box) - -> (CompileResult, Option) - where L: FileLoader + 'static { +pub fn run_compiler<'a>(args: &[String], + callbacks: &mut CompilerCalls<'a>, + file_loader: Option>, + emitter_dest: Option>) + -> (CompileResult, Option) +{ macro_rules! do_or_return {($expr: expr, $sess: expr) => { match $expr { Compilation::Stop => return (Ok(()), $sess), @@ -207,13 +202,16 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String], let dep_graph = DepGraph::new(sopts.build_dep_graph()); let cstore = Rc::new(CStore::new(&dep_graph)); + + let loader = file_loader.unwrap_or(box RealFileLoader); let codemap = Rc::new(CodeMap::with_file_loader(loader)); let sess = session::build_session_with_codemap(sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), - codemap); + codemap, + emitter_dest); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg); target_features::add_configuration(&mut cfg, &sess); @@ -1144,6 +1142,9 @@ pub fn diagnostics_registry() -> errors::registry::Registry { } pub fn main() { - let result = run(env::args().collect()); + let result = run(|| run_compiler(&env::args().collect::>(), + &mut RustcDefaultCalls, + None, + None)); process::exit(result as i32); } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 6456b72dfb56c..1d7ff45b3b8a0 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -99,8 +99,10 @@ impl EmitterWriter { pub fn new(dst: Box, code_map: Option>) -> EmitterWriter { - EmitterWriter { dst: Raw(dst), - cm: code_map} + EmitterWriter { + dst: Raw(dst), + cm: code_map, + } } fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs index 619e237ee34a3..d238121872be6 100644 --- a/src/librustc_incremental/persist/directory.rs +++ b/src/librustc_incremental/persist/directory.rs @@ -20,6 +20,7 @@ use rustc::ty::TyCtxt; use rustc::util::nodemap::DefIdMap; use std::fmt::{self, Debug}; use std::iter::once; +use std::collections::HashMap; /// Index into the DefIdDirectory #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq, @@ -90,18 +91,29 @@ impl DefIdDirectory { } pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory { - let max_current_crate = self.max_current_crate(tcx); + + fn make_key(name: &str, disambiguator: &str) -> String { + format!("{}/{}", name, disambiguator) + } + + let new_krates: HashMap<_, _> = + once(LOCAL_CRATE) + .chain(tcx.sess.cstore.crates()) + .map(|krate| (make_key(&tcx.crate_name(krate), + &tcx.crate_disambiguator(krate)), krate)) + .collect(); let ids = self.paths.iter() .map(|path| { - if self.krate_still_valid(tcx, max_current_crate, path.krate) { - tcx.retrace_path(path) + let old_krate_id = path.krate.as_usize(); + assert!(old_krate_id < self.krates.len()); + let old_crate_info = &self.krates[old_krate_id]; + let old_crate_key = make_key(&old_crate_info.name, + &old_crate_info.disambiguator); + if let Some(&new_crate_key) = new_krates.get(&old_crate_key) { + tcx.retrace_path(new_crate_key, &path.data) } else { - debug!("crate {} changed from {:?} to {:?}/{:?}", - path.krate, - self.krates[path.krate.as_usize()], - tcx.crate_name(path.krate), - tcx.crate_disambiguator(path.krate)); + debug!("crate {:?} no longer exists", old_crate_key); None } }) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 2e03b7868a3bc..0c7f6204438a7 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -19,7 +19,7 @@ use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::svh::Svh; use rustc::middle::cstore::LoadedMacro; use rustc::session::{config, Session}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc::session::search_paths::PathKind; use rustc::middle; use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate}; @@ -710,7 +710,7 @@ impl<'a> CrateReader<'a> { // The logic for finding the panic runtime here is pretty much the same // as the allocator case with the only addition that the panic strategy // compilation mode also comes into play. - let desired_strategy = self.sess.opts.cg.panic.clone(); + let desired_strategy = self.sess.panic_strategy(); let mut runtime_found = false; let mut needs_panic_runtime = attr::contains_name(&krate.attrs, "needs_panic_runtime"); diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 1f25136ffe1ac..16a5b5402fbe3 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -26,7 +26,7 @@ use rustc::hir::map::DefKey; use rustc::mir::repr::Mir; use rustc::mir::mir_map::MirMap; use rustc::util::nodemap::{NodeSet, DefIdMap}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use std::path::PathBuf; use syntax::ast; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 0a1ff70a0497e..038d0f73d5ce8 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -19,7 +19,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId}; use rustc::hir::map::DefKey; use rustc::hir::svh::Svh; use rustc::middle::cstore::ExternCrate; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc_data_structures::indexed_vec::IndexVec; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap, FnvHashSet}; diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0f067270b80f5..ca4fb77d95ad6 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1293,7 +1293,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, disambiguator: tcx.sess.local_crate_disambiguator().to_string(), - panic_strategy: tcx.sess.opts.cg.panic.clone(), + panic_strategy: tcx.sess.panic_strategy(), plugin_registrar_fn: tcx.sess.plugin_registrar_fn.get().map(|id| { tcx.map.local_def_id(id).index }), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f4d1e8e17f842..58e18bc709e3c 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -18,7 +18,7 @@ use rustc::middle::cstore::{LinkagePreference, NativeLibraryKind}; use rustc::middle::lang_items; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::session::config::PanicStrategy; +use rustc_back::PanicStrategy; use rustc_serialize as serialize; use syntax::{ast, attr}; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ba45b773c09f3..1fc9c45de9306 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -683,9 +683,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; match (value_result, type_result) { - // With `#![feature(item_like_imports)]`, all namespaces - // must be re-exported with extra visibility for an error to occur. - (Ok(value_binding), Ok(type_binding)) if self.new_import_semantics => { + // All namespaces must be re-exported with extra visibility for an error to occur. + (Ok(value_binding), Ok(type_binding)) => { let vis = directive.vis.get(); if !value_binding.pseudo_vis().is_at_least(vis, self) && !type_binding.pseudo_vis().is_at_least(vis, self) { diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 683ad76952a7e..b82c5629f9da1 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector}; use base; use build::AllocaFcx; use common::{type_is_fat_ptr, BlockAndBuilder, C_uint}; @@ -598,3 +598,73 @@ impl FnType { } } } + +pub fn align_up_to(off: usize, a: usize) -> usize { + return (off + a - 1) / a * a; +} + +fn align(off: usize, ty: Type, pointer: usize) -> usize { + let a = ty_align(ty, pointer); + return align_up_to(off, a); +} + +pub fn ty_align(ty: Type, pointer: usize) -> usize { + match ty.kind() { + Integer => ((ty.int_width() as usize) + 7) / 8, + Pointer => pointer, + Float => 4, + Double => 8, + Struct => { + if ty.is_packed() { + 1 + } else { + let str_tys = ty.field_types(); + str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t, pointer))) + } + } + Array => { + let elt = ty.element_type(); + ty_align(elt, pointer) + } + Vector => { + let len = ty.vector_length(); + let elt = ty.element_type(); + ty_align(elt, pointer) * len + } + _ => bug!("ty_align: unhandled type") + } +} + +pub fn ty_size(ty: Type, pointer: usize) -> usize { + match ty.kind() { + Integer => ((ty.int_width() as usize) + 7) / 8, + Pointer => pointer, + Float => 4, + Double => 8, + Struct => { + if ty.is_packed() { + let str_tys = ty.field_types(); + str_tys.iter().fold(0, |s, t| s + ty_size(*t, pointer)) + } else { + let str_tys = ty.field_types(); + let size = str_tys.iter().fold(0, |s, t| { + align(s, *t, pointer) + ty_size(*t, pointer) + }); + align(size, ty, pointer) + } + } + Array => { + let len = ty.array_length(); + let elt = ty.element_type(); + let eltsz = ty_size(elt, pointer); + len * eltsz + } + Vector => { + let len = ty.vector_length(); + let elt = ty.element_type(); + let eltsz = ty_size(elt, pointer); + len * eltsz + }, + _ => bug!("ty_size: unhandled type") + } +} diff --git a/src/librustc_trans/cabi_aarch64.rs b/src/librustc_trans/cabi_aarch64.rs index fc11e3888d3c2..59a84439950ba 100644 --- a/src/librustc_trans/cabi_aarch64.rs +++ b/src/librustc_trans/cabi_aarch64.rs @@ -11,78 +11,12 @@ #![allow(non_upper_case_globals)] use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; -use abi::{FnType, ArgType}; +use abi::{self, FnType, ArgType}; use context::CrateContext; use type_::Type; -use std::cmp; - -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - -fn align(off: usize, ty: Type) -> usize { - let a = ty_align(ty); - return align_up_to(off, a); -} - -fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - ty_align(elt) * len - } - _ => bug!("ty_align: unhandled type") - } -} - fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - let str_tys = ty.field_types(); - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let str_tys = ty.field_types(); - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - _ => bug!("ty_size: unhandled type") - } + abi::ty_size(ty, 8) } fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> { diff --git a/src/librustc_trans/cabi_arm.rs b/src/librustc_trans/cabi_arm.rs index 68a2e8aa8ce95..93d43f7d96116 100644 --- a/src/librustc_trans/cabi_arm.rs +++ b/src/librustc_trans/cabi_arm.rs @@ -11,7 +11,7 @@ #![allow(non_upper_case_globals)] use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; -use abi::{FnType, ArgType}; +use abi::{self, align_up_to, FnType, ArgType}; use context::CrateContext; use type_::Type; @@ -24,40 +24,13 @@ pub enum Flavor { type TyAlignFn = fn(ty: Type) -> usize; -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - fn align(off: usize, ty: Type, align_fn: TyAlignFn) -> usize { let a = align_fn(ty); return align_up_to(off, a); } fn general_ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 4, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, general_ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - general_ty_align(elt) - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - general_ty_align(elt) * len - } - _ => bug!("ty_align: unhandled type") - } + abi::ty_align(ty, 4) } // For more information see: diff --git a/src/librustc_trans/cabi_mips.rs b/src/librustc_trans/cabi_mips.rs index 680310e195a41..25fe53e7ef40f 100644 --- a/src/librustc_trans/cabi_mips.rs +++ b/src/librustc_trans/cabi_mips.rs @@ -13,77 +13,17 @@ use libc::c_uint; use std::cmp; use llvm; -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; -use abi::{ArgType, FnType}; +use llvm::{Integer, Pointer, Float, Double, Vector}; +use abi::{self, align_up_to, ArgType, FnType}; use context::CrateContext; use type_::Type; -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - -fn align(off: usize, ty: Type) -> usize { - let a = ty_align(ty); - return align_up_to(off, a); -} - fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 4, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - ty_align(elt) * len - } - _ => bug!("ty_align: unhandled type") - } + abi::ty_align(ty, 4) } fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 4, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - let str_tys = ty.field_types(); - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let str_tys = ty.field_types(); - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - _ => bug!("ty_size: unhandled type") - } + abi::ty_size(ty, 4) } fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_trans/cabi_mips64.rs index e92ef1eaec8ec..e6b500c88dc7a 100644 --- a/src/librustc_trans/cabi_mips64.rs +++ b/src/librustc_trans/cabi_mips64.rs @@ -13,77 +13,17 @@ use libc::c_uint; use std::cmp; use llvm; -use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; -use abi::{ArgType, FnType}; +use llvm::{Integer, Pointer, Float, Double, Vector}; +use abi::{self, align_up_to, ArgType, FnType}; use context::CrateContext; use type_::Type; -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - -fn align(off: usize, ty: Type) -> usize { - let a = ty_align(ty); - return align_up_to(off, a); -} - fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - ty_align(elt) * len - } - _ => bug!("ty_align: unhandled type") - } + abi::ty_align(ty, 8) } fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - let str_tys = ty.field_types(); - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let str_tys = ty.field_types(); - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - _ => bug!("ty_size: unhandled type") - } + abi::ty_size(ty, 8) } fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) { diff --git a/src/librustc_trans/cabi_powerpc.rs b/src/librustc_trans/cabi_powerpc.rs index e05c31b1d88cd..4e1d7a9337827 100644 --- a/src/librustc_trans/cabi_powerpc.rs +++ b/src/librustc_trans/cabi_powerpc.rs @@ -10,67 +10,26 @@ use libc::c_uint; use llvm; -use llvm::{Integer, Pointer, Float, Double, Struct, Array}; -use abi::{FnType, ArgType}; +use llvm::{Integer, Pointer, Float, Double, Vector}; +use abi::{self, align_up_to, FnType, ArgType}; use context::CrateContext; use type_::Type; use std::cmp; -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - -fn align(off: usize, ty: Type) -> usize { - let a = ty_align(ty); - return align_up_to(off, a); -} - fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 4, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - _ => bug!("ty_size: unhandled type") + if ty.kind() == Vector { + bug!("ty_size: unhandled type") + } else { + abi::ty_align(ty, 4) } } fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 4, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - let str_tys = ty.field_types(); - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let str_tys = ty.field_types(); - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - _ => bug!("ty_size: unhandled type") + if ty.kind() == Vector { + bug!("ty_size: unhandled type") + } else { + abi::ty_size(ty, 4) } } diff --git a/src/librustc_trans/cabi_powerpc64.rs b/src/librustc_trans/cabi_powerpc64.rs index ba54e369fd838..cdc7c1fd1afb3 100644 --- a/src/librustc_trans/cabi_powerpc64.rs +++ b/src/librustc_trans/cabi_powerpc64.rs @@ -15,67 +15,16 @@ // Alignment of 128 bit types is not currently handled, this will // need to be fixed when PowerPC vector support is added. -use llvm::{Integer, Pointer, Float, Double, Struct, Array}; -use abi::{FnType, ArgType}; +use llvm::{Integer, Pointer, Float, Double, Struct, Vector, Array}; +use abi::{self, FnType, ArgType}; use context::CrateContext; use type_::Type; -use std::cmp; - -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - -fn align(off: usize, ty: Type) -> usize { - let a = ty_align(ty); - return align_up_to(off, a); -} - -fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - _ => bug!("ty_align: unhandled type") - } -} - fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - let str_tys = ty.field_types(); - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let str_tys = ty.field_types(); - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - _ => bug!("ty_size: unhandled type") + if ty.kind() == Vector { + bug!("ty_size: unhandled type") + } else { + abi::ty_size(ty, 8) } } diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_trans/cabi_s390x.rs index 19404b667e1fc..5a666c6083d16 100644 --- a/src/librustc_trans/cabi_s390x.rs +++ b/src/librustc_trans/cabi_s390x.rs @@ -12,16 +12,12 @@ // for a pre-z13 machine or using -mno-vx. use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector}; -use abi::{FnType, ArgType}; +use abi::{align_up_to, FnType, ArgType}; use context::CrateContext; use type_::Type; use std::cmp; -fn align_up_to(off: usize, a: usize) -> usize { - return (off + a - 1) / a * a; -} - fn align(off: usize, ty: Type) -> usize { let a = ty_align(ty); return align_up_to(off, a); diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index eb67f4ca6185a..33990148c8b7d 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -16,12 +16,10 @@ use self::RegClass::*; use llvm::{Integer, Pointer, Float, Double}; use llvm::{Struct, Array, Attribute, Vector}; -use abi::{ArgType, FnType}; +use abi::{self, ArgType, FnType}; use context::CrateContext; use type_::Type; -use std::cmp; - #[derive(Clone, Copy, PartialEq)] enum RegClass { NoClass, @@ -90,62 +88,11 @@ fn classify_ty(ty: Type) -> Vec { } fn ty_align(ty: Type) -> usize { - match ty.kind() { - Integer => ((ty.int_width() as usize) + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - if ty.is_packed() { - 1 - } else { - let str_tys = ty.field_types(); - str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t))) - } - } - Array => { - let elt = ty.element_type(); - ty_align(elt) - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - ty_align(elt) * len - } - _ => bug!("ty_align: unhandled type") - } + abi::ty_align(ty, 8) } fn ty_size(ty: Type) -> usize { - match ty.kind() { - Integer => (ty.int_width() as usize + 7) / 8, - Pointer => 8, - Float => 4, - Double => 8, - Struct => { - let str_tys = ty.field_types(); - if ty.is_packed() { - str_tys.iter().fold(0, |s, t| s + ty_size(*t)) - } else { - let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t)); - align(size, ty) - } - } - Array => { - let len = ty.array_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - Vector => { - let len = ty.vector_length(); - let elt = ty.element_type(); - let eltsz = ty_size(elt); - len * eltsz - } - - _ => bug!("ty_size: unhandled type") - } + abi::ty_size(ty, 8) } fn all_mem(cls: &mut [RegClass]) { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 3b4c98fc71e44..ca22faa2ec36a 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -20,7 +20,7 @@ use middle::lang_items::UnsizeTraitLangItem; use rustc::ty::subst::Subst; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc::traits::{self, Reveal}; -use rustc::ty::{ParameterEnvironment}; +use rustc::ty::ParameterEnvironment; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; use rustc::ty::{TyRef, TyAdt, TyTrait, TyNever, TyTuple}; @@ -44,13 +44,13 @@ mod orphan; mod overlap; mod unsafety; -struct CoherenceChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct CoherenceChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { crate_context: &'a CrateCtxt<'a, 'gcx>, inference_context: InferCtxt<'a, 'gcx, 'tcx>, } -struct CoherenceCheckVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - cc: &'a CoherenceChecker<'a, 'gcx, 'tcx> +struct CoherenceCheckVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + cc: &'a CoherenceChecker<'a, 'gcx, 'tcx>, } impl<'a, 'gcx, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'gcx, 'tcx> { @@ -62,36 +62,25 @@ impl<'a, 'gcx, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, ' } impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { - // Returns the def ID of the base type, if there is one. fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option { match ty.sty { - TyAdt(def, _) => { - Some(def.did) - } + TyAdt(def, _) => Some(def.did), - TyTrait(ref t) => { - Some(t.principal.def_id()) - } + TyTrait(ref t) => Some(t.principal.def_id()), - TyBox(_) => { - self.inference_context.tcx.lang_items.owned_box() - } + TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), - TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | - TyStr | TyArray(..) | TySlice(..) | TyFnDef(..) | TyFnPtr(_) | - TyTuple(..) | TyParam(..) | TyError | TyNever | - TyRawPtr(_) | TyRef(..) | TyProjection(..) => { - None - } + TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyStr | TyArray(..) | + TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyTuple(..) | TyParam(..) | TyError | + TyNever | TyRawPtr(_) | TyRef(..) | TyProjection(..) => None, TyInfer(..) | TyClosure(..) | TyAnon(..) => { // `ty` comes from a user declaration so we should only expect types // that the user can type - span_bug!( - span, - "coherence encountered unexpected type searching for base type: {}", - ty); + span_bug!(span, + "coherence encountered unexpected type searching for base type: {}", + ty); } } } @@ -100,9 +89,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. - self.crate_context.tcx.visit_all_items_in_krate( - DepNode::CoherenceCheckImpl, - &mut CoherenceCheckVisitor { cc: self }); + self.crate_context.tcx.visit_all_items_in_krate(DepNode::CoherenceCheckImpl, + &mut CoherenceCheckVisitor { cc: self }); // Populate the table of destructors. It might seem a bit strange to // do this here, but it's actually the most convenient place, since @@ -167,7 +155,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'gcx>, impl_def_id: DefId) { debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}", - impl_trait_ref, impl_def_id); + impl_trait_ref, + impl_def_id); let trait_def = self.crate_context.tcx.lookup_trait_def(impl_trait_ref.def_id); trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref); } @@ -176,9 +165,9 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { ItemImpl(.., ref impl_items) => { - impl_items.iter().map(|impl_item| { - self.crate_context.tcx.map.local_def_id(impl_item.id) - }).collect() + impl_items.iter() + .map(|impl_item| self.crate_context.tcx.map.local_def_id(impl_item.id)) + .collect() } _ => { span_bug!(item.span, "can't convert a non-impl to an impl"); @@ -186,14 +175,14 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } } - // // Destructors // fn populate_destructors(&self) { let tcx = self.crate_context.tcx; let drop_trait = match tcx.lang_items.drop_trait() { - Some(id) => id, None => { return } + Some(id) => id, + None => return, }; tcx.populate_implementations_for_trait_if_necessary(drop_trait); let drop_trait = tcx.lookup_trait_def(drop_trait); @@ -219,13 +208,14 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { match tcx.map.find(impl_node_id) { Some(hir_map::NodeItem(item)) => { let span = match item.node { - ItemImpl(.., ref ty, _) => { - ty.span - }, - _ => item.span + ItemImpl(.., ref ty, _) => ty.span, + _ => item.span, }; - struct_span_err!(tcx.sess, span, E0120, - "the Drop trait may only be implemented on structures") + struct_span_err!(tcx.sess, + span, + E0120, + "the Drop trait may only be implemented on \ + structures") .span_label(span, &format!("implementing Drop requires a struct")) .emit(); @@ -254,15 +244,14 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let copy_trait = tcx.lookup_trait_def(copy_trait); copy_trait.for_each_impl(tcx, |impl_did| { - debug!("check_implementations_of_copy: impl_did={:?}", - impl_did); + debug!("check_implementations_of_copy: impl_did={:?}", impl_did); let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) { n } else { debug!("check_implementations_of_copy(): impl not in this \ crate"); - return + return; }; let self_type = tcx.lookup_item_type(impl_did); @@ -280,14 +269,12 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { match param_env.can_type_implement_copy(tcx, self_type, span) { Ok(()) => {} Err(CopyImplementationError::InfrigingField(name)) => { - struct_span_err!(tcx.sess, span, E0204, - "the trait `Copy` may not be implemented for \ - this type") - .span_label(span, &format!( - "field `{}` does not implement `Copy`", name) - ) - .emit() - + struct_span_err!(tcx.sess, + span, + E0204, + "the trait `Copy` may not be implemented for this type") + .span_label(span, &format!("field `{}` does not implement `Copy`", name)) + .emit() } Err(CopyImplementationError::InfrigingVariant(name)) => { let item = tcx.map.expect_item(impl_node_id); @@ -297,10 +284,12 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { span }; - struct_span_err!(tcx.sess, span, E0205, + struct_span_err!(tcx.sess, + span, + E0205, "the trait `Copy` may not be implemented for this type") - .span_label(span, &format!("variant `{}` does not implement `Copy`", - name)) + .span_label(span, + &format!("variant `{}` does not implement `Copy`", name)) .emit() } Err(CopyImplementationError::NotAnAdt) => { @@ -311,15 +300,19 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { span }; - struct_span_err!(tcx.sess, span, E0206, + struct_span_err!(tcx.sess, + span, + E0206, "the trait `Copy` may not be implemented for this type") .span_label(span, &format!("type is not a structure or enumeration")) .emit(); } Err(CopyImplementationError::HasDestructor) => { - struct_span_err!(tcx.sess, span, E0184, - "the trait `Copy` may not be implemented for this type; \ - the type has a destructor") + struct_span_err!(tcx.sess, + span, + E0184, + "the trait `Copy` may not be implemented for this type; the \ + type has a destructor") .span_label(span, &format!("Copy not allowed on types with destructors")) .emit(); } @@ -359,7 +352,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap(); let target = trait_ref.substs.type_at(1); debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)", - source, target); + source, + target); let span = tcx.map.span(impl_node_id); let param_env = ParameterEnvironment::for_item(tcx, impl_node_id); @@ -368,15 +362,19 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { assert!(!source.has_escaping_regions()); debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)", - source, target); + source, + target); tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { let origin = TypeOrigin::Misc(span); - let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>, + let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, + mt_b: ty::TypeAndMut<'gcx>, mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { - infcx.report_mismatched_types(origin, mk_ptr(mt_b.ty), - target, ty::error::TypeError::Mutability); + infcx.report_mismatched_types(origin, + mk_ptr(mt_b.ty), + target, + ty::error::TypeError::Mutability); } (mt_a.ty, mt_b.ty, unsize_trait, None) }; @@ -394,37 +392,45 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) - if def_a.is_struct() && def_b.is_struct() => { + if def_a.is_struct() && def_b.is_struct() => { if def_a != def_b { let source_path = tcx.item_path_str(def_a.did); let target_path = tcx.item_path_str(def_b.did); - span_err!(tcx.sess, span, E0377, + span_err!(tcx.sess, + span, + E0377, "the trait `CoerceUnsized` may only be implemented \ for a coercion between structures with the same \ definition; expected {}, found {}", - source_path, target_path); + source_path, + target_path); return; } let fields = &def_a.struct_variant().fields; - let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| { - let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); - - if f.unsubst_ty().is_phantom_data() { - // Ignore PhantomData fields - None - } else if infcx.sub_types(false, origin, b, a).is_ok() { - // Ignore fields that aren't significantly changed - None - } else { - // Collect up all fields that were significantly changed - // i.e. those that contain T in coerce_unsized T -> U - Some((i, a, b)) - } - }).collect::>(); + let diff_fields = fields.iter() + .enumerate() + .filter_map(|(i, f)| { + let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b)); + + if f.unsubst_ty().is_phantom_data() { + // Ignore PhantomData fields + None + } else if infcx.sub_types(false, origin, b, a).is_ok() { + // Ignore fields that aren't significantly changed + None + } else { + // Collect up all fields that were significantly changed + // i.e. those that contain T in coerce_unsized T -> U + Some((i, a, b)) + } + }) + .collect::>(); if diff_fields.is_empty() { - span_err!(tcx.sess, span, E0374, + span_err!(tcx.sess, + span, + E0374, "the trait `CoerceUnsized` may only be implemented \ for a coercion between structures with one field \ being coerced, none found"); @@ -437,16 +443,22 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { tcx.map.span(impl_node_id) }; - let mut err = struct_span_err!(tcx.sess, span, E0375, - "implementing the trait `CoerceUnsized` \ - requires multiple coercions"); + let mut err = struct_span_err!(tcx.sess, + span, + E0375, + "implementing the trait \ + `CoerceUnsized` requires multiple \ + coercions"); err.note("`CoerceUnsized` may only be implemented for \ a coercion between structures with one field being coerced"); err.note(&format!("currently, {} fields need coercions: {}", - diff_fields.len(), - diff_fields.iter().map(|&(i, a, b)| { - format!("{} ({} to {})", fields[i].name, a, b) - }).collect::>().join(", ") )); + diff_fields.len(), + diff_fields.iter() + .map(|&(i, a, b)| { + format!("{} ({} to {})", fields[i].name, a, b) + }) + .collect::>() + .join(", "))); err.span_label(span, &format!("requires multiple coercions")); err.emit(); return; @@ -458,7 +470,9 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } _ => { - span_err!(tcx.sess, span, E0376, + span_err!(tcx.sess, + span, + E0376, "the trait `CoerceUnsized` may only be implemented \ for a coercion between structures"); return; @@ -469,8 +483,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // Register an obligation for `A: Trait`. let cause = traits::ObligationCause::misc(span, impl_node_id); - let predicate = tcx.predicate_for_trait_def(cause, trait_def_id, 0, - source, &[target]); + let predicate = + tcx.predicate_for_trait_def(cause, trait_def_id, 0, source, &[target]); fulfill_cx.register_predicate_obligation(&infcx, predicate); // Check that all transitive obligations are satisfied. @@ -480,8 +494,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // Finally, resolve all regions. let mut free_regions = FreeRegionMap::new(); - free_regions.relate_free_regions_from_predicates( - &infcx.parameter_environment.caller_bounds); + free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment + .caller_bounds); infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id); if let Some(kind) = kind { @@ -495,7 +509,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: DefId) { if tcx.sess.features.borrow().unboxed_closures { // the feature gate allows all of them - return + return; } let did = Some(trait_def_id); let li = &tcx.lang_items; @@ -507,14 +521,15 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def } else if did == li.fn_once_trait() { "FnOnce" } else { - return // everything OK + return; // everything OK }; let mut err = struct_span_err!(tcx.sess, sp, E0183, "manual implementations of `{}` are experimental", trait_name); - help!(&mut err, "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); + help!(&mut err, + "add `#![feature(unboxed_closures)]` to the crate attributes to enable"); err.emit(); } @@ -522,9 +537,10 @@ pub fn check_coherence(ccx: &CrateCtxt) { let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence); ccx.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { CoherenceChecker { - crate_context: ccx, - inference_context: infcx, - }.check(); + crate_context: ccx, + inference_context: infcx, + } + .check(); }); unsafety::check(ccx.tcx); orphan::check(ccx.tcx); diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 70342a0cd258e..bff794364c098 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -25,17 +25,20 @@ pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.visit_all_items_in_krate(DepNode::CoherenceOrphanCheck, &mut orphan); } -struct OrphanChecker<'cx, 'tcx:'cx> { - tcx: TyCtxt<'cx, 'tcx, 'tcx> +struct OrphanChecker<'cx, 'tcx: 'cx> { + tcx: TyCtxt<'cx, 'tcx, 'tcx>, } impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { fn check_def_id(&self, item: &hir::Item, def_id: DefId) { if def_id.krate != LOCAL_CRATE { - struct_span_err!(self.tcx.sess, item.span, E0116, - "cannot define inherent `impl` for a type outside of the \ - crate where the type is defined") - .span_label(item.span, &format!("impl for type defined outside of crate.")) + struct_span_err!(self.tcx.sess, + item.span, + E0116, + "cannot define inherent `impl` for a type outside of the crate \ + where the type is defined") + .span_label(item.span, + &format!("impl for type defined outside of crate.")) .note("define and implement a trait or new type instead") .emit(); } @@ -48,11 +51,17 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty: &str, span: Span) { match lang_def_id { - Some(lang_def_id) if lang_def_id == impl_def_id => { /* OK */ }, + Some(lang_def_id) if lang_def_id == impl_def_id => { + // OK + } _ => { - struct_span_err!(self.tcx.sess, span, E0390, - "only a single inherent implementation marked with `#[lang = \"{}\"]` \ - is allowed for the `{}` primitive", lang, ty) + struct_span_err!(self.tcx.sess, + span, + E0390, + "only a single inherent implementation marked with `#[lang = \ + \"{}\"]` is allowed for the `{}` primitive", + lang, + ty) .span_help(span, "consider using a trait to implement these methods") .emit(); } @@ -209,12 +218,14 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { return; } _ => { - struct_span_err!(self.tcx.sess, ty.span, E0118, + struct_span_err!(self.tcx.sess, + ty.span, + E0118, "no base type found for inherent implementation") - .span_label(ty.span, &format!("impl requires a base type")) - .note(&format!("either implement a trait on it or create a newtype \ - to wrap it instead")) - .emit(); + .span_label(ty.span, &format!("impl requires a base type")) + .note(&format!("either implement a trait on it or create a newtype \ + to wrap it instead")) + .emit(); return; } } @@ -226,20 +237,23 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; match traits::orphan_check(self.tcx, def_id) { - Ok(()) => { } + Ok(()) => {} Err(traits::OrphanCheckErr::NoLocalInputType) => { - struct_span_err!( - self.tcx.sess, item.span, E0117, - "only traits defined in the current crate can be \ - implemented for arbitrary types") - .span_label(item.span, &format!("impl doesn't use types inside crate")) - .note(&format!("the impl does not reference any \ - types defined in this crate")) - .emit(); + struct_span_err!(self.tcx.sess, + item.span, + E0117, + "only traits defined in the current crate can be \ + implemented for arbitrary types") + .span_label(item.span, &format!("impl doesn't use types inside crate")) + .note(&format!("the impl does not reference any types defined in \ + this crate")) + .emit(); return; } Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => { - span_err!(self.tcx.sess, item.span, E0210, + span_err!(self.tcx.sess, + item.span, + E0210, "type parameter `{}` must be used as the type parameter for \ some local type (e.g. `MyStruct`); only traits defined in \ the current crate can be implemented for a type parameter", @@ -285,10 +299,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { trait_ref, trait_def_id, self.tcx.trait_has_default_impl(trait_def_id)); - if - self.tcx.trait_has_default_impl(trait_def_id) && - trait_def_id.krate != LOCAL_CRATE - { + if self.tcx.trait_has_default_impl(trait_def_id) && + trait_def_id.krate != LOCAL_CRATE { let self_ty = trait_ref.self_ty(); let opt_self_def_id = match self_ty.sty { ty::TyAdt(self_def, _) => Some(self_def.did), @@ -305,20 +317,17 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { if self_def_id.is_local() { None } else { - Some(format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - self.tcx.item_path_str(trait_def_id))) + Some(format!("cross-crate traits with a default impl, like `{}`, \ + can only be implemented for a struct/enum type \ + defined in the current crate", + self.tcx.item_path_str(trait_def_id))) } } _ => { - Some(format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type, \ - not `{}`", - self.tcx.item_path_str(trait_def_id), - self_ty)) + Some(format!("cross-crate traits with a default impl, like `{}`, can \ + only be implemented for a struct/enum type, not `{}`", + self.tcx.item_path_str(trait_def_id), + self_ty)) } }; @@ -330,14 +339,18 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { // Disallow *all* explicit impls of `Sized` and `Unsize` for now. if Some(trait_def_id) == self.tcx.lang_items.sized_trait() { - struct_span_err!(self.tcx.sess, item.span, E0322, - "explicit impls for the `Sized` trait are not permitted") + struct_span_err!(self.tcx.sess, + item.span, + E0322, + "explicit impls for the `Sized` trait are not permitted") .span_label(item.span, &format!("impl of 'Sized' not allowed")) .emit(); return; } if Some(trait_def_id) == self.tcx.lang_items.unsize_trait() { - span_err!(self.tcx.sess, item.span, E0328, + span_err!(self.tcx.sess, + item.span, + E0328, "explicit impls for the `Unsize` trait are not permitted"); return; } @@ -348,9 +361,11 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { self.tcx.map.node_to_string(item.id)); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); if trait_ref.def_id.krate != LOCAL_CRATE { - struct_span_err!(self.tcx.sess, item_trait_ref.path.span, E0318, - "cannot create default implementations for traits outside the \ - crate they're defined in; define a new trait instead") + struct_span_err!(self.tcx.sess, + item_trait_ref.path.span, + E0318, + "cannot create default implementations for traits outside \ + the crate they're defined in; define a new trait instead") .span_label(item_trait_ref.path.span, &format!("`{}` trait not defined in this crate", item_trait_ref.path)) @@ -365,7 +380,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { } } -impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { +impl<'cx, 'tcx, 'v> intravisit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { self.check_item(item); } diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index c42b8f8840028..1bf140c21a5a5 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -23,15 +23,17 @@ use util::nodemap::DefIdMap; use lint; pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut overlap = OverlapChecker { tcx: tcx, - default_impls: DefIdMap() }; + let mut overlap = OverlapChecker { + tcx: tcx, + default_impls: DefIdMap(), + }; // this secondary walk specifically checks for some other cases, // like defaulted traits, for which additional overlap rules exist tcx.visit_all_items_in_krate(DepNode::CoherenceOverlapCheckSpecial, &mut overlap); } -struct OverlapChecker<'cx, 'tcx:'cx> { +struct OverlapChecker<'cx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'tcx, 'tcx>, // maps from a trait def-id to an impl id @@ -41,18 +43,21 @@ struct OverlapChecker<'cx, 'tcx:'cx> { impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) { #[derive(Copy, Clone, PartialEq)] - enum Namespace { Type, Value } + enum Namespace { + Type, + Value, + } fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> (ast::Name, Namespace) - { + -> (ast::Name, Namespace) { let item = tcx.impl_or_trait_item(def_id); - (item.name(), match item { - ty::TypeTraitItem(..) => Namespace::Type, - ty::ConstTraitItem(..) => Namespace::Value, - ty::MethodTraitItem(..) => Namespace::Value, - }) + (item.name(), + match item { + ty::TypeTraitItem(..) => Namespace::Type, + ty::ConstTraitItem(..) => Namespace::Value, + ty::MethodTraitItem(..) => Namespace::Value, + }) } let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow(); @@ -79,11 +84,11 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { let inherent_impls = self.tcx.inherent_impls.borrow(); let impls = match inherent_impls.get(&ty_def_id) { Some(impls) => impls, - None => return + None => return, }; for (i, &impl1_def_id) in impls.iter().enumerate() { - for &impl2_def_id in &impls[(i+1)..] { + for &impl2_def_id in &impls[(i + 1)..] { self.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) @@ -94,10 +99,12 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { } } -impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { +impl<'cx, 'tcx, 'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { - hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) => { + hir::ItemEnum(..) | + hir::ItemStruct(..) | + hir::ItemUnion(..) => { let type_def_id = self.tcx.map.local_def_id(item.id); self.check_for_overlapping_inherent_impls(type_def_id); } @@ -111,12 +118,14 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id); if let Some(prev_id) = prev_default_impl { - let mut err = struct_span_err!( - self.tcx.sess, - self.tcx.span_of_impl(impl_def_id).unwrap(), E0521, - "redundant default implementations of trait `{}`:", - trait_ref); - err.span_note(self.tcx.span_of_impl(self.tcx.map.local_def_id(prev_id)) + let mut err = struct_span_err!(self.tcx.sess, + self.tcx.span_of_impl(impl_def_id).unwrap(), + E0521, + "redundant default implementations of trait \ + `{}`:", + trait_ref); + err.span_note(self.tcx + .span_of_impl(self.tcx.map.local_def_id(prev_id)) .unwrap(), "redundant implementation is here:"); err.emit(); @@ -127,8 +136,8 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); let trait_def_id = trait_ref.def_id; - let _task = self.tcx.dep_graph.in_task( - DepNode::CoherenceOverlapCheck(trait_def_id)); + let _task = + self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapCheck(trait_def_id)); let def = self.tcx.lookup_trait_def(trait_def_id); @@ -137,17 +146,19 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { // insertion failed due to overlap if let Err(overlap) = insert_result { - let mut err = struct_span_err!( - self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0119, - "conflicting implementations of trait `{}`{}:", - overlap.trait_desc, - overlap.self_desc.clone().map_or(String::new(), - |ty| format!(" for type `{}`", ty))); + let mut err = struct_span_err!(self.tcx.sess, + self.tcx.span_of_impl(impl_def_id).unwrap(), + E0119, + "conflicting implementations of trait `{}`{}:", + overlap.trait_desc, + overlap.self_desc.clone().map_or(String::new(), + |ty| { + format!(" for type `{}`", ty) + })); match self.tcx.span_of_impl(overlap.with_impl) { Ok(span) => { - err.span_label(span, - &format!("first implementation here")); + err.span_label(span, &format!("first implementation here")); err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(), &format!("conflicting implementation{}", overlap.self_desc @@ -155,8 +166,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { |ty| format!(" for `{}`", ty)))); } Err(cname) => { - err.note(&format!("conflicting implementation in crate `{}`", - cname)); + err.note(&format!("conflicting implementation in crate `{}`", cname)); } } @@ -177,7 +187,9 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> { let mut supertrait_def_ids = traits::supertrait_def_ids(self.tcx, data.principal.def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { - span_err!(self.tcx.sess, item.span, E0371, + span_err!(self.tcx.sess, + item.span, + E0371, "the object type `{}` automatically \ implements the trait `{}`", trait_ref.self_ty(), diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index cdf5478e692b2..ff55ce0e5eb55 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -20,21 +20,26 @@ pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.map.krate().visit_all_items(&mut orphan); } -struct UnsafetyChecker<'cx, 'tcx:'cx> { - tcx: TyCtxt<'cx, 'tcx, 'tcx> +struct UnsafetyChecker<'cx, 'tcx: 'cx> { + tcx: TyCtxt<'cx, 'tcx, 'tcx>, } impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { - fn check_unsafety_coherence(&mut self, item: &'v hir::Item, + fn check_unsafety_coherence(&mut self, + item: &'v hir::Item, unsafety: hir::Unsafety, polarity: hir::ImplPolarity) { match self.tcx.impl_trait_ref(self.tcx.map.local_def_id(item.id)) { None => { // Inherent impl. match unsafety { - hir::Unsafety::Normal => { /* OK */ } + hir::Unsafety::Normal => { + // OK + } hir::Unsafety::Unsafe => { - span_err!(self.tcx.sess, item.span, E0197, + span_err!(self.tcx.sess, + item.span, + E0197, "inherent impls cannot be declared as unsafe"); } } @@ -43,31 +48,33 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { Some(trait_ref) => { let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id); match (trait_def.unsafety, unsafety, polarity) { - (hir::Unsafety::Unsafe, - hir::Unsafety::Unsafe, hir::ImplPolarity::Negative) => { - span_err!(self.tcx.sess, item.span, E0198, + (hir::Unsafety::Unsafe, hir::Unsafety::Unsafe, hir::ImplPolarity::Negative) => { + span_err!(self.tcx.sess, + item.span, + E0198, "negative implementations are not unsafe"); } (hir::Unsafety::Normal, hir::Unsafety::Unsafe, _) => { - span_err!(self.tcx.sess, item.span, E0199, + span_err!(self.tcx.sess, + item.span, + E0199, "implementing the trait `{}` is not unsafe", trait_ref); } - (hir::Unsafety::Unsafe, - hir::Unsafety::Normal, hir::ImplPolarity::Positive) => { - span_err!(self.tcx.sess, item.span, E0200, + (hir::Unsafety::Unsafe, hir::Unsafety::Normal, hir::ImplPolarity::Positive) => { + span_err!(self.tcx.sess, + item.span, + E0200, "the trait `{}` requires an `unsafe impl` declaration", trait_ref); } - (hir::Unsafety::Unsafe, - hir::Unsafety::Normal, hir::ImplPolarity::Negative) | - (hir::Unsafety::Unsafe, - hir::Unsafety::Unsafe, hir::ImplPolarity::Positive) | + (hir::Unsafety::Unsafe, hir::Unsafety::Normal, hir::ImplPolarity::Negative) | + (hir::Unsafety::Unsafe, hir::Unsafety::Unsafe, hir::ImplPolarity::Positive) | (hir::Unsafety::Normal, hir::Unsafety::Normal, _) => { - /* OK */ + // OK } } } @@ -75,7 +82,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { } } -impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { +impl<'cx, 'tcx, 'v> intravisit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v hir::Item) { match item.node { hir::ItemDefaultImpl(unsafety, _) => { @@ -84,7 +91,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { hir::ItemImpl(unsafety, polarity, ..) => { self.check_unsafety_coherence(item, unsafety, polarity); } - _ => { } + _ => {} } } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 8f02c9c7d3de0..afd833d8bdd81 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -59,7 +59,6 @@ const EMPTY_BUCKET: u64 = 0; /// around just the "table" part of the hashtable. It enforces some /// invariants at the type level and employs some performance trickery, /// but in general is just a tricked out `Vec>`. -#[cfg_attr(stage0, unsafe_no_drop_flag)] pub struct RawTable { capacity: usize, size: usize, diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index d6a5efbd279a5..6f5ce350e6cb3 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -314,9 +314,11 @@ impl CString { } // Turns this `CString` into an empty string to prevent -// memory unsafe code from working by accident. +// memory unsafe code from working by accident. Inline +// to prevent LLVM from optimizing it away in debug builds. #[stable(feature = "cstring_drop", since = "1.13.0")] impl Drop for CString { + #[inline] fn drop(&mut self) { unsafe { *self.inner.get_unchecked_mut(0) = 0; } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 912045453e086..b3e4351e9b200 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -278,7 +278,6 @@ #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] -#![cfg_attr(stage0, feature(unsafe_no_drop_flag))] #![feature(unwind_attributes)] #![feature(vec_push_all)] #![feature(zero_one)] diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 5082f64ccbb41..4f64b3f2e1d67 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -557,7 +557,9 @@ pub struct ExpansionData { pub depth: usize, pub backtrace: ExpnId, pub module: Rc, - pub in_block: bool, + + // True if non-inline modules without a `#[path]` are forbidden at the root of this expansion. + pub no_noninline_mod: bool, } /// One of these is made during expansion and incrementally updated as we go; @@ -590,7 +592,7 @@ impl<'a> ExtCtxt<'a> { depth: 0, backtrace: NO_EXPANSION, module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), - in_block: false, + no_noninline_mod: false, }, } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 36a33dcc5c570..b1d828d0e3e49 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -667,9 +667,9 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } fn fold_block(&mut self, block: P) -> P { - let orig_in_block = mem::replace(&mut self.cx.current_expansion.in_block, true); + let no_noninline_mod = mem::replace(&mut self.cx.current_expansion.no_noninline_mod, true); let result = noop_fold_block(block, self); - self.cx.current_expansion.in_block = orig_in_block; + self.cx.current_expansion.no_noninline_mod = no_noninline_mod; result } @@ -708,6 +708,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { return noop_fold_item(item, self); } + let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); @@ -717,11 +718,14 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let inline_module = item.span.contains(inner) || inner == syntax_pos::DUMMY_SP; if inline_module { - module.directory.push(&*{ - ::attr::first_attr_value_str_by_name(&item.attrs, "path") - .unwrap_or(item.ident.name.as_str()) - }); + if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { + self.cx.current_expansion.no_noninline_mod = false; + module.directory.push(&*path); + } else { + module.directory.push(&*item.ident.name.as_str()); + } } else { + self.cx.current_expansion.no_noninline_mod = false; module.directory = PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner)); module.directory.pop(); @@ -731,6 +735,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); let result = noop_fold_item(item, self); self.cx.current_expansion.module = orig_module; + self.cx.current_expansion.no_noninline_mod = orig_no_noninline_mod; return result; } // Ensure that test functions are accessible from the test harness. diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9f4c0b5eb808f..2e0c7ddb540f4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -122,7 +122,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, rhs); let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr)); p.directory = cx.current_expansion.module.directory.clone(); - p.restrictions = match cx.current_expansion.in_block { + p.restrictions = match cx.current_expansion.no_noninline_mod { true => Restrictions::NO_NONINLINE_MOD, false => Restrictions::empty(), }; diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index a40c30b3e3397..a1c273baeea42 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -38,14 +38,24 @@ pub struct JsonEmitter { } impl JsonEmitter { + pub fn stderr(registry: Option, + code_map: Rc) -> JsonEmitter { + JsonEmitter { + dst: Box::new(io::stderr()), + registry: registry, + cm: code_map, + } + } + pub fn basic() -> JsonEmitter { JsonEmitter::stderr(None, Rc::new(CodeMap::new())) } - pub fn stderr(registry: Option, - code_map: Rc) -> JsonEmitter { + pub fn new(dst: Box, + registry: Option, + code_map: Rc) -> JsonEmitter { JsonEmitter { - dst: Box::new(io::stderr()), + dst: dst, registry: registry, cm: code_map, } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d5ed1d157e47a..5476166932d32 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5274,23 +5274,27 @@ impl<'a> Parser<'a> { } } else { let directory = self.directory.clone(); - self.push_directory(id, &outer_attrs); + let restrictions = self.push_directory(id, &outer_attrs); self.expect(&token::OpenDelim(token::Brace))?; let mod_inner_lo = self.span.lo; let attrs = self.parse_inner_attributes()?; - let m = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; + let m = self.with_res(restrictions, |this| { + this.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo) + })?; self.directory = directory; Ok((id, ItemKind::Mod(m), Some(attrs))) } } - fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { - let default_path = self.id_to_interned_str(id); - let file_path = match ::attr::first_attr_value_str_by_name(attrs, "path") { - Some(d) => d, - None => default_path, - }; - self.directory.push(&*file_path) + fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) -> Restrictions { + if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") { + self.directory.push(&*path); + self.restrictions - Restrictions::NO_NONINLINE_MOD + } else { + let default_path = self.id_to_interned_str(id); + self.directory.push(&*default_path); + self.restrictions + } } pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option { diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index e4510520a55a4..6ccf9848c6df9 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -19,7 +19,7 @@ use std::iter; use std::slice; use std::mem; use std::vec; -use attr; +use attr::{self, HasAttrs}; use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos}; use std::rc::Rc; @@ -226,12 +226,20 @@ fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec) -> (P, ast::Ident) { let super_ = token::str_to_ident("super"); + // Generate imports with `#[allow(private_in_public)]` to work around issue #36768. + let allow_private_in_public = cx.ext_cx.attribute(DUMMY_SP, cx.ext_cx.meta_list( + DUMMY_SP, + InternedString::new("allow"), + vec![cx.ext_cx.meta_list_item_word(DUMMY_SP, InternedString::new("private_in_public"))], + )); let items = tests.into_iter().map(|r| { cx.ext_cx.item_use_simple(DUMMY_SP, ast::Visibility::Public, cx.ext_cx.path(DUMMY_SP, vec![super_, r])) + .map_attrs(|_| vec![allow_private_in_public.clone()]) }).chain(tested_submods.into_iter().map(|(r, sym)| { let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]); cx.ext_cx.item_use_simple_(DUMMY_SP, ast::Visibility::Public, r, path) + .map_attrs(|_| vec![allow_private_in_public.clone()]) })).collect(); let reexport_mod = ast::Mod { diff --git a/src/stage0.txt b/src/stage0.txt index f9cf819dc9487..05189f2011b0d 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,6 +12,6 @@ # tarball for a stable release you'll likely see `1.x.0-$date` where `1.x.0` was # released on `$date` -rustc: beta-2016-08-17 -rustc_key: 195e6261 -cargo: nightly-2016-08-21 +rustc: beta-2016-09-28 +rustc_key: 62b3e239 +cargo: nightly-2016-09-26 diff --git a/src/test/incremental/change_crate_order/auxiliary/a.rs b/src/test/incremental/change_crate_order/auxiliary/a.rs new file mode 100644 index 0000000000000..69b4acd3e3023 --- /dev/null +++ b/src/test/incremental/change_crate_order/auxiliary/a.rs @@ -0,0 +1,14 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="rlib"] + +pub static A : u32 = 32; + diff --git a/src/test/incremental/change_crate_order/auxiliary/b.rs b/src/test/incremental/change_crate_order/auxiliary/b.rs new file mode 100644 index 0000000000000..1ab97a312c1f1 --- /dev/null +++ b/src/test/incremental/change_crate_order/auxiliary/b.rs @@ -0,0 +1,14 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type="rlib"] + +pub static B: u32 = 32; + diff --git a/src/test/incremental/change_crate_order/main.rs b/src/test/incremental/change_crate_order/main.rs new file mode 100644 index 0000000000000..bd8742ff38e01 --- /dev/null +++ b/src/test/incremental/change_crate_order/main.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:a.rs +// aux-build:b.rs +// revisions:rpass1 rpass2 + +#![feature(rustc_attrs)] + + +#[cfg(rpass1)] +extern crate a; +#[cfg(rpass1)] +extern crate b; + +#[cfg(rpass2)] +extern crate b; +#[cfg(rpass2)] +extern crate a; + +use a::A; +use b::B; + +//? #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] +pub fn main() { + A + B; +} diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs index 19e410fef5388..05c1713561a3e 100644 --- a/src/test/run-make/llvm-phase/test.rs +++ b/src/test/run-make/llvm-phase/test.rs @@ -79,8 +79,8 @@ fn main() { format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap()) .split(' ').map(|s| s.to_string()).collect(); - let (result, _) = rustc_driver::run_compiler_with_file_loader( - &args, &mut JitCalls, box JitLoader); + let (result, _) = rustc_driver::run_compiler( + &args, &mut JitCalls, Some(box JitLoader), None); if let Err(n) = result { panic!("Error {}", n); } diff --git a/src/test/run-pass-fulldeps/compiler-calls.rs b/src/test/run-pass-fulldeps/compiler-calls.rs index 775ba38004e3a..35e9f3f5c8d64 100644 --- a/src/test/run-pass-fulldeps/compiler-calls.rs +++ b/src/test/run-pass-fulldeps/compiler-calls.rs @@ -86,6 +86,6 @@ fn main() { let mut tc = TestCalls { count: 1 }; // we should never get use this filename, but lets make sure they are valid args. let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; - rustc_driver::run_compiler(&args, &mut tc); + rustc_driver::run_compiler(&args, &mut tc, None, None); assert_eq!(tc.count, 30); } diff --git a/src/test/run-pass/cstring-drop.rs b/src/test/run-pass/cstring-drop.rs deleted file mode 100644 index 960391bb8deac..0000000000000 --- a/src/test/run-pass/cstring-drop.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-emscripten - -// Test that `CString::new("hello").unwrap().as_ptr()` pattern -// leads to failure. - -use std::env; -use std::ffi::{CString, CStr}; -use std::os::raw::c_char; -use std::process::{Command, Stdio}; - -fn main() { - let args: Vec = env::args().collect(); - if args.len() > 1 && args[1] == "child" { - // Repeat several times to be more confident that - // it is `Drop` for `CString` that does the cleanup, - // and not just some lucky UB. - let xs = vec![CString::new("Hello").unwrap(); 10]; - let ys = xs.iter().map(|s| s.as_ptr()).collect::>(); - drop(xs); - assert!(ys.into_iter().any(is_hello)); - return; - } - - let output = Command::new(&args[0]).arg("child").output().unwrap(); - assert!(!output.status.success()); -} - -fn is_hello(s: *const c_char) -> bool { - // `s` is a dangling pointer and reading it is technically - // undefined behavior. But we want to prevent the most diabolical - // kind of UB (apart from nasal demons): reading a value that was - // previously written. - // - // Segfaulting or reading an empty string is Ok, - // reading "Hello" is bad. - let s = unsafe { CStr::from_ptr(s) }; - let hello = CString::new("Hello").unwrap(); - s == hello.as_ref() -} diff --git a/src/test/run-pass/issue-36768.rs b/src/test/run-pass/issue-36768.rs new file mode 100644 index 0000000000000..bb4d12919a1c2 --- /dev/null +++ b/src/test/run-pass/issue-36768.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--test +#![deny(private_in_public)] + +#[test] fn foo() {} +mod foo {} + +#[test] fn core() {} +extern crate core; diff --git a/src/test/run-pass/mod_dir_path.rs b/src/test/run-pass/mod_dir_path.rs index e0327a1dcd4ed..28dee15cfa043 100644 --- a/src/test/run-pass/mod_dir_path.rs +++ b/src/test/run-pass/mod_dir_path.rs @@ -17,4 +17,15 @@ mod mod_dir_simple { pub fn main() { assert_eq!(mod_dir_simple::syrup::foo(), 10); + + #[path = "auxiliary"] + mod foo { + mod two_macros; + } + + #[path = "auxiliary"] + mod bar { + macro_rules! m { () => { mod two_macros; } } + m!(); + } }