diff --git a/Cargo.lock b/Cargo.lock index 16f2ffc28150f..7c074fb18a6f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3120,7 +3120,6 @@ dependencies = [ "graphviz", "jobserver", "log", - "measureme", "num_cpus", "parking_lot 0.9.0", "polonius-engine", @@ -3470,6 +3469,7 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ + "bitflags", "cfg-if", "crossbeam-utils 0.6.5", "ena", @@ -3478,6 +3478,7 @@ dependencies = [ "jobserver", "lazy_static 1.3.0", "log", + "measureme", "parking_lot 0.9.0", "rustc-hash", "rustc-rayon 0.3.0", diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index a13ff69a7b56f..6937fb922de48 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -25,7 +25,7 @@ fn main() { let mut dylib_path = bootstrap::util::dylib_path(); dylib_path.insert(0, PathBuf::from(libdir.clone())); - //FIXME(misdreavus): once stdsimd uses cfg(rustdoc) instead of cfg(dox), remove the `--cfg dox` + //FIXME(misdreavus): once stdsimd uses cfg(doc) instead of cfg(dox), remove the `--cfg dox` //arguments here let mut cmd = Command::new(rustdoc); cmd.args(&args) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4caf36a6f2a51..730e8cf05d41d 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -102,10 +102,10 @@ def verify(path, sha_path, verbose): return verified -def unpack(tarball, dst, verbose=False, match=None): +def unpack(tarball, tarball_suffix, dst, verbose=False, match=None): """Unpack the given tarball file""" print("extracting", tarball) - fname = os.path.basename(tarball).replace(".tar.gz", "") + fname = os.path.basename(tarball).replace(tarball_suffix, "") with contextlib.closing(tarfile.open(tarball)) as tar: for member in tar.getnames(): if "/" not in member: @@ -331,6 +331,7 @@ def __init__(self): self.use_vendored_sources = '' self.verbose = False + def download_stage0(self): """Fetch the build system for Rust, written in Rust @@ -344,18 +345,30 @@ def download_stage0(self): rustc_channel = self.rustc_channel cargo_channel = self.cargo_channel + def support_xz(): + try: + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + temp_path = temp_file.name + with tarfile.open(temp_path, "w:xz") as tar: + pass + return True + except tarfile.CompressionError: + return False + if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.program_out_of_date(self.rustc_stamp())): if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) - filename = "rust-std-{}-{}.tar.gz".format( - rustc_channel, self.build) + tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' + filename = "rust-std-{}-{}{}".format( + rustc_channel, self.build, tarball_suffix) pattern = "rust-std-{}".format(self.build) - self._download_stage0_helper(filename, pattern) + self._download_stage0_helper(filename, pattern, tarball_suffix) - filename = "rustc-{}-{}.tar.gz".format(rustc_channel, self.build) - self._download_stage0_helper(filename, "rustc") + filename = "rustc-{}-{}{}".format(rustc_channel, self.build, + tarball_suffix) + self._download_stage0_helper(filename, "rustc", tarball_suffix) self.fix_executable("{}/bin/rustc".format(self.bin_root())) self.fix_executable("{}/bin/rustdoc".format(self.bin_root())) with output(self.rustc_stamp()) as rust_stamp: @@ -365,20 +378,22 @@ def download_stage0(self): # libraries/binaries that are included in rust-std with # the system MinGW ones. if "pc-windows-gnu" in self.build: - filename = "rust-mingw-{}-{}.tar.gz".format( - rustc_channel, self.build) - self._download_stage0_helper(filename, "rust-mingw") + filename = "rust-mingw-{}-{}{}".format( + rustc_channel, self.build, tarball_suffix) + self._download_stage0_helper(filename, "rust-mingw", tarball_suffix) if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.program_out_of_date(self.cargo_stamp())): - filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build) - self._download_stage0_helper(filename, "cargo") + tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' + filename = "cargo-{}-{}{}".format(cargo_channel, self.build, + tarball_suffix) + self._download_stage0_helper(filename, "cargo", tarball_suffix) self.fix_executable("{}/bin/cargo".format(self.bin_root())) with output(self.cargo_stamp()) as cargo_stamp: cargo_stamp.write(self.date) - def _download_stage0_helper(self, filename, pattern): + def _download_stage0_helper(self, filename, pattern, tarball_suffix): cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, self.date) if not os.path.exists(rustc_cache): @@ -388,7 +403,7 @@ def _download_stage0_helper(self, filename, pattern): tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) - unpack(tarball, self.bin_root(), match=pattern, verbose=self.verbose) + unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose) @staticmethod def fix_executable(fname): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2edcef203ad26..99b8ddf7db1f0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1242,7 +1242,8 @@ impl<'a> Builder<'a> { cargo.arg("--frozen"); } - cargo.env("RUSTC_INSTALL_BINDIR", &self.config.bindir); + // Try to use a sysroot-relative bindir, in case it was configured absolutely. + cargo.env("RUSTC_INSTALL_BINDIR", self.config.bindir_relative()); self.ci_env.force_coloring_in_ci(&mut cargo); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d1bdfa0a76763..0c03b95c7b251 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -647,6 +647,20 @@ impl Config { config } + /// Try to find the relative path of `bindir`, otherwise return it in full. + pub fn bindir_relative(&self) -> &Path { + let bindir = &self.bindir; + if bindir.is_absolute() { + // Try to make it relative to the prefix. + if let Some(prefix) = &self.prefix { + if let Ok(stripped) = bindir.strip_prefix(prefix) { + return stripped; + } + } + } + bindir + } + /// Try to find the relative path of `libdir`. pub fn libdir_relative(&self) -> Option<&Path> { let libdir = self.libdir.as_ref()?; diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 3c3e72aa37959..f8be04a1087bf 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -106,11 +106,11 @@ item, it will be accompanied by a banner explaining that the item is only availa platforms. For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently -running on. To aid this, Rustdoc sets the flag `#[cfg(rustdoc)]` when running on your crate. +running on. To aid this, Rustdoc sets the flag `#[cfg(doc)]` when running on your crate. Combining this with the target platform of a given item allows it to appear when building your crate normally on that platform, as well as when building documentation anywhere. -For example, `#[cfg(any(windows, rustdoc))]` will preserve the item either on Windows or during the +For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that the item is supposed to be used on Windows. For example: @@ -118,12 +118,12 @@ the item is supposed to be used on Windows. For example: #![feature(doc_cfg)] /// Token struct that can only be used on Windows. -#[cfg(any(windows, rustdoc))] +#[cfg(any(windows, doc))] #[doc(cfg(windows))] pub struct WindowsToken; /// Token struct that can only be used on Unix. -#[cfg(any(unix, rustdoc))] +#[cfg(any(unix, doc))] #[doc(cfg(unix))] pub struct UnixToken; ``` diff --git a/src/doc/unstable-book/src/language-features/doc-cfg.md b/src/doc/unstable-book/src/language-features/doc-cfg.md index 96c66a1515ed5..e75f1aea99229 100644 --- a/src/doc/unstable-book/src/language-features/doc-cfg.md +++ b/src/doc/unstable-book/src/language-features/doc-cfg.md @@ -13,7 +13,7 @@ This attribute has two effects: 2. The item's doc-tests will only run on the specific platform. In addition to allowing the use of the `#[doc(cfg)]` attribute, this feature enables the use of a -special conditional compilation flag, `#[cfg(rustdoc)]`, set whenever building documentation on your +special conditional compilation flag, `#[cfg(doc)]`, set whenever building documentation on your crate. This feature was introduced as part of PR [#43348] to allow the platform-specific parts of the @@ -22,7 +22,7 @@ standard library be documented. ```rust #![feature(doc_cfg)] -#[cfg(any(windows, rustdoc))] +#[cfg(any(windows, doc))] #[doc(cfg(windows))] /// The application's icon in the notification area (a.k.a. system tray). /// diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 7ffc8b3729cb4..b7a35568e3fc5 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -201,12 +201,13 @@ pub trait Iterator { /// Consumes the iterator, counting the number of iterations and returning it. /// - /// This method will evaluate the iterator until its [`next`] returns - /// [`None`]. Once [`None`] is encountered, `count()` returns the number of - /// times it called [`next`]. + /// This method will call [`next`] repeatedly until [`None`] is encountered, + /// returning the number of times it saw [`Some`]. Note that [`next`] has to be + /// called at least once even if the iterator does not have any elements. /// /// [`next`]: #tymethod.next /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`Some`]: ../../std/option/enum.Option.html#variant.Some /// /// # Overflow Behavior /// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index ed40a5f31d9bd..06c7041703ae5 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -514,6 +514,28 @@ impl Result { } } + /// Applies a function to the contained value (if any), + /// or returns the provided default (if not). + /// + /// # Examples + /// + /// ``` + /// #![feature(result_map_or)] + /// let x: Result<_, &str> = Ok("foo"); + /// assert_eq!(x.map_or(42, |v| v.len()), 3); + /// + /// let x: Result<&str, _> = Err("bar"); + /// assert_eq!(x.map_or(42, |v| v.len()), 42); + /// ``` + #[inline] + #[unstable(feature = "result_map_or", issue = "66293")] + pub fn map_or U>(self, default: U, f: F) -> U { + match self { + Ok(t) => f(t), + Err(_) => default, + } + } + /// Maps a `Result` to `U` by applying a function to a /// contained [`Ok`] value, or a fallback function to a /// contained [`Err`] value. diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 92b94af75d750..bcbe765b85073 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -40,4 +40,3 @@ byteorder = { version = "1.3" } chalk-engine = { version = "0.9.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } -measureme = "0.4" diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0ea33d725f1e7..7dbacfd133f3f 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -124,7 +124,6 @@ pub mod util { pub mod captures; pub mod common; pub mod nodemap; - pub mod profiling; pub mod bug; } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 721baad25639f..dc3bc5fa0cebf 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -35,7 +35,6 @@ use crate::util::common::time; use errors::DiagnosticBuilder; use std::slice; use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; @@ -71,7 +70,7 @@ pub struct LintStore { /// Lints that are buffered up early on in the `Session` before the /// `LintLevels` is calculated -#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)] +#[derive(PartialEq, Debug)] pub struct BufferedEarlyLint { pub lint_id: LintId, pub ast_id: ast::NodeId, @@ -1574,27 +1573,3 @@ pub fn check_ast_crate( } } } - -impl Encodable for LintId { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.lint.name.to_lowercase()) - } -} - -impl Decodable for LintId { - #[inline] - fn decode(d: &mut D) -> Result { - let s = d.read_str()?; - ty::tls::with(|tcx| { - match tcx.lint_store.find_lints(&s) { - Ok(ids) => { - if ids.len() != 0 { - panic!("invalid lint-id `{}`", s); - } - Ok(ids[0]) - } - Err(_) => panic!("invalid lint-id `{}`", s), - } - }) - } -} diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 1f4086227327e..e5c80c3589494 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -15,6 +15,7 @@ use std::path::{Path, PathBuf}; use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; +use syntax::expand::allocator::AllocatorKind; use rustc_target::spec::Target; use rustc_data_structures::sync::{self, MetadataRef}; use rustc_macros::HashStable; @@ -227,6 +228,8 @@ pub trait CrateStore { // utility functions fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; fn metadata_encoding_version(&self) -> &[u8]; + fn injected_panic_runtime(&self) -> Option; + fn allocator_kind(&self) -> Option; } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 9792223ea1506..a69584cb90ad1 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -2,7 +2,6 @@ pub use self::code_stats::{DataTypeKind, SizeKind, FieldInfo, VariantInfo}; use self::code_stats::CodeStats; use crate::dep_graph::cgu_reuse_tracker::CguReuseTracker; -use crate::hir::def_id::CrateNum; use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; @@ -22,18 +21,17 @@ use errors::emitter::{Emitter, EmitterWriter}; use errors::emitter::HumanReadableErrorType; use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; use syntax::edition::Edition; -use syntax::expand::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; use syntax::sess::{ParseSess, ProcessCfgMod}; use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; -use crate::util::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; use rustc_data_structures::flock; use rustc_data_structures::jobserver; +use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use ::jobserver::Client; use std; @@ -102,12 +100,6 @@ pub struct Session { /// The maximum number of stackframes allowed in const eval. pub const_eval_stack_frame_limit: usize, - /// The `metadata::creader` module may inject an allocator/`panic_runtime` - /// dependency if it didn't already find one, and this tracks what was - /// injected. - pub allocator_kind: Once>, - pub injected_panic_runtime: Once>, - /// Map from imported macro spans (which consist of /// the localized span for the macro body) to the /// macro name and definition span in the source crate. @@ -1099,7 +1091,6 @@ fn build_session_( ); match profiler { Ok(profiler) => { - crate::ty::query::QueryName::register_with_profiler(&profiler); Some(Arc::new(profiler)) }, Err(e) => { @@ -1182,8 +1173,6 @@ fn build_session_( recursion_limit: Once::new(), type_length_limit: Once::new(), const_eval_stack_frame_limit: 100, - allocator_kind: Once::new(), - injected_panic_runtime: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 04e0f6f4b56d7..a15acb00c17fb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -46,11 +46,11 @@ use crate::ty::CanonicalPolyFnSig; use crate::util::common::ErrorReported; use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap}; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use crate::util::profiling::SelfProfilerRef; use errors::DiagnosticBuilder; use arena::SyncDroplessArena; use smallvec::SmallVec; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{ HashStable, StableHasher, StableVec, hash_stable_hashmap, }; @@ -75,6 +75,7 @@ use syntax::source_map::MultiSpan; use syntax::feature_gate; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::Span; +use syntax::expand::allocator::AllocatorKind; pub struct AllArenas { pub interner: SyncDroplessArena, @@ -1338,6 +1339,14 @@ impl<'tcx> TyCtxt<'tcx> { self.all_crate_nums(LOCAL_CRATE) } + pub fn injected_panic_runtime(self) -> Option { + self.cstore.injected_panic_runtime() + } + + pub fn allocator_kind(self) -> Option { + self.cstore.allocator_kind() + } + pub fn features(self) -> &'tcx feature_gate::Features { self.features_query(LOCAL_CRATE) } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c1c6a655d96a9..7e126459dcc73 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -6,7 +6,7 @@ use crate::ty::query::queries; use crate::ty::query::{Query, QueryName}; use crate::ty::query::QueryCache; use crate::ty::query::plumbing::CycleError; -use crate::util::profiling::ProfileCategory; +use rustc_data_structures::profiling::ProfileCategory; use std::borrow::Cow; use std::hash::Hash; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 0615004125b3c..a1eb1c43335b1 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -39,7 +39,7 @@ use crate::ty::util::NeedsDrop; use crate::ty::subst::SubstsRef; use crate::util::nodemap::{DefIdSet, DefIdMap}; use crate::util::common::ErrorReported; -use crate::util::profiling::ProfileCategory::*; +use rustc_data_structures::profiling::ProfileCategory::*; use rustc_data_structures::svh::Svh; use rustc_index::vec::IndexVec; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 538154b035ac6..1c15b7d5f3559 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -672,7 +672,7 @@ macro_rules! define_queries_inner { rustc_data_structures::stable_hasher::StableHasher, ich::StableHashingContext }; - use crate::util::profiling::ProfileCategory; + use rustc_data_structures::profiling::ProfileCategory; define_queries_struct! { tcx: $tcx, @@ -816,8 +816,20 @@ macro_rules! define_queries_inner { $($name),* } + impl rustc_data_structures::profiling::QueryName for QueryName { + fn discriminant(self) -> std::mem::Discriminant { + std::mem::discriminant(&self) + } + + fn as_str(self) -> &'static str { + QueryName::as_str(&self) + } + } + impl QueryName { - pub fn register_with_profiler(profiler: &crate::util::profiling::SelfProfiler) { + pub fn register_with_profiler( + profiler: &rustc_data_structures::profiling::SelfProfiler, + ) { $(profiler.register_query_name(QueryName::$name);)* } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 35b62603b076a..f8b3e0ffe5cd9 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -194,7 +194,7 @@ fn exported_symbols_provider_local( symbols.push((exported_symbol, SymbolExportLevel::C)); } - if tcx.sess.allocator_kind.get().is_some() { + if tcx.allocator_kind().is_some() { for method in ALLOCATOR_METHODS { let symbol_name = format!("__rust_{}", method.name); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index b302b9ae7f0e4..ed901fa064a4e 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -19,7 +19,7 @@ use rustc::util::nodemap::FxHashMap; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::ty::TyCtxt; use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry}; -use rustc::util::profiling::SelfProfilerRef; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index c3f2a5161ae1c..faa7b588e56e3 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -549,7 +549,7 @@ pub fn codegen_crate( }); let allocator_module = if any_dynamic_crate { None - } else if let Some(kind) = *tcx.sess.allocator_kind.get() { + } else if let Some(kind) = tcx.allocator_kind() { let llmod_id = cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string(); diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index e79b3a81b9654..0fd47115022c2 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -25,6 +25,8 @@ rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } rustc-hash = "1.0.1" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_index = { path = "../librustc_index", package = "rustc_index" } +bitflags = "1.2.1" +measureme = "0.4" [dependencies.parking_lot] version = "0.9" diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 474a42644d915..fb541637e5f79 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -94,6 +94,7 @@ pub use ena::unify; pub mod vec_linked_list; pub mod work_queue; pub mod fingerprint; +pub mod profiling; pub struct OnDrop(pub F); diff --git a/src/librustc/util/profiling.rs b/src/librustc_data_structures/profiling.rs similarity index 92% rename from src/librustc/util/profiling.rs rename to src/librustc_data_structures/profiling.rs index 5a1b7f3aa4cb8..86f59bfabe627 100644 --- a/src/librustc/util/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -7,8 +7,6 @@ use std::sync::Arc; use std::thread::ThreadId; use std::u32; -use crate::ty::query::QueryName; - use measureme::{StringId, TimestampKind}; /// MmapSerializatioSink is faster on macOS and Linux @@ -20,6 +18,10 @@ type SerializationSink = measureme::FileSerializationSink; type Profiler = measureme::Profiler; +pub trait QueryName: Sized + Copy { + fn discriminant(self) -> Discriminant; + fn as_str(self) -> &'static str; +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)] pub enum ProfileCategory { @@ -32,7 +34,7 @@ pub enum ProfileCategory { Other, } -bitflags! { +bitflags::bitflags! { struct EventFilter: u32 { const GENERIC_ACTIVITIES = 1 << 0; const QUERY_PROVIDERS = 1 << 1; @@ -137,7 +139,7 @@ impl SelfProfilerRef { /// Start profiling a query provider. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] - pub fn query_provider(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn query_provider(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::QUERY_PROVIDERS, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start(profiler, profiler.query_event_kind, event_id) @@ -146,7 +148,7 @@ impl SelfProfilerRef { /// Record a query in-memory cache hit. #[inline(always)] - pub fn query_cache_hit(&self, query_name: QueryName) { + pub fn query_cache_hit(&self, query_name: impl QueryName) { self.non_guard_query_event( |profiler| profiler.query_cache_hit_event_kind, query_name, @@ -159,7 +161,7 @@ impl SelfProfilerRef { /// Profiling continues until the TimingGuard returned from this call is /// dropped. #[inline(always)] - pub fn query_blocked(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn query_blocked(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::QUERY_BLOCKED, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start(profiler, profiler.query_blocked_event_kind, event_id) @@ -170,7 +172,7 @@ impl SelfProfilerRef { /// incremental compilation on-disk cache. Profiling continues until the /// TimingGuard returned from this call is dropped. #[inline(always)] - pub fn incr_cache_loading(&self, query_name: QueryName) -> TimingGuard<'_> { + pub fn incr_cache_loading(&self, query_name: impl QueryName) -> TimingGuard<'_> { self.exec(EventFilter::INCR_CACHE_LOADS, |profiler| { let event_id = SelfProfiler::get_query_name_string_id(query_name); TimingGuard::start( @@ -185,7 +187,7 @@ impl SelfProfilerRef { fn non_guard_query_event( &self, event_kind: fn(&SelfProfiler) -> StringId, - query_name: QueryName, + query_name: impl QueryName, event_filter: EventFilter, timestamp_kind: TimestampKind ) { @@ -203,6 +205,12 @@ impl SelfProfilerRef { TimingGuard::none() })); } + + pub fn register_queries(&self, f: impl FnOnce(&SelfProfiler)) { + if let Some(profiler) = &self.profiler { + f(&profiler) + } + } } pub struct SelfProfiler { @@ -274,15 +282,15 @@ impl SelfProfiler { }) } - fn get_query_name_string_id(query_name: QueryName) -> StringId { + fn get_query_name_string_id(query_name: impl QueryName) -> StringId { let discriminant = unsafe { - mem::transmute::, u64>(mem::discriminant(&query_name)) + mem::transmute::, u64>(query_name.discriminant()) }; StringId::reserved(discriminant as u32) } - pub fn register_query_name(&self, query_name: QueryName) { + pub fn register_query_name(&self, query_name: impl QueryName) { let id = SelfProfiler::get_query_name_string_id(query_name); self.profiler.alloc_string_with_reserved_id(id, query_name.as_str()); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 10bc6599e7592..514c6d0e1dad9 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -181,6 +181,7 @@ pub fn run_compiler( crate_name: None, lint_caps: Default::default(), register_lints: None, + override_queries: None, }; callbacks.config(&mut config); config @@ -259,6 +260,7 @@ pub fn run_compiler( crate_name: None, lint_caps: Default::default(), register_lints: None, + override_queries: None, }; callbacks.config(&mut config); diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 02068b2ce388d..fae4eb48c4a1b 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -12,6 +12,7 @@ use rustc_data_structures::OnDrop; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_parse::new_parser_from_source_str; +use rustc::ty; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -38,6 +39,8 @@ pub struct Compiler { pub(crate) queries: Queries, pub(crate) crate_name: Option, pub(crate) register_lints: Option>, + pub(crate) override_queries: + Option, &mut ty::query::Providers<'_>)>, } impl Compiler { @@ -131,6 +134,13 @@ pub struct Config { /// Note that if you find a Some here you probably want to call that function in the new /// function being registered. pub register_lints: Option>, + + /// This is a callback from the driver that is called just after we have populated + /// the list of queries. + /// + /// The second parameter is local providers and the third parameter is external providers. + pub override_queries: + Option, &mut ty::query::Providers<'_>)>, } pub fn run_compiler_in_existing_thread_pool(config: Config, f: F) -> R @@ -157,6 +167,7 @@ where queries: Default::default(), crate_name: config.crate_name, register_lints: config.register_lints, + override_queries: config.override_queries, }; let _sess_abort_error = OnDrop(|| { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 453007c564246..c57622b8b8fe5 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -786,6 +786,7 @@ pub fn create_global_ctxt( let codegen_backend = compiler.codegen_backend().clone(); let crate_name = crate_name.to_string(); let defs = mem::take(&mut resolver_outputs.definitions); + let override_queries = compiler.override_queries; let ((), result) = BoxedGlobalCtxt::new(static move || { let sess = &*sess; @@ -810,6 +811,10 @@ pub fn create_global_ctxt( default_provide_extern(&mut extern_providers); codegen_backend.provide_extern(&mut extern_providers); + if let Some(callback) = override_queries { + callback(sess, &mut local_providers, &mut extern_providers); + } + let gcx = TyCtxt::create_global_ctxt( sess, lint_store, diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 115345955aea3..6b9d708cefaca 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -108,6 +108,10 @@ pub fn create_session( process_configure_mod, ); + sess.prof.register_queries(|profiler| { + rustc::ty::query::QueryName::register_with_profiler(&profiler); + }); + let codegen_backend = get_codegen_backend(&sess); let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 05e3ee3322e59..b4dea19d3dc3f 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -531,7 +531,7 @@ impl<'a> CrateLoader<'a> { }); if !any_non_rlib { info!("panic runtime injection skipped, only generating rlib"); - self.sess.injected_panic_runtime.set(None); + self.cstore.injected_panic_runtime = None; return } @@ -563,7 +563,7 @@ impl<'a> CrateLoader<'a> { // we just don't need one at all, then we're done here and there's // nothing else to do. if !needs_panic_runtime || runtime_found { - self.sess.injected_panic_runtime.set(None); + self.cstore.injected_panic_runtime = None; return } @@ -600,7 +600,7 @@ impl<'a> CrateLoader<'a> { name, desired_strategy.desc())); } - self.sess.injected_panic_runtime.set(Some(cnum)); + self.cstore.injected_panic_runtime = Some(cnum); self.inject_dependency_if(cnum, "a panic runtime", &|data| data.root.needs_panic_runtime); } @@ -722,7 +722,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_allocator_crate(&self, krate: &ast::Crate) { + fn inject_allocator_crate(&mut self, krate: &ast::Crate) { let has_global_allocator = match &*global_allocator_spans(krate) { [span1, span2, ..] => { self.sess.struct_span_err(*span2, "cannot define multiple global allocators") @@ -742,7 +742,7 @@ impl<'a> CrateLoader<'a> { needs_allocator = needs_allocator || data.root.needs_allocator; }); if !needs_allocator { - self.sess.allocator_kind.set(None); + self.cstore.allocator_kind = None; return } @@ -758,7 +758,7 @@ impl<'a> CrateLoader<'a> { } }); if all_rlib { - self.sess.allocator_kind.set(None); + self.cstore.allocator_kind = None; return } @@ -795,7 +795,7 @@ impl<'a> CrateLoader<'a> { } }); if global_allocator.is_some() { - self.sess.allocator_kind.set(Some(AllocatorKind::Global)); + self.cstore.allocator_kind = Some(AllocatorKind::Global); return } @@ -816,7 +816,7 @@ impl<'a> CrateLoader<'a> { add `#[global_allocator]` to a static item \ that implements the GlobalAlloc trait."); } - self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib)); + self.cstore.allocator_kind = Some(AllocatorKind::DefaultLib); } fn inject_dependency_if(&self, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index c6c8ee575a98a..54857ce1b8281 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -14,6 +14,7 @@ use rustc_data_structures::svh::Svh; use syntax::ast; use syntax::edition::Edition; use syntax_expand::base::SyntaxExtension; +use syntax::expand::allocator::AllocatorKind; use syntax_pos; use proc_macro::bridge::client::ProcMacro; @@ -101,6 +102,8 @@ crate struct CrateMetadata { #[derive(Clone)] pub struct CStore { metas: IndexVec>>, + pub(crate) injected_panic_runtime: Option, + pub(crate) allocator_kind: Option, } pub enum LoadedMacro { @@ -116,6 +119,8 @@ impl Default for CStore { // corresponding `CrateNum`. This first entry will always remain // `None`. metas: IndexVec::from_elem_n(None, 1), + injected_panic_runtime: None, + allocator_kind: None, } } } diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 7f76a9730e198..dbf7fede1469f 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -184,7 +184,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // // Things like allocators and panic runtimes may not have been activated // quite yet, so do so here. - activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, + activate_injected_dep(tcx.injected_panic_runtime(), &mut ret, &|cnum| tcx.is_panic_runtime(cnum)); // When dylib B links to dylib A, then when using B we must also link to A. @@ -244,7 +244,6 @@ fn add_library( } fn attempt_static(tcx: TyCtxt<'_>) -> Option { - let sess = &tcx.sess; let crates = cstore::used_crates(tcx, RequireStatic); if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { return None @@ -264,7 +263,7 @@ fn attempt_static(tcx: TyCtxt<'_>) -> Option { // Our allocator/panic runtime may not have been linked above if it wasn't // explicitly linked, which is the case for any injected dependency. Handle // that here and activate them. - activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, + activate_injected_dep(tcx.injected_panic_runtime(), &mut ret, &|cnum| tcx.is_panic_runtime(cnum)); Some(ret) diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index 015866548cd38..a6cb3864ca7d4 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -31,6 +31,7 @@ use syntax::attr; use syntax::source_map; use syntax::source_map::Spanned; use syntax::symbol::Symbol; +use syntax::expand::allocator::AllocatorKind; use syntax_pos::{Span, FileName}; macro_rules! provide { @@ -527,4 +528,12 @@ impl CrateStore for cstore::CStore { { rmeta::METADATA_HEADER } + + fn injected_panic_runtime(&self) -> Option { + self.injected_panic_runtime + } + + fn allocator_kind(&self) -> Option { + self.allocator_kind + } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 982330baf9c95..8e574cc961b2b 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -560,13 +560,6 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } - fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { - match ty.kind { - ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), - _ => false, - } - } - fn is_local(&self, ty: Ty<'tcx>) -> bool { match ty.kind { ty::Adt(adt_def, ..) => adt_def.did.is_local(), @@ -590,6 +583,8 @@ enum Constructor<'tcx> { FixedLenSlice(u64), /// Slice patterns. Captures any array constructor of `length >= i + j`. VarLenSlice(u64, u64), + /// Fake extra constructor for enums that aren't allowed to be matched exhaustively. + NonExhaustive, } // Ignore spans when comparing, they don't carry semantic information as they are only for lints. @@ -597,6 +592,7 @@ impl<'tcx> std::cmp::PartialEq for Constructor<'tcx> { fn eq(&self, other: &Self) -> bool { match (self, other) { (Constructor::Single, Constructor::Single) => true, + (Constructor::NonExhaustive, Constructor::NonExhaustive) => true, (Constructor::Variant(a), Constructor::Variant(b)) => a == b, (Constructor::ConstantValue(a, _), Constructor::ConstantValue(b, _)) => a == b, ( @@ -771,6 +767,8 @@ impl<'tcx> Constructor<'tcx> { // ranges have been omitted. remaining_ctors } + // This constructor is never covered by anything else + NonExhaustive => vec![NonExhaustive], } } @@ -781,65 +779,68 @@ impl<'tcx> Constructor<'tcx> { ty: Ty<'tcx>, ) -> Vec> { debug!("wildcard_subpatterns({:#?}, {:?})", self, ty); - match ty.kind { - ty::Tuple(ref fs) => { - fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect() - } - ty::Slice(ty) | ty::Array(ty, _) => match *self { - FixedLenSlice(length) => (0..length).map(|_| Pat::wildcard_from_ty(ty)).collect(), - VarLenSlice(prefix, suffix) => { - (0..prefix + suffix).map(|_| Pat::wildcard_from_ty(ty)).collect() + + match self { + Single | Variant(_) => match ty.kind { + ty::Tuple(ref fs) => { + fs.into_iter().map(|t| t.expect_ty()).map(Pat::wildcard_from_ty).collect() } - ConstantValue(..) => vec![], - _ => bug!("bad slice pattern {:?} {:?}", self, ty), - }, - ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)], - ty::Adt(adt, substs) => { - if adt.is_box() { - // Use T as the sub pattern type of Box. - vec![Pat::wildcard_from_ty(substs.type_at(0))] - } else { - let variant = &adt.variants[self.variant_index_for_adt(cx, adt)]; - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !cx.is_local(ty); - variant - .fields - .iter() - .map(|field| { - let is_visible = - adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); - let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs)); - match (is_visible, is_non_exhaustive, is_uninhabited) { - // Treat all uninhabited types in non-exhaustive variants as - // `TyErr`. - (_, true, true) => cx.tcx.types.err, - // Treat all non-visible fields as `TyErr`. They can't appear in - // any other pattern from this match (because they are private), so - // their type does not matter - but we don't want to know they are - // uninhabited. - (false, ..) => cx.tcx.types.err, - (true, ..) => { - let ty = field.ty(cx.tcx, substs); - match ty.kind { - // If the field type returned is an array of an unknown - // size return an TyErr. - ty::Array(_, len) - if len - .try_eval_usize(cx.tcx, cx.param_env) - .is_none() => - { - cx.tcx.types.err + ty::Ref(_, rty, _) => vec![Pat::wildcard_from_ty(rty)], + ty::Adt(adt, substs) => { + if adt.is_box() { + // Use T as the sub pattern type of Box. + vec![Pat::wildcard_from_ty(substs.type_at(0))] + } else { + let variant = &adt.variants[self.variant_index_for_adt(cx, adt)]; + let is_non_exhaustive = + variant.is_field_list_non_exhaustive() && !cx.is_local(ty); + variant + .fields + .iter() + .map(|field| { + let is_visible = adt.is_enum() + || field.vis.is_accessible_from(cx.module, cx.tcx); + let is_uninhabited = cx.is_uninhabited(field.ty(cx.tcx, substs)); + match (is_visible, is_non_exhaustive, is_uninhabited) { + // Treat all uninhabited types in non-exhaustive variants as + // `TyErr`. + (_, true, true) => cx.tcx.types.err, + // Treat all non-visible fields as `TyErr`. They can't appear + // in any other pattern from this match (because they are + // private), so their type does not matter - but we don't want + // to know they are uninhabited. + (false, ..) => cx.tcx.types.err, + (true, ..) => { + let ty = field.ty(cx.tcx, substs); + match ty.kind { + // If the field type returned is an array of an unknown + // size return an TyErr. + ty::Array(_, len) + if len + .try_eval_usize(cx.tcx, cx.param_env) + .is_none() => + { + cx.tcx.types.err + } + _ => ty, } - _ => ty, } } - } - }) - .map(Pat::wildcard_from_ty) - .collect() + }) + .map(Pat::wildcard_from_ty) + .collect() + } } - } - _ => vec![], + _ => vec![], + }, + FixedLenSlice(_) | VarLenSlice(..) => match ty.kind { + ty::Slice(ty) | ty::Array(ty, _) => { + let arity = self.arity(cx, ty); + (0..arity).map(|_| Pat::wildcard_from_ty(ty)).collect() + } + _ => bug!("bad slice pattern {:?} {:?}", self, ty), + }, + ConstantValue(..) | ConstantRange(..) | NonExhaustive => vec![], } } @@ -850,19 +851,19 @@ impl<'tcx> Constructor<'tcx> { /// A struct pattern's arity is the number of fields it contains, etc. fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 { debug!("Constructor::arity({:#?}, {:?})", self, ty); - match ty.kind { - ty::Tuple(ref fs) => fs.len() as u64, - ty::Slice(..) | ty::Array(..) => match *self { - FixedLenSlice(length) => length, - VarLenSlice(prefix, suffix) => prefix + suffix, - ConstantValue(..) => 0, - _ => bug!("bad slice pattern {:?} {:?}", self, ty), + match self { + Single | Variant(_) => match ty.kind { + ty::Tuple(ref fs) => fs.len() as u64, + ty::Slice(..) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty), + ty::Ref(..) => 1, + ty::Adt(adt, _) => { + adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64 + } + _ => 0, }, - ty::Ref(..) => 1, - ty::Adt(adt, _) => { - adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64 - } - _ => 0, + FixedLenSlice(length) => *length, + VarLenSlice(prefix, suffix) => prefix + suffix, + ConstantValue(..) | ConstantRange(..) | NonExhaustive => 0, } } @@ -886,53 +887,50 @@ impl<'tcx> Constructor<'tcx> { pats: impl IntoIterator>, ) -> Pat<'tcx> { let mut subpatterns = pats.into_iter(); - let pat = match ty.kind { - ty::Adt(..) | ty::Tuple(..) => { - let subpatterns = subpatterns - .enumerate() - .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) - .collect(); - - if let ty::Adt(adt, substs) = ty.kind { - if adt.is_enum() { - PatKind::Variant { - adt_def: adt, - substs, - variant_index: self.variant_index_for_adt(cx, adt), - subpatterns, + + let pat = match self { + Single | Variant(_) => match ty.kind { + ty::Adt(..) | ty::Tuple(..) => { + let subpatterns = subpatterns + .enumerate() + .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) + .collect(); + + if let ty::Adt(adt, substs) = ty.kind { + if adt.is_enum() { + PatKind::Variant { + adt_def: adt, + substs, + variant_index: self.variant_index_for_adt(cx, adt), + subpatterns, + } + } else { + PatKind::Leaf { subpatterns } } } else { PatKind::Leaf { subpatterns } } - } else { - PatKind::Leaf { subpatterns } - } - } - - ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() }, - - ty::Slice(_) | ty::Array(..) => match self { - FixedLenSlice(_) => { - PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] } } - VarLenSlice(prefix_len, _suffix_len) => { - let prefix = subpatterns.by_ref().take(*prefix_len as usize).collect(); - let suffix = subpatterns.collect(); - let wild = Pat::wildcard_from_ty(ty); - PatKind::Slice { prefix, slice: Some(wild), suffix } - } - _ => bug!("bad slice pattern {:?} {:?}", self, ty), - }, - - _ => match *self { - ConstantValue(value, _) => PatKind::Constant { value }, - ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { - lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), - hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), - end, - }), + ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() }, + ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty), _ => PatKind::Wild, }, + FixedLenSlice(_) => { + PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] } + } + &VarLenSlice(prefix_len, _) => { + let prefix = subpatterns.by_ref().take(prefix_len as usize).collect(); + let suffix = subpatterns.collect(); + let wild = Pat::wildcard_from_ty(ty); + PatKind::Slice { prefix, slice: Some(wild), suffix } + } + &ConstantValue(value, _) => PatKind::Constant { value }, + &ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { + lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), + hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), + end, + }), + NonExhaustive => PatKind::Wild, }; Pat { ty, span: DUMMY_SP, kind: Box::new(pat) } @@ -1128,7 +1126,7 @@ fn all_constructors<'a, 'tcx>( pcx: PatCtxt<'tcx>, ) -> Vec> { debug!("all_constructors({:?})", pcx.ty); - let ctors = match pcx.ty.kind { + match pcx.ty.kind { ty::Bool => [true, false] .iter() .map(|&b| ConstantValue(ty::Const::from_bool(cx.tcx, b), pcx.span)) @@ -1145,17 +1143,49 @@ fn all_constructors<'a, 'tcx>( vec![VarLenSlice(0, 0)] } } - ty::Adt(def, substs) if def.is_enum() => def - .variants - .iter() - .filter(|v| { - !cx.tcx.features().exhaustive_patterns - || !v - .uninhabited_from(cx.tcx, substs, def.adt_kind()) - .contains(cx.tcx, cx.module) - }) - .map(|v| Variant(v.def_id)) - .collect(), + ty::Adt(def, substs) if def.is_enum() => { + let ctors: Vec<_> = def + .variants + .iter() + .filter(|v| { + !cx.tcx.features().exhaustive_patterns + || !v + .uninhabited_from(cx.tcx, substs, def.adt_kind()) + .contains(cx.tcx, cx.module) + }) + .map(|v| Variant(v.def_id)) + .collect(); + + // If our scrutinee is *privately* an empty enum, we must treat it as though it had an + // "unknown" constructor (in that case, all other patterns obviously can't be variants) + // to avoid exposing its emptyness. See the `match_privately_empty` test for details. + // FIXME: currently the only way I know of something can be a privately-empty enum is + // when the exhaustive_patterns feature flag is not present, so this is only needed for + // that case. + let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty); + // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an + // additionnal "unknown" constructor. + let is_declared_nonexhaustive = + def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty); + + if is_privately_empty || is_declared_nonexhaustive { + // There is no point in enumerating all possible variants, because the user can't + // actually match against them themselves. So we return only the fictitious + // constructor. + // E.g., in an example like: + // ``` + // let err: io::ErrorKind = ...; + // match err { + // io::ErrorKind::NotFound => {}, + // } + // ``` + // we don't want to show every possible IO error, but instead have only `_` as the + // witness. + vec![NonExhaustive] + } else { + ctors + } + } ty::Char => { vec![ // The valid Unicode Scalar Value ranges. @@ -1175,6 +1205,15 @@ fn all_constructors<'a, 'tcx>( ), ] } + ty::Int(_) | ty::Uint(_) + if pcx.ty.is_ptr_sized_integral() + && !cx.tcx.features().precise_pointer_size_matching => + { + // `usize`/`isize` are not allowed to be matched exhaustively unless the + // `precise_pointer_size_matching` feature is enabled. So we treat those types like + // `#[non_exhaustive]` enums by returning a special unmatcheable constructor. + vec![NonExhaustive] + } ty::Int(ity) => { let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128; let min = 1u128 << (bits - 1); @@ -1193,8 +1232,7 @@ fn all_constructors<'a, 'tcx>( vec![Single] } } - }; - ctors + } } /// An inclusive interval, used for precise integer exhaustiveness checking. @@ -1592,9 +1630,6 @@ pub fn is_useful<'p, 'a, 'tcx>( let all_ctors = all_constructors(cx, pcx); debug!("all_ctors = {:#?}", all_ctors); - let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty); - let is_declared_nonexhaustive = cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty); - // `missing_ctors` is the set of constructors from the same type as the // first column of `matrix` that are matched only by wildcard patterns // from the first column. @@ -1602,38 +1637,15 @@ pub fn is_useful<'p, 'a, 'tcx>( // Therefore, if there is some pattern that is unmatched by `matrix`, // it will still be unmatched if the first constructor is replaced by // any of the constructors in `missing_ctors` - // - // However, if our scrutinee is *privately* an empty enum, we - // must treat it as though it had an "unknown" constructor (in - // that case, all other patterns obviously can't be variants) - // to avoid exposing its emptyness. See the `match_privately_empty` - // test for details. - // - // FIXME: currently the only way I know of something can - // be a privately-empty enum is when the exhaustive_patterns - // feature flag is not present, so this is only - // needed for that case. - - // Missing constructors are those that are not matched by any - // non-wildcard patterns in the current column. To determine if - // the set is empty, we can check that `.peek().is_none()`, so - // we only fully construct them on-demand, because they're rarely used and can be big. - let missing_ctors = MissingConstructors::new(cx.tcx, cx.param_env, all_ctors, used_ctors); - debug!( - "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}", - missing_ctors.is_empty(), - is_privately_empty, - is_declared_nonexhaustive - ); + // Missing constructors are those that are not matched by any non-wildcard patterns in the + // current column. We only fully construct them on-demand, because they're rarely used and + // can be big. + let missing_ctors = MissingConstructors::new(cx.tcx, cx.param_env, all_ctors, used_ctors); - // For privately empty and non-exhaustive enums, we work as if there were an "extra" - // `_` constructor for the type, so we can never match over all constructors. - let is_non_exhaustive = is_privately_empty - || is_declared_nonexhaustive - || (pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching); + debug!("missing_ctors.empty()={:#?}", missing_ctors.is_empty(),); - if missing_ctors.is_empty() && !is_non_exhaustive { + if missing_ctors.is_empty() { let (all_ctors, _) = missing_ctors.into_inner(); split_grouped_constructors(cx.tcx, cx.param_env, pcx, all_ctors, matrix, DUMMY_SP, None) .into_iter() @@ -1662,26 +1674,9 @@ pub fn is_useful<'p, 'a, 'tcx>( // // we can report 3 witnesses: `S`, `E`, and `W`. // - // However, there are 2 cases where we don't want + // However, there is a case where we don't want // to do this and instead report a single `_` witness: - // - // 1) If the user is matching against a non-exhaustive - // enum, there is no point in enumerating all possible - // variants, because the user can't actually match - // against them themselves, e.g., in an example like: - // ``` - // let err: io::ErrorKind = ...; - // match err { - // io::ErrorKind::NotFound => {}, - // } - // ``` - // we don't want to show every possible IO error, - // but instead have `_` as the witness (this is - // actually *required* if the user specified *all* - // IO errors, but is probably what we want in every - // case). - // - // 2) If the user didn't actually specify a constructor + // if the user didn't actually specify a constructor // in this arm, e.g., in // ``` // let x: (Direction, Direction, bool) = ...; @@ -1691,7 +1686,7 @@ pub fn is_useful<'p, 'a, 'tcx>( // `(, , true)` - we are // satisfied with `(_, _, true)`. In this case, // `used_ctors` is empty. - if is_non_exhaustive || missing_ctors.all_ctors_are_missing() { + if missing_ctors.all_ctors_are_missing() { // All constructors are unused. Add a wild pattern // rather than each individual constructor. usefulness.apply_wildcard(pcx.ty) @@ -2218,13 +2213,21 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>( /// fields filled with wild patterns. fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>( cx: &mut MatchCheckCtxt<'a, 'tcx>, - pat: &'q Pat<'tcx>, + mut pat: &'q Pat<'tcx>, constructor: &Constructor<'tcx>, ctor_wild_subpatterns: &[&'p Pat<'tcx>], ) -> Option> { + while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind { + pat = subpattern; + } + + if let NonExhaustive = constructor { + // Only a wildcard pattern can match the special extra constructor + return if pat.is_wildcard() { Some(PatStack::default()) } else { None }; + } + let result = match *pat.kind { - PatKind::AscribeUserType { ref subpattern, .. } => PatStack::from_pattern(subpattern) - .specialize_constructor(cx, constructor, ctor_wild_subpatterns), + PatKind::AscribeUserType { .. } => bug!(), // Handled above PatKind::Binding { .. } | PatKind::Wild => { Some(PatStack::from_slice(ctor_wild_subpatterns)) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 2ede43e2111ed..489f71c489d02 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -638,8 +638,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn should_const_prop(&self) -> bool { - self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 + fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool { + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { + return true; + } else if self.tcx.sess.opts.debugging_opts.mir_opt_level == 0 { + return false; + } + + match *op { + interpret::Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Scalar(s))) => + s.is_bits(), + interpret::Operand::Immediate(Immediate::ScalarPair(ScalarMaybeUndef::Scalar(l), + ScalarMaybeUndef::Scalar(r))) => + l.is_bits() && r.is_bits(), + _ => false + } } } @@ -739,15 +752,15 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if self.can_const_prop[local] { trace!("propagated into {:?}", local); - if self.should_const_prop() { - let value = - self.get_const(local).expect("local was dead/uninitialized"); - trace!("replacing {:?} with {:?}", rval, value); - self.replace_with_const( - rval, - value, - statement.source_info, - ); + if let Some(value) = self.get_const(local) { + if self.should_const_prop(value) { + trace!("replacing {:?} with {:?}", rval, value); + self.replace_with_const( + rval, + value, + statement.source_info, + ); + } } } else { trace!("can't propagate into {:?}", local); @@ -849,7 +862,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { &msg, ); } else { - if self.should_const_prop() { + if self.should_const_prop(value) { if let ScalarMaybeUndef::Scalar(scalar) = value_const { *cond = self.operand_from_scalar( scalar, @@ -862,8 +875,8 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } }, TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { - if self.should_const_prop() { - if let Some(value) = self.eval_operand(&discr, source_info) { + if let Some(value) = self.eval_operand(&discr, source_info) { + if self.should_const_prop(value) { if let ScalarMaybeUndef::Scalar(scalar) = self.ecx.read_scalar(value).unwrap() { *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b227f432a4e98..0f508966a4cc2 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -247,7 +247,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } = options; // Add the rustdoc cfg into the doc build. - cfgs.push("rustdoc".to_string()); + cfgs.push("doc".to_string()); let cpath = Some(input.clone()); let input = Input::File(input); @@ -335,6 +335,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt crate_name, lint_caps, register_lints: None, + override_queries: None, }; interface::run_compiler_in_existing_thread_pool(config, |compiler| { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 553ef6a9c4788..c483f6fb4770f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -64,7 +64,7 @@ pub fn run(options: Options) -> i32 { }; let mut cfgs = options.cfgs.clone(); - cfgs.push("rustdoc".to_owned()); + cfgs.push("doc".to_owned()); cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, @@ -79,6 +79,7 @@ pub fn run(options: Options) -> i32 { crate_name: options.crate_name.clone(), lint_caps: Default::default(), register_lints: None, + override_queries: None, }; let mut test_args = options.test_args.clone(); diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index ad567c97c2c40..557da174d8941 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -369,7 +369,7 @@ impl Seek for BufReader { /// /// It is critical to call [`flush`] before `BufWriter` is dropped. Though /// dropping will attempt to flush the the contents of the buffer, any errors -/// that happen in the process of dropping will be ignored. Calling ['flush'] +/// that happen in the process of dropping will be ignored. Calling [`flush`] /// ensures that the buffer is empty and thus dropping will not even attempt /// file operations. /// diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index d44c8ca544e80..a8d2b0cb397ab 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -4,7 +4,7 @@ #![allow(missing_docs, nonstandard_style, missing_debug_implementations)] cfg_if::cfg_if! { - if #[cfg(rustdoc)] { + if #[cfg(doc)] { // When documenting libstd we want to show unix/windows/linux modules as // these are the "main modules" that are used across platforms. This diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index 16b0539cdb9f9..9eeab34643f93 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -56,7 +56,7 @@ cfg_if::cfg_if! { // then later used in the `std::os` module when documenting, for example, // Windows when we're compiling for Linux. -#[cfg(rustdoc)] +#[cfg(doc)] cfg_if::cfg_if! { if #[cfg(unix)] { // On unix we'll document what's already available @@ -80,7 +80,7 @@ cfg_if::cfg_if! { } } -#[cfg(rustdoc)] +#[cfg(doc)] cfg_if::cfg_if! { if #[cfg(windows)] { // On windows we'll just be documenting what's already available diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index d0bed0f038e6c..bf0166ceb6fbf 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -2,21 +2,21 @@ use crate::io::ErrorKind; -#[cfg(any(rustdoc, target_os = "linux"))] pub use crate::os::linux as platform; - -#[cfg(all(not(rustdoc), target_os = "android"))] pub use crate::os::android as platform; -#[cfg(all(not(rustdoc), target_os = "dragonfly"))] pub use crate::os::dragonfly as platform; -#[cfg(all(not(rustdoc), target_os = "freebsd"))] pub use crate::os::freebsd as platform; -#[cfg(all(not(rustdoc), target_os = "haiku"))] pub use crate::os::haiku as platform; -#[cfg(all(not(rustdoc), target_os = "ios"))] pub use crate::os::ios as platform; -#[cfg(all(not(rustdoc), target_os = "macos"))] pub use crate::os::macos as platform; -#[cfg(all(not(rustdoc), target_os = "netbsd"))] pub use crate::os::netbsd as platform; -#[cfg(all(not(rustdoc), target_os = "openbsd"))] pub use crate::os::openbsd as platform; -#[cfg(all(not(rustdoc), target_os = "solaris"))] pub use crate::os::solaris as platform; -#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use crate::os::emscripten as platform; -#[cfg(all(not(rustdoc), target_os = "fuchsia"))] pub use crate::os::fuchsia as platform; -#[cfg(all(not(rustdoc), target_os = "l4re"))] pub use crate::os::linux as platform; -#[cfg(all(not(rustdoc), target_os = "redox"))] pub use crate::os::redox as platform; +#[cfg(any(doc, target_os = "linux"))] pub use crate::os::linux as platform; + +#[cfg(all(not(doc), target_os = "android"))] pub use crate::os::android as platform; +#[cfg(all(not(doc), target_os = "dragonfly"))] pub use crate::os::dragonfly as platform; +#[cfg(all(not(doc), target_os = "freebsd"))] pub use crate::os::freebsd as platform; +#[cfg(all(not(doc), target_os = "haiku"))] pub use crate::os::haiku as platform; +#[cfg(all(not(doc), target_os = "ios"))] pub use crate::os::ios as platform; +#[cfg(all(not(doc), target_os = "macos"))] pub use crate::os::macos as platform; +#[cfg(all(not(doc), target_os = "netbsd"))] pub use crate::os::netbsd as platform; +#[cfg(all(not(doc), target_os = "openbsd"))] pub use crate::os::openbsd as platform; +#[cfg(all(not(doc), target_os = "solaris"))] pub use crate::os::solaris as platform; +#[cfg(all(not(doc), target_os = "emscripten"))] pub use crate::os::emscripten as platform; +#[cfg(all(not(doc), target_os = "fuchsia"))] pub use crate::os::fuchsia as platform; +#[cfg(all(not(doc), target_os = "l4re"))] pub use crate::os::linux as platform; +#[cfg(all(not(doc), target_os = "redox"))] pub use crate::os::redox as platform; pub use self::rand::hashmap_random_keys; pub use libc::strlen; diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 7a0bcd03d758f..8912aed925580 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -45,7 +45,7 @@ pub mod backtrace; pub mod condvar; pub mod io; pub mod mutex; -#[cfg(any(rustdoc, // see `mod os`, docs are generated for multiple platforms +#[cfg(any(doc, // see `mod os`, docs are generated for multiple platforms unix, target_os = "redox", target_os = "cloudabi", diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 608cc2a09cbee..555c715771aaa 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -30,7 +30,7 @@ const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[ (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), - (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), + (sym::doc, sym::doc_cfg, cfg_fn!(doc_cfg)), ]; #[derive(Debug)] diff --git a/src/test/codegen/optimize-attr-1.rs b/src/test/codegen/optimize-attr-1.rs index 4a5b7c05231dc..a8be10ba3ce0a 100644 --- a/src/test/codegen/optimize-attr-1.rs +++ b/src/test/codegen/optimize-attr-1.rs @@ -8,7 +8,7 @@ // CHECK-LABEL: define i32 @nothing // CHECK-SAME: [[NOTHING_ATTRS:#[0-9]+]] -// NO-OPT: ret i32 %_1.0 +// NO-OPT: ret i32 4 // SIZE-OPT: ret i32 4 // SPEEC-OPT: ret i32 4 #[no_mangle] @@ -18,7 +18,7 @@ pub fn nothing() -> i32 { // CHECK-LABEL: define i32 @size // CHECK-SAME: [[SIZE_ATTRS:#[0-9]+]] -// NO-OPT: ret i32 %_1.0 +// NO-OPT: ret i32 6 // SIZE-OPT: ret i32 6 // SPEED-OPT: ret i32 6 #[optimize(size)] @@ -31,7 +31,7 @@ pub fn size() -> i32 { // NO-OPT-SAME: [[NOTHING_ATTRS]] // SPEED-OPT-SAME: [[NOTHING_ATTRS]] // SIZE-OPT-SAME: [[SPEED_ATTRS:#[0-9]+]] -// NO-OPT: ret i32 %_1.0 +// NO-OPT: ret i32 8 // SIZE-OPT: ret i32 8 // SPEED-OPT: ret i32 8 #[optimize(speed)] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 1e628d019196b..615f1fe1fd0b8 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -141,7 +141,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -216,7 +216,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 295c2244879f8..70d0f86c3d268 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 9582137eae91c..9f1850dfb4c90 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -60,6 +60,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { crate_name: None, lint_caps: Default::default(), register_lints: None, + override_queries: None, }; interface::run_compiler(config, |compiler| { diff --git a/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs b/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs index d0ead4136575f..62fd3da9233fa 100644 --- a/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs +++ b/src/test/rustdoc-ui/doc-test-rustdoc-feature.rs @@ -4,11 +4,11 @@ #![feature(doc_cfg)] -// Make sure `cfg(rustdoc)` is set when finding doctests but not inside the doctests. +// Make sure `cfg(doc)` is set when finding doctests but not inside the doctests. /// ``` /// #![feature(doc_cfg)] -/// assert!(!cfg!(rustdoc)); +/// assert!(!cfg!(doc)); /// ``` -#[cfg(rustdoc)] +#[cfg(doc)] pub struct Foo; diff --git a/src/test/ui/consts/issue-52432.rs b/src/test/ui/consts/issue-52432.rs new file mode 100644 index 0000000000000..2d4c939f47d79 --- /dev/null +++ b/src/test/ui/consts/issue-52432.rs @@ -0,0 +1,10 @@ +#![feature(const_raw_ptr_to_usize_cast)] + +fn main() { + [(); &(static |x| {}) as *const _ as usize]; + //~^ ERROR: closures cannot be static + //~| ERROR: type annotations needed + [(); &(static || {}) as *const _ as usize]; + //~^ ERROR: closures cannot be static + //~| ERROR: evaluation of constant value failed +} diff --git a/src/test/ui/consts/issue-52432.stderr b/src/test/ui/consts/issue-52432.stderr new file mode 100644 index 0000000000000..e9539d24118a0 --- /dev/null +++ b/src/test/ui/consts/issue-52432.stderr @@ -0,0 +1,28 @@ +error[E0697]: closures cannot be static + --> $DIR/issue-52432.rs:4:12 + | +LL | [(); &(static |x| {}) as *const _ as usize]; + | ^^^^^^^^^^ + +error[E0697]: closures cannot be static + --> $DIR/issue-52432.rs:7:12 + | +LL | [(); &(static || {}) as *const _ as usize]; + | ^^^^^^^^^ + +error[E0282]: type annotations needed + --> $DIR/issue-52432.rs:4:20 + | +LL | [(); &(static |x| {}) as *const _ as usize]; + | ^ consider giving this closure parameter a type + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-52432.rs:7:10 + | +LL | [(); &(static || {}) as *const _ as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0282, E0697. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs index 17ea58231915d..9830503a8cac6 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs +++ b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.rs @@ -1,4 +1,4 @@ -#[cfg(rustdoc)] //~ ERROR: `cfg(rustdoc)` is experimental and subject to change +#[cfg(doc)] //~ ERROR: `cfg(doc)` is experimental and subject to change pub struct SomeStruct; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr index 9bf97a4a4771c..26a1f4decf4cf 100644 --- a/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr +++ b/src/test/ui/feature-gates/feature-gate-doc_cfg-cfg-rustdoc.stderr @@ -1,8 +1,8 @@ -error[E0658]: `cfg(rustdoc)` is experimental and subject to change +error[E0658]: `cfg(doc)` is experimental and subject to change --> $DIR/feature-gate-doc_cfg-cfg-rustdoc.rs:1:7 | -LL | #[cfg(rustdoc)] - | ^^^^^^^ +LL | #[cfg(doc)] + | ^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/43781 = help: add `#![feature(doc_cfg)]` to the crate attributes to enable diff --git a/src/test/ui/issues/issue-40231-1.rs b/src/test/ui/issues/issue-40231-1.rs new file mode 100644 index 0000000000000..999399ec8d34c --- /dev/null +++ b/src/test/ui/issues/issue-40231-1.rs @@ -0,0 +1,54 @@ +// check-pass + +#![allow(dead_code)] + +trait Structure: Sized where E: Encoding { + type RefTarget: ?Sized; + type FfiPtr; + unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>; +} + +enum Slice {} + +impl Structure for Slice where E: Encoding { + type RefTarget = [E::Unit]; + type FfiPtr = (*const E::FfiUnit, usize); + unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> { + panic!() + } +} + +trait Encoding { + type Unit: Unit; + type FfiUnit; +} + +trait Unit {} + +enum Utf16 {} + +impl Encoding for Utf16 { + type Unit = Utf16Unit; + type FfiUnit = u16; +} + +struct Utf16Unit(pub u16); + +impl Unit for Utf16Unit {} + +type SUtf16Str = SeStr; + +struct SeStr where S: Structure, E: Encoding { + _data: S::RefTarget, +} + +impl SeStr where S: Structure, E: Encoding { + pub unsafe fn from_ptr<'a>(_ptr: S::FfiPtr) -> Option<&'a Self> { + panic!() + } +} + +fn main() { + const TEXT_U16: &'static [u16] = &[]; + let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() }; +} diff --git a/src/test/ui/issues/issue-40231-2.rs b/src/test/ui/issues/issue-40231-2.rs new file mode 100644 index 0000000000000..780433b28c596 --- /dev/null +++ b/src/test/ui/issues/issue-40231-2.rs @@ -0,0 +1,54 @@ +// check-pass + +#![allow(dead_code)] + +trait Structure: Sized where E: Encoding { + type RefTarget: ?Sized; + type FfiPtr; + unsafe fn borrow_from_ffi_ptr<'a>(ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget>; +} + +enum Slice {} + +impl Structure for Slice where E: Encoding { + type RefTarget = [E::Unit]; + type FfiPtr = (*const E::FfiUnit, usize); + unsafe fn borrow_from_ffi_ptr<'a>(_ptr: Self::FfiPtr) -> Option<&'a Self::RefTarget> { + panic!() + } +} + +trait Encoding { + type Unit: Unit; + type FfiUnit; +} + +trait Unit {} + +enum Utf16 {} + +impl Encoding for Utf16 { + type Unit = Utf16Unit; + type FfiUnit = u16; +} + +struct Utf16Unit(pub u16); + +impl Unit for Utf16Unit {} + +struct SUtf16Str { + _data: >::RefTarget, +} + +impl SUtf16Str { + pub unsafe fn from_ptr<'a>(ptr: >::FfiPtr) + -> Option<&'a Self> { + std::mem::transmute::::Unit]>, _>( + >::borrow_from_ffi_ptr(ptr)) + } +} + +fn main() { + const TEXT_U16: &'static [u16] = &[]; + let _ = unsafe { SUtf16Str::from_ptr((TEXT_U16.as_ptr(), TEXT_U16.len())).unwrap() }; +} diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.rs b/src/test/ui/type-alias-impl-trait/issue-63279.rs new file mode 100644 index 0000000000000..586ff7a31587f --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63279.rs @@ -0,0 +1,9 @@ +#![feature(type_alias_impl_trait)] + +type Closure = impl FnOnce(); //~ ERROR: type mismatch resolving + +fn c() -> Closure { + || -> Closure { || () } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr new file mode 100644 index 0000000000000..a5065241fc74d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -0,0 +1,13 @@ +error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:6:5: 6:28] as std::ops::FnOnce<()>>::Output == ()` + --> $DIR/issue-63279.rs:3:1 + | +LL | type Closure = impl FnOnce(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found () + | + = note: expected type `Closure` + found type `()` + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/unboxed-closures/issue-30904.rs b/src/test/ui/unboxed-closures/issue-30904.rs new file mode 100644 index 0000000000000..eec5e962b431e --- /dev/null +++ b/src/test/ui/unboxed-closures/issue-30904.rs @@ -0,0 +1,36 @@ +#![feature(fn_traits, unboxed_closures)] + +fn test FnOnce<(&'x str,)>>(_: F) {} + +struct Compose(F,G); +impl FnOnce<(T,)> for Compose +where F: FnOnce<(T,)>, G: FnOnce<(F::Output,)> { + type Output = G::Output; + extern "rust-call" fn call_once(self, (x,): (T,)) -> G::Output { + (self.1)((self.0)(x)) + } +} + +struct Str<'a>(&'a str); +fn mk_str<'a>(s: &'a str) -> Str<'a> { Str(s) } + +fn main() { + let _: for<'a> fn(&'a str) -> Str<'a> = mk_str; + // expected concrete lifetime, found bound lifetime parameter 'a + let _: for<'a> fn(&'a str) -> Str<'a> = Str; + //~^ ERROR: mismatched types + + test(|_: &str| {}); + test(mk_str); + // expected concrete lifetime, found bound lifetime parameter 'x + test(Str); //~ ERROR: type mismatch in function arguments + + test(Compose(|_: &str| {}, |_| {})); + test(Compose(mk_str, |_| {})); + // internal compiler error: cannot relate bound region: + // ReLateBound(DebruijnIndex { depth: 2 }, + // BrNamed(DefId { krate: 0, node: DefIndex(6) => test::'x }, 'x(65))) + //<= ReSkolemized(0, + // BrNamed(DefId { krate: 0, node: DefIndex(6) => test::'x }, 'x(65))) + test(Compose(Str, |_| {})); +} diff --git a/src/test/ui/unboxed-closures/issue-30904.stderr b/src/test/ui/unboxed-closures/issue-30904.stderr new file mode 100644 index 0000000000000..943cbe0ccc297 --- /dev/null +++ b/src/test/ui/unboxed-closures/issue-30904.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/issue-30904.rs:20:45 + | +LL | let _: for<'a> fn(&'a str) -> Str<'a> = Str; + | ^^^ expected concrete lifetime, found bound lifetime parameter 'a + | + = note: expected type `for<'a> fn(&'a str) -> Str<'a>` + found type `fn(&str) -> Str<'_> {Str::<'_>}` + +error[E0631]: type mismatch in function arguments + --> $DIR/issue-30904.rs:26:10 + | +LL | fn test FnOnce<(&'x str,)>>(_: F) {} + | ---- -------------------------- required by this bound in `test` +... +LL | struct Str<'a>(&'a str); + | ------------------------ found signature of `fn(&str) -> _` +... +LL | test(Str); + | ^^^ expected signature of `for<'x> fn(&'x str) -> _` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.