diff --git a/.gitignore b/.gitignore index bf66eabc1c800..8b141416e4f63 100644 --- a/.gitignore +++ b/.gitignore @@ -73,12 +73,13 @@ __pycache__/ /obj/ /rt/ /rustllvm/ -/src/libunicode/DerivedCoreProperties.txt -/src/libunicode/EastAsianWidth.txt -/src/libunicode/HangulSyllableType.txt -/src/libunicode/PropList.txt -/src/libunicode/Scripts.txt -/src/libunicode/UnicodeData.txt +/src/libstd_unicode/DerivedCoreProperties.txt +/src/libstd_unicode/DerivedNormalizationProps.txt +/src/libstd_unicode/PropList.txt +/src/libstd_unicode/ReadMe.txt +/src/libstd_unicode/Scripts.txt +/src/libstd_unicode/SpecialCasing.txt +/src/libstd_unicode/UnicodeData.txt /stage[0-9]+/ /target /test/ diff --git a/.travis.yml b/.travis.yml index 15b610833b0ef..2b5eaecb0b42c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,10 +69,10 @@ script: if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then echo skipping, not a full build; elif [ "$TRAVIS_OS_NAME" = "osx" ]; then - git submodule update --init && + travis_retry git submodule update --init && src/ci/run.sh; else - git submodule update --init && + travis_retry git submodule update --init && src/ci/docker/run.sh $IMAGE; fi diff --git a/mk/crates.mk b/mk/crates.mk index 9624a51dda01b..0c553f5f08b80 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -177,6 +177,7 @@ TARGET_SPECIFIC_alloc_jemalloc := 1 DOC_CRATES := std alloc collections core libc std_unicode ifeq ($(CFG_DISABLE_JEMALLOC),) +RUSTFLAGS_std := --cfg 'feature="jemalloc"' RUSTFLAGS_rustc_back := --cfg 'feature="jemalloc"' endif diff --git a/mk/main.mk b/mk/main.mk index 2c646450d018e..9cd30be6531d1 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -175,7 +175,7 @@ endif # that the snapshot will be generated with a statically linked rustc so we only # have to worry about the distribution of one file (with its native dynamic # dependencies) -RUSTFLAGS_STAGE0 += -C prefer-dynamic -C no-stack-check +RUSTFLAGS_STAGE0 += -C prefer-dynamic RUSTFLAGS_STAGE1 += -C prefer-dynamic RUST_LIB_FLAGS_ST2 += -C prefer-dynamic RUST_LIB_FLAGS_ST3 += -C prefer-dynamic diff --git a/src/Cargo.lock b/src/Cargo.lock index 3da29933c812e..d153945dc091f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -569,7 +569,6 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_driver 0.0.0", "rustc_errors 0.0.0", diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 89d297760e286..85e8dbce1a955 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -72,7 +72,7 @@ def download(path, url, probably_big, verbose): option = "-#" else: option = "-s" - run(["curl", option, "-Sf", "-o", path, url], verbose=verbose) + run(["curl", option, "--retry", "3", "-Sf", "-o", path, url], verbose=verbose) def verify(path, sha_path, verbose): diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 2b063741c0740..d1c9918a73373 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -151,17 +151,25 @@ pub fn std(build: &Build, stage: u32, target: &str) { let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc"); cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/std_shim/Cargo.toml")) - .arg("--features").arg(build.std_features()) - .arg("--no-deps"); - - for krate in &["alloc", "collections", "core", "std", "std_unicode"] { - cargo.arg("-p").arg(krate); - // Create all crate output directories first to make sure rustdoc uses - // relative links. - // FIXME: Cargo should probably do this itself. - t!(fs::create_dir_all(out_dir.join(krate))); + .arg("--features").arg(build.std_features()); + + // We don't want to build docs for internal std dependencies unless + // in compiler-docs mode. When not in that mode, we whitelist the crates + // for which docs must be built. + if build.config.compiler_docs { + cargo.arg("-p").arg("std"); + } else { + cargo.arg("--no-deps"); + for krate in &["alloc", "collections", "core", "std", "std_unicode"] { + cargo.arg("-p").arg(krate); + // Create all crate output directories first to make sure rustdoc uses + // relative links. + // FIXME: Cargo should probably do this itself. + t!(fs::create_dir_all(out_dir.join(krate))); + } } + build.run(&mut cargo); cp_r(&out_dir, &out) } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index bf815a817ed87..a8a047a29285b 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -316,7 +316,6 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { "codegen-units"); suite("check-incremental", "src/test/incremental", "incremental", "incremental"); - suite("check-ui", "src/test/ui", "ui", "ui"); } if build.config.build.contains("msvc") { @@ -363,6 +362,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { }); }; + suite("check-ui", "src/test/ui", "ui", "ui"); suite("check-rpass-full", "src/test/run-pass-fulldeps", "run-pass", "run-pass-fulldeps"); suite("check-rfail-full", "src/test/run-fail-fulldeps", @@ -517,11 +517,21 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { // ======================================================================== // Documentation targets rules.doc("doc-book", "src/doc/book") - .dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0)) + .dep(move |s| { + s.name("tool-rustbook") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) .run(move |s| doc::rustbook(build, s.target, "book")); rules.doc("doc-nomicon", "src/doc/nomicon") - .dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0)) + .dep(move |s| { + s.name("tool-rustbook") + .host(&build.config.build) + .target(&build.config.build) + .stage(0) + }) .default(build.config.docs) .run(move |s| doc::rustbook(build, s.target, "nomicon")); rules.doc("doc-standalone", "src/doc") @@ -1364,7 +1374,6 @@ mod tests { assert!(plan.iter().any(|s| s.name.contains("-ui"))); assert!(plan.iter().any(|s| s.name.contains("cfail"))); - assert!(plan.iter().any(|s| s.name.contains("cfail"))); assert!(plan.iter().any(|s| s.name.contains("cfail-full"))); assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); assert!(plan.iter().any(|s| s.name.contains("debuginfo"))); @@ -1397,8 +1406,7 @@ mod tests { assert!(plan.iter().all(|s| s.host == "A")); assert!(plan.iter().all(|s| s.target == "C")); - assert!(plan.iter().any(|s| s.name.contains("-ui"))); - assert!(plan.iter().any(|s| s.name.contains("cfail"))); + assert!(!plan.iter().any(|s| s.name.contains("-ui"))); assert!(plan.iter().any(|s| s.name.contains("cfail"))); assert!(!plan.iter().any(|s| s.name.contains("cfail-full"))); assert!(plan.iter().any(|s| s.name.contains("codegen-units"))); diff --git a/src/doc/book/lang-items.md b/src/doc/book/lang-items.md index 6a08c1b6bb468..0d6a142ca4f72 100644 --- a/src/doc/book/lang-items.md +++ b/src/doc/book/lang-items.md @@ -16,15 +16,12 @@ and one for deallocation. A freestanding program that uses the `Box` sugar for dynamic allocations via `malloc` and `free`: ```rust,ignore -#![feature(lang_items, box_syntax, start, libc)] +#![feature(lang_items, box_syntax, start, libc, core_intrinsics)] #![no_std] +use core::intrinsics; extern crate libc; -extern { - fn abort() -> !; -} - #[lang = "owned_box"] pub struct Box(*mut T); @@ -34,7 +31,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { // Check if `malloc` failed: if p as usize == 0 { - abort(); + intrinsics::abort(); } p @@ -58,7 +55,7 @@ fn main(argc: isize, argv: *const *const u8) -> isize { } #[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { loop {} } +#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } } # #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} # #[no_mangle] pub extern fn rust_eh_register_frames () {} # #[no_mangle] pub extern fn rust_eh_unregister_frames () {} diff --git a/src/doc/book/no-stdlib.md b/src/doc/book/no-stdlib.md index a06de35c0ce69..79f0593be1780 100644 --- a/src/doc/book/no-stdlib.md +++ b/src/doc/book/no-stdlib.md @@ -37,9 +37,10 @@ The function marked `#[start]` is passed the command line parameters in the same format as C: ```rust,ignore -#![feature(lang_items)] +#![feature(lang_items, core_intrinsics)] #![feature(start)] #![no_std] +use core::intrinsics; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -69,7 +70,7 @@ pub extern fn rust_eh_unwind_resume() { pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, _line: u32) -> ! { - loop {} + unsafe { intrinsics::abort() } } ``` @@ -79,10 +80,11 @@ correct ABI and the correct name, which requires overriding the compiler's name mangling too: ```rust,ignore -#![feature(lang_items)] +#![feature(lang_items, core_intrinsics)] #![feature(start)] #![no_std] #![no_main] +use core::intrinsics; // Pull in the system libc library for what crt0.o likely requires. extern crate libc; @@ -112,7 +114,7 @@ pub extern fn rust_eh_unwind_resume() { pub extern fn rust_begin_panic(_msg: core::fmt::Arguments, _file: &'static str, _line: u32) -> ! { - loop {} + unsafe { intrinsics::abort() } } ``` diff --git a/src/doc/nomicon/coercions.md b/src/doc/nomicon/coercions.md index 6a9ebd6edf8fb..b699946cecaa2 100644 --- a/src/doc/nomicon/coercions.md +++ b/src/doc/nomicon/coercions.md @@ -17,6 +17,7 @@ Coercion is allowed between the following types: * `&T` to `*const T` * `&mut T` to `*mut T` * Unsizing: `T` to `U` if `T` implements `CoerceUnsized` +* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref`) `CoerceUnsized> for Pointer where T: Unsize` is implemented for all pointer types (including smart pointers like Box and Rc). Unsize is @@ -27,8 +28,9 @@ only implemented automatically, and enables the following transformations: * `Foo<..., T, ...>` => `Foo<..., U, ...>` where: * `T: Unsize` * `Foo` is a struct - * Only the last field of `Foo` has type `T` + * Only the last field of `Foo` has type involving `T` * `T` is not part of the type of any other fields + * `Bar: Unsize>`, if the last field of `Foo` has type `Bar` Coercions occur at a *coercion site*. Any location that is explicitly typed will cause a coercion to its type. If inference is necessary, the coercion will diff --git a/src/etc/unicode.py b/src/etc/unicode.py index bddc83f63d25d..e5389c112e811 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -23,10 +23,7 @@ # Since this should not require frequent updates, we just store this # out-of-line and check the unicode.rs file into git. -import fileinput, re, os, sys, operator - -bytes_old = 0 -bytes_new = 0 +import fileinput, re, os, sys, operator, math preamble = '''// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at @@ -362,7 +359,23 @@ def emit_trie_lookup_range_table(f): let leaf = r.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)]; trie_range_leaf(c, r.r6[leaf as usize]) } -}\n +} + +pub struct SmallBoolTrie { + r1: &'static [u8], // first level + r2: &'static [u64], // leaves +} + +impl SmallBoolTrie { + fn lookup(&self, c: char) -> bool { + let c = c as usize; + match self.r1.get(c >> 6) { + Some(&child) => trie_range_leaf(c, self.r2[child as usize]), + None => false, + } + } +} + """) def compute_trie(rawdata, chunksize): @@ -379,8 +392,6 @@ def compute_trie(rawdata, chunksize): return (root, child_data) def emit_bool_trie(f, name, t_data, is_pub=True): - global bytes_old, bytes_new - bytes_old += 8 * len(t_data) CHUNK = 64 rawdata = [False] * 0x110000 for (lo, hi) in t_data: @@ -433,15 +444,50 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write("\n ],\n") f.write(" };\n\n") - bytes_new += 256 + 992 + 256 + 8 * len(r3) + len(r5) + 8 * len(r6) + +def emit_small_bool_trie(f, name, t_data, is_pub=True): + last_chunk = max(int(hi / 64) for (lo, hi) in t_data) + n_chunks = last_chunk + 1 + chunks = [0] * n_chunks + for (lo, hi) in t_data: + for cp in range(lo, hi + 1): + if int(cp / 64) >= len(chunks): + print(cp, int(cp / 64), len(chunks), lo, hi) + chunks[int(cp / 64)] |= 1 << (cp & 63) + + pub_string = "" + if is_pub: + pub_string = "pub " + f.write(" %sconst %s: &'static super::SmallBoolTrie = &super::SmallBoolTrie {\n" + % (pub_string, name)) + + (r1, r2) = compute_trie(chunks, 1) + + f.write(" r1: &[\n") + data = ','.join(str(node) for node in r1) + format_table_content(f, data, 12) + f.write("\n ],\n") + + f.write(" r2: &[\n") + data = ','.join('0x%016x' % node for node in r2) + format_table_content(f, data, 12) + f.write("\n ],\n") + + f.write(" };\n\n") def emit_property_module(f, mod, tbl, emit): f.write("pub mod %s {\n" % mod) for cat in sorted(emit): - emit_bool_trie(f, "%s_table" % cat, tbl[cat]) - f.write(" pub fn %s(c: char) -> bool {\n" % cat) - f.write(" super::trie_lookup_range_table(c, %s_table)\n" % cat) - f.write(" }\n\n") + if cat in ["Cc", "White_Space", "Pattern_White_Space"]: + emit_small_bool_trie(f, "%s_table" % cat, tbl[cat]) + f.write(" pub fn %s(c: char) -> bool {\n" % cat) + f.write(" %s_table.lookup(c)\n" % cat) + f.write(" }\n\n") + else: + emit_bool_trie(f, "%s_table" % cat, tbl[cat]) + f.write(" pub fn %s(c: char) -> bool {\n" % cat) + f.write(" super::trie_lookup_range_table(c, %s_table)\n" % cat) + f.write(" }\n\n") f.write("}\n\n") def emit_conversions_module(f, to_upper, to_lower, to_title): @@ -543,4 +589,3 @@ def emit_norm_module(f, canon, compat, combine, norm_props): # normalizations and conversions module emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props) emit_conversions_module(rf, to_upper, to_lower, to_title) - #print 'bytes before = %d, bytes after = %d' % (bytes_old, bytes_new) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index e1a240a0d2eba..459dc94f33686 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -708,7 +708,7 @@ impl Arc { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Arc { +unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// Drops the `Arc`. /// /// This will decrement the strong reference count. If the strong reference @@ -736,7 +736,6 @@ impl Drop for Arc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` - #[unsafe_destructor_blind_to_params] #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index f9dfdc0e07536..c67106cf57aaf 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,7 +70,7 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![needs_allocator] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allocator)] #![feature(box_syntax)] @@ -79,9 +79,10 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(custom_attribute)] -#![feature(dropck_parametricity)] +#![feature(dropck_eyepatch)] #![cfg_attr(not(test), feature(exact_size_is_empty))] #![feature(fundamental)] +#![feature(generic_param_attrs)] #![feature(lang_items)] #![feature(needs_allocator)] #![feature(optin_builtin_traits)] diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index f23ea0ea8bf71..357a2724e0020 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -539,8 +539,7 @@ impl RawVec { } } -impl Drop for RawVec { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for RawVec { /// Frees the memory owned by the RawVec *without* trying to Drop its contents. fn drop(&mut self) { let elem_size = mem::size_of::(); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 86f8c746646aa..010e378ef2f48 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -644,7 +644,7 @@ impl Deref for Rc { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Rc { +unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// Drops the `Rc`. /// /// This will decrement the strong reference count. If the strong reference @@ -672,7 +672,6 @@ impl Drop for Rc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` - #[unsafe_destructor_blind_to_params] fn drop(&mut self) { unsafe { let ptr = *self.ptr; diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index f2df393ad777f..241f8149d24d2 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -16,7 +16,7 @@ reason = "this library is unlikely to be stabilized in its current \ form or name", issue = "27783")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allocator)] #![feature(libc)] #![feature(staged_api)] diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 5f0b637656b7d..de2b75f62b68a 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -12,7 +12,7 @@ #![crate_type = "rlib"] #![no_std] #![allocator] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![unstable(feature = "alloc_system", reason = "this library is unlikely to be stabilized in its current \ form or name", diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 174a93ed23e09..a3cfc15895eb7 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -26,14 +26,14 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(no_crate_inject, attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(core_intrinsics)] +#![feature(dropck_eyepatch)] #![feature(heap_api)] -#![feature(heap_api)] +#![feature(generic_param_attrs)] #![feature(staged_api)] -#![feature(dropck_parametricity)] #![cfg_attr(test, feature(test))] #![allow(deprecated)] @@ -258,8 +258,7 @@ impl TypedArena { } } -impl Drop for TypedArena { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for TypedArena { fn drop(&mut self) { unsafe { // Determine how much was filled. diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index c5d5ad27d2304..7d245f79f6998 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -153,8 +153,7 @@ use core::ops::{Deref, DerefMut}; use core::iter::{FromIterator, FusedIterator}; -use core::mem::swap; -use core::mem::size_of; +use core::mem::{swap, size_of}; use core::ptr; use core::fmt; @@ -226,12 +225,15 @@ pub struct BinaryHeap { #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub struct PeekMut<'a, T: 'a + Ord> { heap: &'a mut BinaryHeap, + sift: bool, } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] impl<'a, T: Ord> Drop for PeekMut<'a, T> { fn drop(&mut self) { - self.heap.sift_down(0); + if self.sift { + self.heap.sift_down(0); + } } } @@ -250,6 +252,16 @@ impl<'a, T: Ord> DerefMut for PeekMut<'a, T> { } } +impl<'a, T: Ord> PeekMut<'a, T> { + /// Removes the peeked value from the heap and returns it. + #[unstable(feature = "binary_heap_peek_mut_pop", issue = "38863")] + pub fn pop(mut this: PeekMut<'a, T>) -> T { + let value = this.heap.pop().unwrap(); + this.sift = false; + value + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for BinaryHeap { fn clone(&self) -> Self { @@ -385,7 +397,10 @@ impl BinaryHeap { if self.is_empty() { None } else { - Some(PeekMut { heap: self }) + Some(PeekMut { + heap: self, + sift: true, + }) } } diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 788236c24d063..98c71967f3c39 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -137,8 +137,7 @@ pub struct BTreeMap { } #[stable(feature = "btree_drop", since = "1.7.0")] -impl Drop for BTreeMap { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap { fn drop(&mut self) { unsafe { for _ in ptr::read(self).into_iter() { diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 883417e9f4ec7..834cc0c948dc7 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -366,11 +366,10 @@ //! These can all be interpreted as flags for a particular formatter. //! //! * `+` - This is intended for numeric types and indicates that the sign -//! should always be printed. Positive signs are never printed by -//! default, and the negative sign is only printed by default for the -//! `Signed` trait. This flag indicates that the correct sign (`+` or `-`) -//! should always be printed. -//! * `-` - Currently not used +//! (`+` or `-`) should always be printed. Positive signs are never +//! printed by default. This behavior is controlled by the +//! [`pad_integral`][pad_integral] method. +//! * `-` - Currently not used. //! * `#` - This flag is indicates that the "alternate" form of printing should //! be used. The alternate forms are: //! * `#?` - pretty-print the `Debug` formatting @@ -384,6 +383,8 @@ //! same format would yield `-0000001` for the integer `-1`. Notice that //! the negative version has one fewer zero than the positive version. //! +//! [pad_integral]: struct.Formatter.html#method.pad_integral +//! //! ## Width //! //! This is a parameter for the "minimum width" that the format should take up. diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index f9746f5694a49..561d8860dc880 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -27,7 +27,7 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![cfg_attr(test, allow(deprecated))] // rand -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(allow_internal_unstable)] @@ -35,10 +35,11 @@ #![feature(box_syntax)] #![cfg_attr(not(test), feature(char_escape_debug))] #![feature(core_intrinsics)] -#![feature(dropck_parametricity)] +#![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] #![feature(fused)] +#![feature(generic_param_attrs)] #![feature(heap_api)] #![feature(inclusive_range)] #![feature(lang_items)] diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs index 310855090885c..7f913d4afe476 100644 --- a/src/libcollections/linked_list.rs +++ b/src/libcollections/linked_list.rs @@ -726,8 +726,7 @@ impl LinkedList { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for LinkedList { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for LinkedList { fn drop(&mut self) { while let Some(_) = self.pop_front_node() {} } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index c399283babf26..27cf0268c99bb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -370,7 +370,8 @@ impl Vec { /// * `capacity` needs to be the capacity that the pointer was allocated with. /// /// Violating these may cause problems like corrupting the allocator's - /// internal datastructures. + /// internal datastructures. For example it is **not** safe + /// to build a `Vec` from a pointer to a C `char` array and a `size_t`. /// /// The ownership of `ptr` is effectively transferred to the /// `Vec` which may then deallocate, reallocate or change the @@ -1786,8 +1787,7 @@ impl Ord for Vec { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Vec { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for Vec { fn drop(&mut self) { unsafe { // use drop for [T] @@ -2056,8 +2056,7 @@ impl Clone for IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for IntoIter { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for IntoIter { fn drop(&mut self) { // destroy the remaining elements for _x in self.by_ref() {} diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 67621b860bf39..76e44c815793f 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -69,8 +69,7 @@ impl Clone for VecDeque { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for VecDeque { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T> Drop for VecDeque { fn drop(&mut self) { let (front, back) = self.as_mut_slices(); unsafe { @@ -1228,9 +1227,8 @@ impl VecDeque { self.pop_front() } - /// Inserts an element at `index` within the `VecDeque`. Whichever - /// end is closer to the insertion point will be moved to make room, - /// and all the affected elements will be moved to new positions. + /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices + /// greater than or equal to `index` towards the back. /// /// Element at index 0 is the front of the queue. /// @@ -1239,14 +1237,19 @@ impl VecDeque { /// Panics if `index` is greater than `VecDeque`'s length /// /// # Examples + /// /// ``` /// use std::collections::VecDeque; /// - /// let mut buf = VecDeque::new(); - /// buf.push_back(10); - /// buf.push_back(12); - /// buf.insert(1, 11); - /// assert_eq!(Some(&11), buf.get(1)); + /// let mut vec_deque = VecDeque::new(); + /// vec_deque.push_back('a'); + /// vec_deque.push_back('b'); + /// vec_deque.push_back('c'); + /// + /// vec_deque.insert(1, 'd'); + /// + /// let vec = vec_deque.into_iter().collect::>(); + /// assert_eq!(vec, ['a', 'd', 'b', 'c']); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn insert(&mut self, index: usize, value: T) { diff --git a/src/libcollectionstest/binary_heap.rs b/src/libcollectionstest/binary_heap.rs index 9cd63d8793184..1df341d1fc28a 100644 --- a/src/libcollectionstest/binary_heap.rs +++ b/src/libcollectionstest/binary_heap.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::collections::BinaryHeap; -use std::collections::binary_heap::Drain; +use std::collections::binary_heap::{Drain, PeekMut}; #[test] fn test_iterator() { @@ -94,6 +94,19 @@ fn test_peek_mut() { assert_eq!(heap.peek(), Some(&9)); } +#[test] +fn test_peek_mut_pop() { + let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; + let mut heap = BinaryHeap::from(data); + assert_eq!(heap.peek(), Some(&10)); + { + let mut top = heap.peek_mut().unwrap(); + *top -= 2; + assert_eq!(PeekMut::pop(top), 8); + } + assert_eq!(heap.peek(), Some(&9)); +} + #[test] fn test_push() { let mut heap = BinaryHeap::from(vec![2, 4, 9]); diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 05671e41ed33e..bec3965a9589b 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -11,6 +11,7 @@ #![deny(warnings)] #![feature(binary_heap_extras)] +#![feature(binary_heap_peek_mut_pop)] #![feature(box_syntax)] #![feature(btree_range)] #![feature(collection_placement)] diff --git a/src/libcompiler_builtins/build.rs b/src/libcompiler_builtins/build.rs index 44aa08e245873..6a766fc02df3e 100644 --- a/src/libcompiler_builtins/build.rs +++ b/src/libcompiler_builtins/build.rs @@ -192,14 +192,12 @@ fn main() { if !target.contains("ios") { sources.extend(&["absvti2.c", - "addtf3.c", "addvti3.c", "ashlti3.c", "ashrti3.c", "clzti2.c", "cmpti2.c", "ctzti2.c", - "divtf3.c", "divti3.c", "ffsti2.c", "fixdfti.c", @@ -216,17 +214,13 @@ fn main() { "floatuntixf.c", "lshrti3.c", "modti3.c", - "multf3.c", "multi3.c", "mulvti3.c", "negti2.c", "negvti2.c", "parityti2.c", "popcountti2.c", - "powitf2.c", - "subtf3.c", "subvti3.c", - "trampoline_setup.c", "ucmpti2.c", "udivmodti4.c", "udivti3.c", diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 2cb2f81fcffb5..35324f7b5968f 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -65,7 +65,7 @@ #![no_core] #![deny(missing_docs)] #![deny(missing_debug_implementations)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(allow_internal_unstable)] #![feature(asm)] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index ed01b93f1335a..798f1e6cbeb84 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -100,13 +100,26 @@ pub trait Sized { /// /// All implementations of `Unsize` are provided automatically by the compiler. /// +/// `Unsize` is implemented for: +/// +/// - `[T; N]` is `Unsize<[T]>` +/// - `T` is `Unsize` when `T: Trait` +/// - `Foo<..., T, ...>` is `Unsize>` if: +/// - `T: Unsize` +/// - Foo is a struct +/// - Only the last field of `Foo` has a type involving `T` +/// - `T` is not part of the type of any other fields +/// - `Bar: Unsize>`, if the last field of `Foo` has type `Bar` +/// /// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow /// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized -/// types. See the [DST coercion RFC][RFC982] for more details. +/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. /// /// [coerceunsized]: ../ops/trait.CoerceUnsized.html /// [rc]: ../../std/rc/struct.Rc.html /// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md + #[unstable(feature = "unsize", issue = "27732")] #[lang="unsize"] pub trait Unsize { diff --git a/src/libcore/num/i128.rs b/src/libcore/num/i128.rs index 6268271a1dcc5..04354e2e33f96 100644 --- a/src/libcore/num/i128.rs +++ b/src/libcore/num/i128.rs @@ -14,4 +14,4 @@ #![unstable(feature = "i128", issue="35118")] -int_module! { i128 } +int_module! { i128, #[unstable(feature = "i128", issue="35118")] } diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 630fac9d92f0f..04311d687ea92 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,13 +10,14 @@ #![doc(hidden)] -macro_rules! int_module { ($T:ident) => ( - -/// The smallest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MIN: $T = $T::min_value(); -/// The largest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MAX: $T = $T::max_value(); - -) } +macro_rules! int_module { + ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, $($attr: tt)*) => ( + /// The smallest value that can be represented by this integer type. + $($attr)* + pub const MIN: $T = $T::min_value(); + /// The largest value that can be represented by this integer type. + $($attr)* + pub const MAX: $T = $T::max_value(); + ) +} diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs index 77291f687255e..987ac3e000732 100644 --- a/src/libcore/num/u128.rs +++ b/src/libcore/num/u128.rs @@ -13,4 +13,4 @@ //! *[See also the `u128` primitive type](../../std/primitive.u128.html).* #![unstable(feature = "i128", issue="35118")] -uint_module! { u128 } +uint_module! { u128, #[unstable(feature = "i128", issue="35118")] } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index a3a2dc73e9c8e..2e59b39278ab6 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,13 +10,14 @@ #![doc(hidden)] -macro_rules! uint_module { ($T:ident) => ( - -/// The smallest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MIN: $T = $T::min_value(); -/// The largest value that can be represented by this integer type. -#[stable(feature = "rust1", since = "1.0.0")] -pub const MAX: $T = $T::max_value(); - -) } +macro_rules! uint_module { + ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); + ($T:ident, $($attr: tt)*) => ( + /// The smallest value that can be represented by this integer type. + $($attr)* + pub const MIN: $T = $T::min_value(); + /// The largest value that can be represented by this integer type. + $($attr)* + pub const MAX: $T = $T::max_value(); + ) +} diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 40d941a8b27e0..94df72f28fa9c 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -2710,6 +2710,35 @@ mod impls { /// Trait that indicates that this is a pointer or a wrapper for one, /// where unsizing can be performed on the pointee. +/// +/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce] +/// for more details. +/// +/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize` +/// by converting from a thin pointer to a fat pointer. +/// +/// For custom types, the coercion here works by coercing `Foo` to `Foo` +/// provided an impl of `CoerceUnsized> for Foo` exists. +/// Such an impl can only be written if `Foo` has only a single non-phantomdata +/// field involving `T`. If the type of that field is `Bar`, an implementation +/// of `CoerceUnsized> for Bar` must exist. The coercion will work by +/// by coercing the `Bar` field into `Bar` and filling in the rest of the fields +/// from `Foo` to create a `Foo`. This will effectively drill down to a pointer +/// field and coerce that. +/// +/// Generally, for smart pointers you will implement +/// `CoerceUnsized> for Ptr where T: Unsize, U: ?Sized`, with an +/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T` +/// like `Cell` and `RefCell`, you +/// can directly implement `CoerceUnsized> for Wrap where T: CoerceUnsized`. +/// This will let coercions of types like `Cell>` work. +/// +/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind +/// pointers. It is implemented automatically by the compiler. +/// +/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md +/// [unsize]: ../marker/trait.Unsize.html +/// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "coerce_unsized", issue = "27732")] #[lang="coerce_unsized"] pub trait CoerceUnsized { diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e3ca8eca76c57..bf5a59c45e4d3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -74,7 +74,10 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// /// # Safety /// -/// This is only unsafe because it accepts a raw pointer. +/// This function copies the memory through the raw pointers passed to it +/// as arguments. +/// +/// Ensure that these pointers are valid before calling `swap`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn swap(x: *mut T, y: *mut T) { diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index 3c608ef9c9268..8365e9db2a947 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -22,7 +22,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(libc)] #![feature(staged_api)] diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index b179a16e55e58..f5a687de64e48 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -23,7 +23,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(unicode)] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index 4d2f1b999a2ae..a5cd9fab2cf4b 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -90,6 +90,7 @@ test(attr(deny(warnings))))] #![deny(missing_docs)] +#![deny(warnings)] #![feature(staged_api)] use self::Name::*; @@ -968,7 +969,6 @@ fn test_split_within() { #[cfg(test)] mod tests { use super::*; - use super::Fail::*; use std::result::Result::{Err, Ok}; use std::result; diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 220051c9d35ea..8e587ad211de8 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -292,7 +292,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(allow(unused_variables), deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(str_escape)] diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 517cd016e8a35..057df647c7257 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -168,7 +168,7 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] #![deny(missing_docs)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 8f85bfe2c638e..348180a48dc38 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -21,7 +21,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index b75d9ec6520a4..90f4b364482e6 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -30,7 +30,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(alloc)] #![feature(core_intrinsics)] diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 22b365fa64f0e..93bc867462568 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -27,7 +27,7 @@ #![stable(feature = "proc_macro_lib", since = "1.15.0")] #![crate_type = "rlib"] #![crate_type = "dylib"] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![deny(missing_docs)] #![feature(rustc_private)] diff --git a/src/libproc_macro_plugin/lib.rs b/src/libproc_macro_plugin/lib.rs index c45762bfb6e71..0a7d352584872 100644 --- a/src/libproc_macro_plugin/lib.rs +++ b/src/libproc_macro_plugin/lib.rs @@ -80,7 +80,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(rustc_diagnostic_macros)] diff --git a/src/libproc_macro_tokens/lib.rs b/src/libproc_macro_tokens/lib.rs index 3bfa2fbb29fbd..0dd9aaab1c63a 100644 --- a/src/libproc_macro_tokens/lib.rs +++ b/src/libproc_macro_tokens/lib.rs @@ -52,7 +52,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(rustc_private)] diff --git a/src/librand/lib.rs b/src/librand/lib.rs index c31a0ed53207d..0cf70880d328b 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -23,7 +23,7 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![no_std] #![unstable(feature = "rand", reason = "use `rand` from crates.io", diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 4d66bba9f07ee..35afdd75cb8c4 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -18,6 +18,7 @@ use hir::{self, PatKind}; struct CFGBuilder<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, graph: CFGGraph, fn_exit: CFGIndex, loop_scopes: Vec, @@ -42,10 +43,23 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let fn_exit = graph.add_node(CFGNodeData::Exit); let body_exit; + // Find the function this expression is from. + let mut node_id = body.id; + loop { + let node = tcx.map.get(node_id); + if hir::map::blocks::FnLikeNode::from_node(node).is_some() { + break; + } + let parent = tcx.map.get_parent_node(node_id); + assert!(node_id != parent); + node_id = parent; + } + let mut cfg_builder = CFGBuilder { + tcx: tcx, + tables: tcx.item_tables(tcx.map.local_def_id(node_id)), graph: graph, fn_exit: fn_exit, - tcx: tcx, loop_scopes: Vec::new() }; body_exit = cfg_builder.expr(body, entry); @@ -310,11 +324,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprIndex(ref l, ref r) | - hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &l, Some(&**r).into_iter()) } - hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &e, None::.iter()) } @@ -368,9 +382,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &hir::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.tables().method_map.get(&method_call) { + let fn_ty = match self.tables.method_map.get(&method_call) { Some(method) => method.ty, - None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr) + None => self.tables.expr_ty_adjusted(func_or_rcvr) }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e261c699b6ac6..a68876b5ae9c0 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -113,6 +113,7 @@ pub enum DepNode { SizedConstraint(D), AssociatedItemDefIds(D), InherentImpls(D), + Tables(D), // The set of impls for a given trait. Ultimately, it would be // nice to get more fine-grained here (e.g., to include a @@ -162,6 +163,7 @@ impl DepNode { ItemSignature, AssociatedItemDefIds, InherentImpls, + Tables, TraitImpls, ReprHints, } @@ -230,6 +232,7 @@ impl DepNode { SizedConstraint(ref d) => op(d).map(SizedConstraint), AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), + Tables(ref d) => op(d).map(Tables), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), ReprHints(ref d) => op(d).map(ReprHints), diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 6e08b52f9a249..91e88e2c73ff8 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -45,15 +45,6 @@ pub struct FnLikeNode<'a> { node: map::Node<'a> } /// corresponds to some FnLikeNode. pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } -/// Components shared by fn-like things (fn items, methods, closures). -pub struct FnParts<'a> { - pub decl: &'a FnDecl, - pub body: ast::BodyId, - pub kind: FnKind<'a>, - pub span: Span, - pub id: NodeId, -} - impl MaybeFnLike for ast::Item { fn is_fn_like(&self) -> bool { match self.node { ast::ItemFn(..) => true, _ => false, } @@ -165,16 +156,6 @@ impl<'a> FnLikeNode<'a> { } } - pub fn to_fn_parts(self) -> FnParts<'a> { - FnParts { - decl: self.decl(), - body: self.body(), - kind: self.kind(), - span: self.span(), - id: self.id(), - } - } - pub fn body(self) -> ast::BodyId { self.handle(|i: ItemFnParts<'a>| i.body, |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a6ffe7cea5592..bd0ff695d093a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -23,10 +23,6 @@ pub struct NodeCollector<'ast> { pub(super) map: Vec>, /// The parent of this node pub parent_node: NodeId, - /// If true, completely ignore nested items. We set this when loading - /// HIR from metadata, since in that case we only want the HIR for - /// one specific item (and not the ones nested inside of it). - pub ignore_nested_items: bool } impl<'ast> NodeCollector<'ast> { @@ -35,30 +31,12 @@ impl<'ast> NodeCollector<'ast> { krate: krate, map: vec![], parent_node: CRATE_NODE_ID, - ignore_nested_items: false }; collector.insert_entry(CRATE_NODE_ID, RootCrate); collector } - pub(super) fn extend(krate: &'ast Crate, - parent: &'ast InlinedItem, - parent_node: NodeId, - map: Vec>) - -> NodeCollector<'ast> { - let mut collector = NodeCollector { - krate: krate, - map: map, - parent_node: parent_node, - ignore_nested_items: true - }; - - collector.insert_entry(parent_node, RootInlinedParent(parent)); - - collector - } - fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) { debug!("ast_map: {:?} => {:?}", id, entry); let len = self.map.len(); @@ -92,27 +70,19 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { fn visit_nested_item(&mut self, item: ItemId) { debug!("visit_nested_item: {:?}", item); - if !self.ignore_nested_items { - self.visit_item(self.krate.item(item.id)) - } + self.visit_item(self.krate.item(item.id)); } fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { - if !self.ignore_nested_items { - self.visit_trait_item(self.krate.trait_item(item_id)) - } + self.visit_trait_item(self.krate.trait_item(item_id)); } fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { - if !self.ignore_nested_items { - self.visit_impl_item(self.krate.impl_item(item_id)) - } + self.visit_impl_item(self.krate.impl_item(item_id)); } fn visit_nested_body(&mut self, id: BodyId) { - if !self.ignore_nested_items { - self.visit_body(self.krate.body(id)) - } + self.visit_body(self.krate.body(id)); } fn visit_item(&mut self, i: &'ast Item) { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 27ebeea9ad91d..7c0621279fd6f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -25,28 +25,18 @@ use syntax::codemap::Spanned; use syntax_pos::Span; use hir::*; -use hir::intravisit::Visitor; use hir::print::Nested; +use util::nodemap::DefIdMap; use arena::TypedArena; use std::cell::RefCell; use std::io; -use std::mem; pub mod blocks; mod collector; mod def_collector; pub mod definitions; -/// The data we save and restore about an inlined item or method. This is not -/// part of the AST that we parse from a file, but it becomes part of the tree -/// that we trans. -#[derive(Debug)] -struct InlinedItem { - def_id: DefId, - body: Body, -} - #[derive(Copy, Clone, Debug)] pub enum Node<'ast> { NodeItem(&'ast Item), @@ -99,7 +89,6 @@ enum MapEntry<'ast> { /// Roots for node trees. RootCrate, - RootInlinedParent(&'ast InlinedItem) } impl<'ast> Clone for MapEntry<'ast> { @@ -152,8 +141,7 @@ impl<'ast> MapEntry<'ast> { EntryVisibility(id, _) => id, NotPresent | - RootCrate | - RootInlinedParent(_) => return None, + RootCrate => return None, }) } @@ -225,7 +213,7 @@ impl<'ast> MapEntry<'ast> { pub struct Forest { krate: Crate, pub dep_graph: DepGraph, - inlined_items: TypedArena + inlined_bodies: TypedArena } impl Forest { @@ -233,7 +221,7 @@ impl Forest { Forest { krate: krate, dep_graph: dep_graph.clone(), - inlined_items: TypedArena::new() + inlined_bodies: TypedArena::new() } } @@ -263,20 +251,15 @@ pub struct Map<'ast> { /// /// Also, indexing is pretty quick when you've got a vector and /// plain old integers. - map: RefCell>>, + map: Vec>, definitions: Definitions, - /// All NodeIds that are numerically greater or equal to this value come - /// from inlined items. - local_node_id_watermark: NodeId, + /// Bodies inlined from other crates are cached here. + inlined_bodies: RefCell>, } impl<'ast> Map<'ast> { - pub fn is_inlined_node_id(&self, id: NodeId) -> bool { - id >= self.local_node_id_watermark - } - /// Registers a read in the dependency graph of the AST node with /// the given `id`. This needs to be called each time a public /// function returns the HIR for a node -- in other words, when it @@ -289,111 +272,71 @@ impl<'ast> Map<'ast> { } fn dep_node(&self, id0: NodeId) -> DepNode { - let map = self.map.borrow(); let mut id = id0; - if !self.is_inlined_node_id(id) { - let mut last_expr = None; - loop { - let entry = map[id.as_usize()]; - match entry { - EntryItem(..) | - EntryTraitItem(..) | - EntryImplItem(..) => { - if let Some(last_id) = last_expr { - // The body may have a separate dep node - if entry.is_body_owner(last_id) { - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); - } + let mut last_expr = None; + loop { + let entry = self.map[id.as_usize()]; + match entry { + EntryItem(..) | + EntryTraitItem(..) | + EntryImplItem(..) => { + if let Some(last_id) = last_expr { + // The body may have a separate dep node + if entry.is_body_owner(last_id) { + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } - return DepNode::Hir(self.local_def_id(id)); } + return DepNode::Hir(self.local_def_id(id)); + } - EntryVariant(p, v) => { - id = p; + EntryVariant(p, v) => { + id = p; - if last_expr.is_some() { - if v.node.disr_expr.map(|e| e.node_id) == last_expr { - // The enum parent holds both Hir and HirBody nodes. - let def_id = self.local_def_id(id); - return DepNode::HirBody(def_id); - } + if last_expr.is_some() { + if v.node.disr_expr.map(|e| e.node_id) == last_expr { + // The enum parent holds both Hir and HirBody nodes. + let def_id = self.local_def_id(id); + return DepNode::HirBody(def_id); } } + } - EntryForeignItem(p, _) | - EntryField(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - EntryExpr(p, _) => { - last_expr = Some(id); - id = p; - } - - RootCrate => { - return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); - } - - RootInlinedParent(_) => - bug!("node {} has inlined ancestor but is not inlined", id0), - - NotPresent => - // Some nodes, notably macro definitions, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - return self.opt_local_def_id(id) - .map(|def_id| DepNode::Hir(def_id)) - .unwrap_or_else(|| { - bug!("Walking parents from `{}` \ - led to `NotPresent` at `{}`", - id0, id) - }), + EntryForeignItem(p, _) | + EntryField(p, _) | + EntryStmt(p, _) | + EntryTy(p, _) | + EntryTraitRef(p, _) | + EntryLocal(p, _) | + EntryPat(p, _) | + EntryBlock(p, _) | + EntryStructCtor(p, _) | + EntryLifetime(p, _) | + EntryTyParam(p, _) | + EntryVisibility(p, _) => + id = p, + + EntryExpr(p, _) => { + last_expr = Some(id); + id = p; } - } - } else { - // reading from an inlined def-id is really a read out of - // the metadata from which we loaded the item. - loop { - match map[id.as_usize()] { - EntryItem(p, _) | - EntryForeignItem(p, _) | - EntryTraitItem(p, _) | - EntryImplItem(p, _) | - EntryVariant(p, _) | - EntryField(p, _) | - EntryExpr(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - RootInlinedParent(parent) => - return DepNode::MetaData(parent.def_id), - - RootCrate => - bug!("node {} has crate ancestor but is inlined", id0), - - NotPresent => - bug!("node {} is inlined but not present in map", id0), + + RootCrate => { + return DepNode::Hir(DefId::local(CRATE_DEF_INDEX)); } + + NotPresent => + // Some nodes, notably macro definitions, are not + // present in the map for whatever reason, but + // they *do* have def-ids. So if we encounter an + // empty hole, check for that case. + return self.opt_local_def_id(id) + .map(|def_id| DepNode::Hir(def_id)) + .unwrap_or_else(|| { + bug!("Walking parents from `{}` \ + led to `NotPresent` at `{}`", + id0, id) + }), } } } @@ -442,11 +385,11 @@ impl<'ast> Map<'ast> { } fn entry_count(&self) -> usize { - self.map.borrow().len() + self.map.len() } fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id.as_usize()).cloned() + self.map.get(id.as_usize()).cloned() } pub fn krate(&self) -> &'ast Crate { @@ -483,7 +426,7 @@ impl<'ast> Map<'ast> { /// for embedded constant expressions (e.g. `N` in `[T; N]`). pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { let parent = self.get_parent_node(node_id); - if self.map.borrow()[parent.as_usize()].is_body_owner(node_id) { + if self.map[parent.as_usize()].is_body_owner(node_id) { parent } else { node_id @@ -644,11 +587,7 @@ impl<'ast> Map<'ast> { } pub fn get_parent_did(&self, id: NodeId) -> DefId { - let parent = self.get_parent(id); - match self.find_entry(parent) { - Some(RootInlinedParent(ii)) => ii.def_id, - _ => self.local_def_id(parent) - } + self.local_def_id(self.get_parent(id)) } pub fn get_foreign_abi(&self, id: NodeId) -> Abi { @@ -660,8 +599,6 @@ impl<'ast> Map<'ast> { _ => None } } - /// Wrong but OK, because the only inlined foreign items are intrinsics. - Some(RootInlinedParent(_)) => Some(Abi::RustIntrinsic), _ => None }; match abi { @@ -737,11 +674,17 @@ impl<'ast> Map<'ast> { } } - pub fn expect_inlined_body(&self, id: NodeId) -> &'ast Body { - match self.find_entry(id) { - Some(RootInlinedParent(inlined_item)) => &inlined_item.body, - _ => bug!("expected inlined item, found {}", self.node_to_string(id)), - } + pub fn get_inlined_body(&self, def_id: DefId) -> Option<&'ast Body> { + self.inlined_bodies.borrow().get(&def_id).map(|&body| { + self.dep_graph.read(DepNode::MetaData(def_id)); + body + }) + } + + pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'ast Body { + let body = self.forest.inlined_bodies.alloc(body); + self.inlined_bodies.borrow_mut().insert(def_id, body); + body } /// Returns the name associated with the given NodeId's AST. @@ -824,7 +767,6 @@ impl<'ast> Map<'ast> { Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), Some(RootCrate) => self.forest.krate.span, - Some(RootInlinedParent(parent)) => parent.body.value.span, Some(NotPresent) | None => { bug!("hir::map::Map::span: id not in map: {:?}", id) } @@ -973,41 +915,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest, entries, vector_length, (entries as f64 / vector_length as f64) * 100.); } - let local_node_id_watermark = NodeId::new(map.len()); - Map { forest: forest, dep_graph: forest.dep_graph.clone(), - map: RefCell::new(map), + map: map, definitions: definitions, - local_node_id_watermark: local_node_id_watermark, + inlined_bodies: RefCell::new(DefIdMap()), } } -/// Used for bodies loaded from external crate that are being inlined into this -/// crate. -pub fn map_decoded_body<'ast>(map: &Map<'ast>, - def_id: DefId, - body: Body, - parent_id: NodeId) - -> &'ast Body { - let _ignore = map.forest.dep_graph.in_ignore(); - - let ii = map.forest.inlined_items.alloc(InlinedItem { - def_id: def_id, - body: body - }); - - let mut collector = NodeCollector::extend(map.krate(), - ii, - parent_id, - mem::replace(&mut *map.map.borrow_mut(), vec![])); - collector.visit_body(&ii.body); - *map.map.borrow_mut() = collector.map; - - &ii.body -} - /// Identical to the `PpAnn` implementation for `hir::Crate`, /// except it avoids creating a dependency on the whole crate. impl<'ast> print::PpAnn for Map<'ast> { diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 18fa6836b5108..c06c53810d753 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1210,6 +1210,7 @@ impl<'a> State<'a> { pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> { self.maybe_print_comment(expr.span.lo)?; + self.print_outer_attributes(&expr.attrs)?; self.ibox(indent_unit)?; self.ann.pre(self, NodeExpr(expr))?; match expr.node { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7b6ed56b779fd..b44e1563ee7ed 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -27,7 +27,6 @@ use middle::region::CodeExtent; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; -use ty::adjustment; use ty::{TyVid, IntVid, FloatVid}; use ty::{self, Ty, TyCtxt}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -37,10 +36,11 @@ use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; +use std::ops::Deref; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; -use util::nodemap::{FxHashMap, FxHashSet, NodeMap}; +use util::nodemap::{FxHashMap, FxHashSet}; use arena::DroplessArena; use self::combine::CombineFields; @@ -76,28 +76,63 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A version of &ty::Tables which can be global or local. -/// Only the local version supports borrow_mut. +/// A version of &ty::Tables which can be `Missing` (not needed), +/// `InProgress` (during typeck) or `Interned` (result of typeck). +/// Only the `InProgress` version supports `borrow_mut`. #[derive(Copy, Clone)] pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Global(&'a RefCell>), - Local(&'a RefCell>) + Interned(&'a ty::Tables<'gcx>), + InProgress(&'a RefCell>), + Missing +} + +pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + Interned(&'a ty::Tables<'gcx>), + InProgress(Ref<'a, ty::Tables<'tcx>>) +} + +impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> { + type Target = ty::Tables<'tcx>; + fn deref(&self) -> &Self::Target { + match *self { + InferTablesRef::Interned(tables) => tables, + InferTablesRef::InProgress(ref tables) => tables + } + } } impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { - pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> { + pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> { match self { - InferTables::Global(tables) => tables.borrow(), - InferTables::Local(tables) => tables.borrow() + InferTables::Interned(tables) => InferTablesRef::Interned(tables), + InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow() with no tables") + } + } + } + + pub fn expect_interned(self) -> &'a ty::Tables<'gcx> { + match self { + InferTables::Interned(tables) => tables, + InferTables::InProgress(_) => { + bug!("InferTables: infcx.tables.expect_interned() during type-checking"); + } + InferTables::Missing => { + bug!("InferTables: infcx.tables.expect_interned() with no tables") + } } } pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> { match self { - InferTables::Global(_) => { + InferTables::Interned(_) => { bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); } - InferTables::Local(tables) => tables.borrow_mut() + InferTables::InProgress(tables) => tables.borrow_mut(), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow_mut() with no tables") + } } } } @@ -370,27 +405,84 @@ impl fmt::Display for FixupError { } } +pub trait InferEnv<'a, 'tcx> { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>); +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, None, None) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, None, Some(self)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::Tables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (Some(self.0), None, Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::Tables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, Some(self.0), Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + let item_id = tcx.map.body_owner(self); + (Some(tcx.item_tables(tcx.map.local_def_id(item_id))), + None, + Some(ty::ParameterEnvironment::for_item(tcx, item_id))) + } +} + /// Helper type of a temporary returned by tcx.infer_ctxt(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: DroplessArena, - tables: Option>>, + fresh_tables: Option>>, + tables: Option<&'a ty::Tables<'gcx>>, param_env: Option>, projection_mode: Reveal, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt(self, - tables: Option>, - param_env: Option>, - projection_mode: Reveal) - -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn infer_ctxt>(self, + env: E, + projection_mode: Reveal) + -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + let (tables, fresh_tables, param_env) = env.to_parts(self); InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - tables: tables.map(RefCell::new), + fresh_tables: fresh_tables.map(RefCell::new), + tables: tables, param_env: param_env, projection_mode: projection_mode, } @@ -399,16 +491,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck /// for MemCategorizationContext/ExprUseVisitor. /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>) + pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId) -> InferCtxt<'a, 'gcx, 'gcx> { + let (tables, _, param_env) = body.to_parts(self); InferCtxt { tcx: self, - tables: InferTables::Global(&self.tables), + tables: InferTables::Interned(tables.unwrap()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), region_vars: RegionVarBindings::new(self), - parameter_environment: param_env, + parameter_environment: param_env.unwrap(), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), projection_cache: RefCell::new(traits::ProjectionCache::new()), @@ -428,15 +521,14 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { let InferCtxtBuilder { global_tcx, ref arena, - ref tables, + ref fresh_tables, + tables, ref mut param_env, projection_mode, } = *self; - let tables = if let Some(ref tables) = *tables { - InferTables::Local(tables) - } else { - InferTables::Global(&global_tcx.tables) - }; + let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { + fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) + }); let param_env = param_env.take().unwrap_or_else(|| { global_tcx.empty_parameter_environment() }); @@ -555,7 +647,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + self.infer_ctxt((), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -573,7 +665,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| { + self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -1490,8 +1582,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. let local_closures = match self.tables { - InferTables::Local(_) => ty.has_closure_types(), - InferTables::Global(_) => false + InferTables::InProgress(_) => ty.has_closure_types(), + _ => false }; if !local_closures { return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span); @@ -1526,15 +1618,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|method| method.def_id) } - pub fn adjustments(&self) -> Ref>> { - fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.adjustments - } - - Ref::map(self.tables.borrow(), project_adjustments) - } - pub fn is_method_call(&self, id: ast::NodeId) -> bool { self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) } @@ -1555,15 +1638,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> Option { - if def_id.is_local() { - self.tables.borrow().closure_kinds.get(&def_id).cloned() - } else { - // During typeck, ALL closures are local. But afterwards, - // during trans, we see closure ids from other traits. - // That may require loading the closure data out of the - // cstore. - Some(self.tcx.closure_kind(def_id)) + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + return tables.borrow().closure_kinds.get(&id).cloned(); + } } + + // During typeck, ALL closures are local. But afterwards, + // during trans, we see closure ids from other traits. + // That may require loading the closure data out of the + // cstore. + Some(self.tcx.closure_kind(def_id)) } pub fn closure_type(&self, @@ -1571,14 +1656,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::ClosureTy<'tcx> { - if let InferTables::Local(tables) = self.tables { - if let Some(ty) = tables.borrow().closure_tys.get(&def_id) { - return ty.subst(self.tcx, substs.substs); + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(ty) = tables.borrow().closure_tys.get(&id) { + return ty.subst(self.tcx, substs.substs); + } } } - let closure_ty = self.tcx.closure_type(def_id, substs); - closure_ty + self.tcx.closure_type(def_id, substs) } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 73ec9d8f8c880..151d7cd17ab14 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(box_patterns)] diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index cce79820ca8da..cfe5cc1739a7c 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -27,7 +27,7 @@ use self::TargetLint::*; use dep_graph::DepNode; use middle::privacy::AccessLevels; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use session::{config, early_error, Session}; use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; use lint::{EarlyLintPassObject, LateLintPassObject}; @@ -39,8 +39,10 @@ use std::cmp; use std::default::Default as StdDefault; use std::mem; use std::fmt; +use std::ops::Deref; use syntax::attr; use syntax::ast; +use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; use errors::{self, Diagnostic, DiagnosticBuilder}; use hir; @@ -298,8 +300,9 @@ impl LintStore { check_lint_name_cmdline(sess, self, &lint_name[..], level); + let lint_flag_val = Symbol::intern(&lint_name); match self.find_lint(&lint_name[..], sess, None) { - Ok(lint_id) => self.set_level(lint_id, (level, CommandLine)), + Ok(lint_id) => self.set_level(lint_id, (level, CommandLine(lint_flag_val))), Err(FindLintError::Removed) => { } Err(_) => { match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone())) @@ -309,7 +312,7 @@ impl LintStore { Some(v) => { v.iter() .map(|lint_id: &LintId| - self.set_level(*lint_id, (level, CommandLine))) + self.set_level(*lint_id, (level, CommandLine(lint_flag_val)))) .collect::>(); } None => { @@ -336,6 +339,9 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + /// Side-tables for the body we are in. + pub tables: &'a ty::Tables<'tcx>, + /// The crate being checked. pub krate: &'a hir::Crate, @@ -442,35 +448,18 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, -> DiagnosticBuilder<'a> where S: Into { - let (mut level, source) = lvlsrc; + let (level, source) = lvlsrc; if level == Allow { return sess.diagnostic().struct_dummy(); } let name = lint.name_lower(); let mut def = None; - let msg = match source { - Default => { - format!("{}, #[{}({})] on by default", msg, - level.as_str(), name) - }, - CommandLine => { - format!("{} [-{} {}]", msg, - match level { - Warn => 'W', Deny => 'D', Forbid => 'F', - Allow => bug!() - }, name.replace("_", "-")) - }, - Node(src) => { - def = Some(src); - msg.to_string() - } - }; - // For purposes of printing, we can treat forbid as deny. - if level == Forbid { level = Deny; } + // Except for possible note details, forbid behaves like deny. + let effective_level = if level == Forbid { Deny } else { level }; - let mut err = match (level, span) { + let mut err = match (effective_level, span) { (Warn, Some(sp)) => sess.struct_span_warn(sp, &msg[..]), (Warn, None) => sess.struct_warn(&msg[..]), (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]), @@ -478,6 +467,35 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, _ => bug!("impossible level in raw_emit_lint"), }; + match source { + Default => { + err.note(&format!("#[{}({})] on by default", level.as_str(), name)); + }, + CommandLine(lint_flag_val) => { + let flag = match level { + Warn => "-W", Deny => "-D", Forbid => "-F", + Allow => bug!("earlier conditional return should handle Allow case") + }; + let hyphen_case_lint_name = name.replace("_", "-"); + if lint_flag_val.as_str().deref() == name { + err.note(&format!("requested on the command line with `{} {}`", + flag, hyphen_case_lint_name)); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + err.note(&format!("`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val)); + } + }, + Node(lint_attr_name, src) => { + def = Some(src); + if lint_attr_name.as_str().deref() != name { + let level_str = level.as_str(); + err.note(&format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); + } + } + } + // Check for future incompatibility lints and issue a stronger warning. if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) { let explanation = format!("this was previously accepted by the compiler \ @@ -645,6 +663,8 @@ pub trait LintContext<'tcx>: Sized { } }; + let lint_attr_name = result.expect("lint attribute should be well-formed").0; + for (lint_id, level, span) in v { let (now, now_source) = self.lints().get_level_source(lint_id); if now == Forbid && level != Forbid { @@ -656,11 +676,11 @@ pub trait LintContext<'tcx>: Sized { diag_builder.span_label(span, &format!("overruled by previous forbid")); match now_source { LintSource::Default => &mut diag_builder, - LintSource::Node(forbid_source_span) => { + LintSource::Node(_, forbid_source_span) => { diag_builder.span_label(forbid_source_span, &format!("`forbid` level set here")) }, - LintSource::CommandLine => { + LintSource::CommandLine(_) => { diag_builder.note("`forbid` lint level was set on command line") } }.emit() @@ -668,7 +688,7 @@ pub trait LintContext<'tcx>: Sized { let src = self.lints().get_level_source(lint_id).1; self.level_stack().push((lint_id, (now, src))); pushed += 1; - self.mut_lints().set_level(lint_id, (level, Node(span))); + self.mut_lints().set_level(lint_id, (level, Node(lint_attr_name, span))); } } } @@ -703,22 +723,6 @@ impl<'a> EarlyContext<'a> { } impl<'a, 'tcx> LateContext<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - krate: &'a hir::Crate, - access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> { - // We want to own the lint store, so move it out of the session. - let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), - LintStore::new()); - - LateContext { - tcx: tcx, - krate: krate, - access_levels: access_levels, - lints: lint_store, - level_stack: vec![], - } - } - fn visit_ids<'b, F: 'b>(&'b mut self, f: F) where F: FnOnce(&mut IdVisitor<'b, 'a, 'tcx>) { @@ -795,6 +799,14 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::NestedVisitorMap::All(&self.tcx.map) } + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; + } + fn visit_item(&mut self, it: &'tcx hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, late_passes, it); @@ -837,10 +849,15 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, body_id: hir::BodyId, span: Span, id: ast::NodeId) { + // Wrap in tables here, not just in visit_nested_body, + // in order for `check_fn` to be able to use them. + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body_id); let body = self.tcx.map.body(body_id); run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); + self.tables = old_tables; } fn visit_variant_data(&mut self, @@ -1238,7 +1255,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); let krate = tcx.map.krate(); - let mut cx = LateContext::new(tcx, krate, access_levels); + + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), LintStore::new()); + let mut cx = LateContext { + tcx: tcx, + tables: &ty::Tables::empty(), + krate: krate, + access_levels: access_levels, + lints: lint_store, + level_stack: vec![], + }; // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 7e0da00694c4a..c0a44261cec09 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -37,6 +37,7 @@ use syntax_pos::Span; use hir::intravisit::FnKind; use syntax::visit as ast_visit; use syntax::ast; +use syntax::symbol::Symbol; use hir; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, @@ -336,10 +337,10 @@ pub enum LintSource { Default, /// Lint level was set by an attribute. - Node(Span), + Node(ast::Name, Span), /// Lint level was set by a command-line flag. - CommandLine, + CommandLine(Symbol), } pub type LevelSource = (Level, LintSource); diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 9677082a43a3c..f583f601726ed 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -15,6 +15,8 @@ use hir::def_id::DefId; use rustc_const_math::*; use self::ConstVal::*; +use std::collections::BTreeMap; + #[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] pub enum ConstVal { Float(ConstFloat), @@ -22,16 +24,12 @@ pub enum ConstVal { Str(InternedString), ByteStr(Rc>), Bool(bool), - Struct(ast::NodeId), - Tuple(ast::NodeId), Function(DefId), - Array(ast::NodeId, u64), - Repeat(ast::NodeId, u64), + Struct(BTreeMap), + Tuple(Vec), + Array(Vec), + Repeat(Box, u64), Char(char), - /// A value that only occurs in case `eval_const_expr` reported an error. You should never - /// handle this case. Its sole purpose is to allow more errors to be reported instead of - /// causing a fatal error. - Dummy, } impl ConstVal { @@ -48,7 +46,6 @@ impl ConstVal { Array(..) => "array", Repeat(..) => "repeat", Char(..) => "char", - Dummy => "dummy value", } } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 00e21410c7077..5af62d0172f5c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -49,6 +49,7 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct MarkSymbolVisitor<'a, 'tcx: 'a> { worklist: Vec, tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, live_symbols: Box>, struct_has_extern_repr: bool, ignore_non_const_paths: bool, @@ -57,19 +58,6 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - worklist: Vec) -> MarkSymbolVisitor<'a, 'tcx> { - MarkSymbolVisitor { - worklist: worklist, - tcx: tcx, - live_symbols: box FxHashSet(), - struct_has_extern_repr: false, - ignore_non_const_paths: false, - inherited_pub_visibility: false, - ignore_variant_stack: vec![], - } - } - fn check_def_id(&mut self, def_id: DefId) { if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { if should_explore(self.tcx, node_id) { @@ -109,12 +97,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - let method = self.tcx.tables().method_map[&method_call]; + let method = self.tables.method_map[&method_call]; self.check_def_id(method.def_id); } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().field_named(name).did); } @@ -123,7 +111,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().fields[idx].did); } @@ -134,7 +122,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def, pats: &[codemap::Spanned]) { - let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty { + let variant = match self.tables.node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => adt.variant_of_def(def), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; @@ -209,7 +197,15 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name, @@ -227,7 +223,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.handle_definition(def); } hir::ExprMethodCall(..) => { @@ -267,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_pattern_match(pat, path.def, fields); } PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); self.handle_definition(def); } _ => () @@ -393,7 +389,16 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: &hir::Crate) -> Box> { let worklist = create_and_seed_worklist(tcx, access_levels, krate); - let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist); + let mut symbol_visitor = MarkSymbolVisitor { + worklist: worklist, + tcx: tcx, + tables: &ty::Tables::empty(), + live_symbols: box FxHashSet(), + struct_has_extern_repr: false, + ignore_non_const_paths: false, + inherited_pub_visibility: false, + ignore_variant_stack: vec![], + }; symbol_visitor.mark_live_symbols(); symbol_visitor.live_symbols } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 38b0b18b0129a..c42e8fcb08ced 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -52,6 +52,7 @@ fn type_is_unsafe_function(ty: Ty) -> bool { struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, @@ -94,7 +95,15 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, @@ -163,7 +172,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables().method_map[&method_call].ty; + let base_type = self.tables.method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -172,7 +181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprCall(ref base, _) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -180,7 +189,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: unary case, base type is {:?}", base_type); if let ty::TyRawPtr(_) = base_type.sty { @@ -204,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty { + if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty { if adt.is_union() { self.require_unsafe(field.span, "access to union field"); } @@ -218,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { + if let ty::TyAdt(adt, ..) = self.tables.pat_ty(pat).sty { if adt.is_union() { for field in fields { self.require_unsafe(field.span, "matching on union field"); @@ -236,6 +245,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = EffectCheckVisitor { tcx: tcx, + tables: &ty::Tables::empty(), unsafe_context: UnsafeContext::new(SafeContext), }; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a3a49c916338e..0eacbba3fdd44 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_adjustment(&mut self, expr: &hir::Expr) { let infcx = self.mc.infcx; //NOTE(@jroesch): mixed RefCell borrow causes crash - let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); + let adj = infcx.tables.borrow().adjustments.get(&expr.id).map(|x| x.clone()); if let Some(adjustment) = adj { match adjustment.kind { adjustment::Adjust::NeverToAny | @@ -989,7 +989,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = tcx.tables().qpath_def(qpath, pat.id); + let def = infcx.tables.borrow().qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index d932061d42d3d..d42b866d47209 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -19,7 +19,7 @@ use ty::layout::{LayoutError, Pointer, SizeSkeleton}; use syntax::abi::Abi::RustIntrinsic; use syntax::ast; use syntax_pos::Span; -use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -33,18 +33,6 @@ struct ItemVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { - fn visit_const(&mut self, item_id: ast::NodeId, body: hir::BodyId) { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_nested_body(body); - }); - } -} - struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx> } @@ -118,64 +106,36 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } - // const, static and N in [T; N]. - fn visit_body(&mut self, body: &'tcx hir::Body) { - self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + let body = self.tcx.map.body(body_id); + self.tcx.infer_ctxt(body_id, Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; visitor.visit_body(body); }); - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::TraitItemKind::Const(_, Some(body)) = item.node { - self.visit_const(item.id, body); - } else { - intravisit::walk_trait_item(self, item); - } - } - - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, body) = item.node { - self.visit_const(item.id, body); - } else { - intravisit::walk_impl_item(self, item); - } - } - - fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::BodyId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "intrinsicck: closure outside of function") - } - let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_fn(fk, fd, b, s, id); - }); + self.visit_body(body); } } impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.infcx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, expr: &'gcx hir::Expr) { let def = if let hir::ExprPath(ref qpath) = expr.node { - self.infcx.tcx.tables().qpath_def(qpath, expr.id) + self.infcx.tables.borrow().qpath_def(qpath, expr.id) } else { Def::Err }; match def { Def::Fn(did) if self.def_id_is_transmute(did) => { - let typ = self.infcx.tcx.tables().node_id_to_type(expr.id); + let typ = self.infcx.tables.borrow().node_id_to_type(expr.id); + let typ = self.infcx.tcx.lift_to_global(&typ).unwrap(); match typ.sty { ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { let from = bare_fn_ty.sig.skip_binder().inputs()[0]; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 745a94a5ddba3..5307b4ec77452 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -351,22 +351,6 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_local(&mut self, l: &'tcx hir::Local) { - check_local(self, l); - } - fn visit_expr(&mut self, ex: &'tcx Expr) { - check_expr(self, ex); - } - fn visit_arm(&mut self, a: &'tcx hir::Arm) { - check_arm(self, a); - } -} - fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, @@ -394,24 +378,13 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // and so forth: intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); - // Special nodes and variables: - // - exit_ln represents the end of the fn, either by return or panic - // - implicit_ret_var is a pseudo-variable that represents - // an implicit return - let specials = Specials { - exit_ln: fn_maps.add_live_node(ExitNode), - fallthrough_ln: fn_maps.add_live_node(ExitNode), - no_ret_var: fn_maps.add_variable(ImplicitRet), - clean_exit_var: fn_maps.add_variable(CleanExit) - }; - // compute liveness - let mut lsets = Liveness::new(&mut fn_maps, specials); + let mut lsets = Liveness::new(&mut fn_maps, body_id); let entry_ln = lsets.compute(&body.value); // check for various error conditions lsets.visit_body(body); - lsets.check_ret(id, sp, fk, entry_ln, body); + lsets.check_ret(id, sp, entry_ln, body); lsets.warn_about_unused_args(body, entry_ln); } @@ -539,6 +512,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx: 'a> { ir: &'a mut IrMaps<'a, 'tcx>, + tables: &'a ty::Tables<'tcx>, s: Specials, successors: Vec, users: Vec, @@ -553,11 +527,26 @@ struct Liveness<'a, 'tcx: 'a> { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn new(ir: &'a mut IrMaps<'a, 'tcx>, specials: Specials) -> Liveness<'a, 'tcx> { + fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { + // Special nodes and variables: + // - exit_ln represents the end of the fn, either by return or panic + // - implicit_ret_var is a pseudo-variable that represents + // an implicit return + let specials = Specials { + exit_ln: ir.add_live_node(ExitNode), + fallthrough_ln: ir.add_live_node(ExitNode), + no_ret_var: ir.add_variable(ImplicitRet), + clean_exit_var: ir.add_variable(CleanExit) + }; + + let tables = ir.tcx.body_tables(body); + let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; + Liveness { ir: ir, + tables: tables, s: specials, successors: vec![invalid_node(); num_live_nodes], users: vec![invalid_users(); num_live_nodes * num_vars], @@ -1065,7 +1054,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAssignOp(_, ref l, ref r) => { // an overloaded assign op is like a method call - if self.ir.tcx.tables().is_method_call(expr.id) { + if self.tables.is_method_call(expr.id) { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { @@ -1092,8 +1081,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited - let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && - self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never(); + let diverges = !self.tables.is_method_call(expr.id) && + self.tables.expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln } else { @@ -1105,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprMethodCall(.., ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables().method_map[&method_call].ty; + let method_ty = self.tables.method_map[&method_call].ty; // FIXME(canndrew): This is_never should really be an is_uninhabited let succ = if method_ty.fn_ret().0.is_never() { self.s.exit_ln @@ -1355,6 +1344,22 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // _______________________________________________________________________ // Checking for error conditions +impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_local(&mut self, l: &'tcx hir::Local) { + check_local(self, l); + } + fn visit_expr(&mut self, ex: &'tcx Expr) { + check_expr(self, ex); + } + fn visit_arm(&mut self, a: &'tcx hir::Arm) { + check_arm(self, a); + } +} + fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { match local.init { Some(_) => { @@ -1389,7 +1394,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } hir::ExprAssignOp(_, ref l, _) => { - if !this.ir.tcx.tables().is_method_call(expr.id) { + if !this.tables.is_method_call(expr.id) { this.check_lvalue(&l); } @@ -1432,15 +1437,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_ret(&self, id: NodeId, sp: Span, - fk: FnKind, entry_ln: LiveNode, body: &hir::Body) { - let fn_ty = if let FnKind::Closure(_) = fk { - self.ir.tcx.tables().node_id_to_type(id) - } else { - self.ir.tcx.item_type(self.ir.tcx.map.local_def_id(id)) - }; + let fn_ty = self.ir.tcx.item_type(self.ir.tcx.map.local_def_id(id)); let fn_ret = match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), @@ -1457,8 +1457,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); - let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), - Reveal::All).enter(|infcx| { + let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| { let cause = traits::ObligationCause::dummy(); traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil() }); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 2d88567b8b873..92e69d7d72957 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.adjustments().get(&expr.id) { + match self.infcx.tables.borrow().adjustments.get(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 765d93742d8fb..6eaf3448d0284 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -79,6 +79,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct ReachableContext<'a, 'tcx: 'a> { // The type context. tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, // The set of items which must be exported in the linkage sense. reachable_symbols: NodeSet, // A worklist of item IDs. Each item ID in this worklist will be inlined @@ -90,17 +91,25 @@ struct ReachableContext<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = match expr.node { hir::ExprPath(ref qpath) => { - Some(self.tcx.tables().qpath_def(qpath, expr.id)) + Some(self.tables.qpath_def(qpath, expr.id)) } hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let def_id = self.tables.method_map[&method_call].def_id; Some(Def::Method(def_id)) } _ => None @@ -135,20 +144,6 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } impl<'a, 'tcx> ReachableContext<'a, 'tcx> { - // Creates a new reachability computation context. - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> { - let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { - *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || - *ty == config::CrateTypeProcMacro - }); - ReachableContext { - tcx: tcx, - reachable_symbols: NodeSet(), - worklist: Vec::new(), - any_library: any_library, - } - } - // Returns true if the given def ID represents a local item that is // eligible for inlining and false otherwise. fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { @@ -369,7 +364,17 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> NodeSet { let _task = tcx.dep_graph.in_task(DepNode::Reachability); - let mut reachable_context = ReachableContext::new(tcx); + let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { + *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || + *ty == config::CrateTypeProcMacro + }); + let mut reachable_context = ReachableContext { + tcx: tcx, + tables: &ty::Tables::empty(), + reachable_symbols: NodeSet(), + worklist: Vec::new(), + any_library: any_library, + }; // Step 1: Seed the worklist with all nodes which were found to be public as // a result of the privacy pass along with all local lang items and impl items. diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1d0e95245ea2d..5bae0e347f7c4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -29,7 +29,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::{iter, u32}; use std::ops::{Index, IndexMut}; use std::vec::IntoIter; -use syntax::ast::{self, Name}; +use syntax::ast::Name; use syntax_pos::Span; mod cache; @@ -1271,17 +1271,12 @@ fn fmt_const_val(fmt: &mut W, const_val: &ConstVal) -> fmt::Result { } Bool(b) => write!(fmt, "{:?}", b), Function(def_id) => write!(fmt, "{}", item_path_str(def_id)), - Struct(node_id) | Tuple(node_id) | Array(node_id, _) | Repeat(node_id, _) => - write!(fmt, "{}", node_to_string(node_id)), + Struct(_) | Tuple(_) | Array(_) | Repeat(..) => + bug!("ConstVal `{:?}` should not be in MIR", const_val), Char(c) => write!(fmt, "{:?}", c), - Dummy => bug!(), } } -fn node_to_string(node_id: ast::NodeId) -> String { - ty::tls::with(|tcx| tcx.map.node_to_user_string(node_id)) -} - fn item_path_str(def_id: DefId) -> String { ty::tls::with(|tcx| tcx.item_path_str(def_id)) } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 59bc001516c79..104c851e057e6 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1175,7 +1175,7 @@ pub fn rustc_short_optgroups() -> Vec { assumed.", "[KIND=]NAME"), opt::multi_s("", "crate-type", "Comma separated list of types of crates for the compiler to emit", - "[bin|lib|rlib|dylib|cdylib|staticlib]"), + "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]"), opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), opt::multi_s("", "emit", "Comma separated list of types of output for \ diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 5c5bf130c3ba4..4893e24091127 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -474,7 +474,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - tcx.infer_ctxt(None, Some(elaborated_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| { let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, @@ -576,7 +576,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); let cause = ObligationCause::dummy(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 59e3d398b2fd3..0fe054b30ba31 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -123,7 +123,7 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ancestors = trait_def.ancestors(impl_data.impl_def_id); match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, impl_data.impl_def_id, substs, node_item.node); @@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .subst(tcx, &penv.free_substs); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(None, Some(penv), Reveal::ExactMatch).enter(|infcx| { + let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a41523f2def76..368b1fb4bcbd3 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 644df8741e853..3df64ebd1581b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -65,6 +65,7 @@ pub struct GlobalArenas<'tcx> { trait_def: TypedArena, adt_def: TypedArena, mir: TypedArena>>, + tables: TypedArena>, } impl<'tcx> GlobalArenas<'tcx> { @@ -75,6 +76,7 @@ impl<'tcx> GlobalArenas<'tcx> { trait_def: TypedArena::new(), adt_def: TypedArena::new(), mir: TypedArena::new(), + tables: TypedArena::new(), } } } @@ -189,6 +191,7 @@ pub struct CommonTypes<'tcx> { pub err: Ty<'tcx>, } +#[derive(RustcEncodable, RustcDecodable)] pub struct Tables<'tcx> { /// Resolved definitions for `::X` associated paths. pub type_relative_path_defs: NodeMap, @@ -211,13 +214,11 @@ pub struct Tables<'tcx> { /// Borrows pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_tys: DefIdMap>, + /// Records the type of each closure. + pub closure_tys: NodeMap>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_kinds: DefIdMap, + /// Records the type of each closure. + pub closure_kinds: NodeMap, /// For each fn, records the "liberated" types of its arguments /// and return type. Liberated means that all bound regions @@ -233,7 +234,7 @@ pub struct Tables<'tcx> { pub fru_field_types: NodeMap>> } -impl<'a, 'gcx, 'tcx> Tables<'tcx> { +impl<'tcx> Tables<'tcx> { pub fn empty() -> Tables<'tcx> { Tables { type_relative_path_defs: NodeMap(), @@ -242,8 +243,8 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { adjustments: NodeMap(), method_map: FxHashMap(), upvar_capture_map: FxHashMap(), - closure_tys: DefIdMap(), - closure_kinds: DefIdMap(), + closure_tys: NodeMap(), + closure_kinds: NodeMap(), liberated_fn_sigs: NodeMap(), fru_field_types: NodeMap() } @@ -401,7 +402,7 @@ pub struct GlobalCtxt<'tcx> { free_region_maps: RefCell>, // FIXME: jroesch make this a refcell - pub tables: RefCell>, + pub tables: RefCell>>, /// Maps from a trait item to the trait item "descriptor" pub associated_items: RefCell>>, @@ -524,6 +525,14 @@ pub struct GlobalCtxt<'tcx> { /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kinds: RefCell>, + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_tys: RefCell>>, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_kinds: RefCell>>, + /// Maps a cast expression to its kind. This is keyed on the /// *from* expression of the cast, not the cast itself. pub cast_kinds: RefCell>, @@ -645,6 +654,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.global_arenas.mir.alloc(RefCell::new(mir)) } + pub fn alloc_tables(self, tables: ty::Tables<'gcx>) -> &'gcx ty::Tables<'gcx> { + self.global_arenas.tables.alloc(tables) + } + pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef { self.global_arenas.trait_def.alloc(def) } @@ -743,7 +756,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { variance_computed: Cell::new(false), sess: s, trait_map: resolutions.trait_map, - tables: RefCell::new(Tables::empty()), + tables: RefCell::new(DepTrackingMap::new(dep_graph.clone())), impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())), @@ -777,6 +790,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rvalue_promotable_to_static: RefCell::new(NodeMap()), custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), + closure_tys: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + closure_kinds: RefCell::new(DepTrackingMap::new(dep_graph.clone())), cast_kinds: RefCell::new(NodeMap()), fragment_infos: RefCell::new(DefIdMap()), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 42b3544421f8b..59d22d270b15d 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -46,3 +46,6 @@ dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } +dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } +dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } +dep_map_ty! { Tables: Tables(DefId) -> &'tcx ty::Tables<'tcx> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fa62e893a2875..a88b1e3ece964 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -321,7 +321,7 @@ pub struct MethodCallee<'tcx> { /// needed to add to the side tables. Thus to disambiguate /// we also keep track of whether there's an adjustment in /// our key. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct MethodCall { pub expr_id: NodeId, pub autoderef: u32 @@ -501,7 +501,7 @@ impl Slice { /// Upvars do not get their own node-id. Instead, we use the pair of /// the original var id (that is, the root variable that is referenced /// by the upvar) and the id of the closure expression. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct UpvarId { pub var_id: NodeId, pub closure_expr_id: NodeId, @@ -1917,8 +1917,30 @@ impl BorrowKind { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn tables(self) -> Ref<'a, Tables<'gcx>> { - self.tables.borrow() + pub fn body_tables(self, body: hir::BodyId) -> &'gcx Tables<'gcx> { + self.item_tables(self.map.body_owner_def_id(body)) + } + + pub fn item_tables(self, def_id: DefId) -> &'gcx Tables<'gcx> { + self.tables.memoize(def_id, || { + if def_id.is_local() { + // Closures' tables come from their outermost function, + // as they are part of the same "inference environment". + let outer_def_id = self.closure_base_def_id(def_id); + if outer_def_id != def_id { + return self.item_tables(outer_def_id); + } + + bug!("No def'n found for {:?} in tcx.tables", def_id); + } + + // Cross-crate side-tables only exist alongside serialized HIR. + self.sess.cstore.maybe_get_item_body(self.global_tcx(), def_id).map(|_| { + self.tables.borrow()[&def_id] + }).unwrap_or_else(|| { + bug!("tcx.item_tables({:?}): missing from metadata", def_id) + }) + }) } pub fn expr_span(self, id: NodeId) -> Span { @@ -2454,12 +2476,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) { + if let Some(&kind) = self.closure_kinds.borrow().get(&def_id) { return kind; } let kind = self.sess.cstore.closure_kind(def_id); - self.tables.borrow_mut().closure_kinds.insert(def_id, kind); + self.closure_kinds.borrow_mut().insert(def_id, kind); kind } @@ -2471,12 +2493,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) { + if let Some(ty) = self.closure_tys.borrow().get(&def_id) { return ty.subst(self, substs.substs); } let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); - self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone()); + self.closure_tys.borrow_mut().insert(def_id, ty.clone()); ty.subst(self, substs.substs) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0b1030f74b0fd..65bec9ecdaf95 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -146,7 +146,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(None, Some(self.clone()), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(self.clone(), Reveal::NotSpecializable).enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt) @@ -536,7 +536,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } let result = - tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch) + tcx.infer_ctxt(param_env.clone(), Reveal::ExactMatch) .enter(|infcx| { traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 3dc577b3c647a..000e4eb59bf05 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -28,7 +28,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(const_fn)] diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index e65d112430a16..edd474b2e9edc 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -15,7 +15,7 @@ #![crate_type = "rlib"] #![no_std] #![unstable(feature = "rustc_private", issue = "27812")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] //! A typesafe bitmask flag generator. diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index dc2214dd34e72..0605644d497db 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -188,12 +188,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, dfcx_loans: &LoanDataFlow<'b, 'tcx>, move_data: &move_data::FlowedMoveData<'c, 'tcx>, all_loans: &[Loan<'tcx>], - fn_id: ast::NodeId, body: &hir::Body) { debug!("check_loans(body id={})", body.value.id); - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 2c277c04a52e3..c33ced52e2bd6 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -18,7 +18,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; -use rustc::ty; +use rustc::ty::{self, Ty}; use std::rc::Rc; use syntax::ast; @@ -34,12 +34,10 @@ struct GatherMoveInfo<'tcx> { pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - decl_id: ast::NodeId, - _decl_span: Span, - var_id: ast::NodeId) { - let ty = bccx.tcx.tables().node_id_to_type(var_id); - let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty)); - move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); + var_id: ast::NodeId, + var_ty: Ty<'tcx>) { + let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty)); + move_data.add_move(bccx.tcx, loan_path, var_id, Declared); } pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 34f1ad57c6211..7101d843b4ce3 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,6 +18,7 @@ use borrowck::*; use borrowck::move_data::MoveData; +use rustc::infer::InferCtxt; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; @@ -25,7 +26,6 @@ use rustc::middle::region; use rustc::ty::{self, TyCtxt}; use syntax::ast; -use syntax::ast::NodeId; use syntax_pos::Span; use rustc::hir; use rustc::hir::Expr; @@ -40,20 +40,20 @@ mod gather_moves; mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - fn_id: NodeId, - body: &hir::Body) + body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let mut glcx = GatherLoanCtxt { bccx: bccx, + infcx: &infcx, all_loans: Vec::new(), - item_ub: bccx.tcx.region_maps.node_extent(body.value.id), + item_ub: bccx.tcx.region_maps.node_extent(body.node_id), move_data: MoveData::new(), move_error_collector: move_error::MoveErrorCollector::new(), }; - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let body = glcx.bccx.tcx.map.body(body); euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body); glcx.report_potential_errors(); @@ -63,6 +63,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, struct GatherLoanCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, move_data: move_data::MoveData<'tcx>, move_error_collector: move_error::MoveErrorCollector<'tcx>, all_loans: Vec>, @@ -158,8 +159,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { mode); } - fn decl_without_init(&mut self, id: ast::NodeId, span: Span) { - gather_moves::gather_decl(self.bccx, &self.move_data, id, span, id); + fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { + let ty = self.infcx.tables.borrow().node_id_to_type(id); + gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } @@ -516,19 +518,17 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { /// sure the loans being taken are sound. struct StaticInitializerCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId + body_id: hir::BodyId, } impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.bccx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, ex: &'tcx Expr) { if let hir::ExprAddrOf(mutbl, ref base) = ex.node { - let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx, - self.item_id); - let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(self.body_id); let mc = mc::MemCategorizationContext::new(&infcx); let base_cmt = mc.cat_expr(&base).unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); @@ -545,16 +545,14 @@ impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { } } -pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId, - body: hir::BodyId) { - +pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, body: hir::BodyId) { debug!("gather_loans_in_static_initializer(expr={:?})", body); let mut sicx = StaticInitializerCtxt { bccx: bccx, - item_id: item_id + body_id: body }; - sicx.visit_nested_body(body); + let body = sicx.bccx.tcx.map.body(body); + sicx.visit_body(body); } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 1ba313015d596..c0e038d183dad 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -24,7 +24,7 @@ use self::InteriorKind::*; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; -use rustc::hir::map::blocks::{FnParts, FnLikeNode}; +use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; use rustc::middle::dataflow::DataFlowContext; use rustc::middle::dataflow::BitwiseOperator; @@ -89,14 +89,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self, ti.id, expr); + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self, ii.id, expr); + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_impl_item(self, ii); } @@ -143,7 +143,7 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I match item.node { hir::ItemStatic(.., ex) | hir::ItemConst(_, ex) => { - gather_loans::gather_loans_in_static_initializer(this, item.id, ex); + gather_loans::gather_loans_in_static_initializer(this, ex); } _ => { } } @@ -179,7 +179,7 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, let AnalysisData { all_loans, loans: loan_dfcx, move_data: flowed_moves } = - build_borrowck_dataflow_data(this, &cfg, body, id); + build_borrowck_dataflow_data(this, &cfg, body_id); move_data::fragments::instrument_move_fragments(&flowed_moves.move_data, this.tcx, @@ -189,31 +189,26 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, &flowed_moves.move_data, id); - check_loans::check_loans(this, - &loan_dfcx, - &flowed_moves, - &all_loans[..], - id, - body); + check_loans::check_loans(this, &loan_dfcx, &flowed_moves, &all_loans[..], body); intravisit::walk_fn(this, fk, decl, body_id, sp, id); } fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, cfg: &cfg::CFG, - body: &'tcx hir::Body, - id: ast::NodeId) + body_id: hir::BodyId) -> AnalysisData<'a, 'tcx> { // Check the body of fn items. let tcx = this.tcx; + let body = tcx.map.body(body_id); let id_range = { let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.map); visitor.visit_body(body); visitor.result() }; let (all_loans, move_data) = - gather_loans::gather_loans_in_fn(this, id, body); + gather_loans::gather_loans_in_fn(this, body_id); let mut loan_dfcx = DataFlowContext::new(this.tcx, @@ -246,7 +241,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, /// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer. pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - fn_parts: FnParts<'tcx>, + body: hir::BodyId, cfg: &cfg::CFG) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'a, 'tcx>) { @@ -262,13 +257,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( } }; - let body = tcx.map.body(fn_parts.body); - - let dataflow_data = build_borrowck_dataflow_data(&mut bccx, - cfg, - body, - fn_parts.id); - + let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body); (bccx, dataflow_data) } diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 1ff232da427fc..d3b22884a3d8c 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![allow(non_camel_case_types)] diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 2949cf0d535bf..400af3c702346 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -51,6 +51,7 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { MatchVisitor { tcx: self.tcx, + tables: self.tcx.body_tables(b), param_env: &ty::ParameterEnvironment::for_item(self.tcx, id) }.visit_body(self.tcx.map.body(b)); } @@ -68,6 +69,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, param_env: &'a ty::ParameterEnvironment<'tcx> } @@ -156,7 +158,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( arm.pats.iter().map(|pat| { - let mut patcx = PatternContext::new(self.tcx); + let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { self.report_inlining_errors(patcx, pat.span); @@ -181,7 +183,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .flat_map(|arm| &arm.0) .map(|pat| vec![pat.0]) .collect(); - let scrut_ty = cx.tcx.tables().node_id_to_type(scrut.id); + let scrut_ty = self.tables.node_id_to_type(scrut.id); check_exhaustive(cx, scrut_ty, scrut.span, &matrix, source); }) } @@ -195,7 +197,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let module = self.tcx.map.local_def_id(self.tcx.map.get_module_parent(pat.id)); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { - let mut patcx = PatternContext::new(self.tcx); + let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; let pats : Matrix = vec![vec![ @@ -228,7 +230,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), _, name, None) = p.node { - let pat_ty = cx.tcx.tables().pat_ty(p); + let pat_ty = cx.tables.pat_ty(p); if let ty::TyAdt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.name == name.node && variant.ctor_kind == CtorKind::Const @@ -455,7 +457,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, _, ref sub) = p.node { - let pat_ty = cx.tcx.tables().node_id_to_type(p.id); + let pat_ty = cx.tables.node_id_to_type(p.id); if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } @@ -470,13 +472,11 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), - Reveal::NotSpecializable).enter(|infcx| { + cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::NotSpecializable).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; - let mut visitor = ExprUseVisitor::new(&mut checker, &infcx); - visitor.walk_expr(guard); + ExprUseVisitor::new(&mut checker, &infcx).walk_expr(guard); }); } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 6b8e0e34c1df6..bc72c8fb9b6fe 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -52,34 +52,24 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<&'tcx Expr> { - let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId | - -> Option<&'tcx Expr> { - for variant in variants { - if variant.node.data.id() == id { - return variant.node.disr_expr.map(|e| { - &tcx.map.body(e).value - }); - } - } - None - }; - + -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>)> { if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { let enum_node_id = tcx.map.get_parent(variant_node_id); - match tcx.map.find(enum_node_id) { - None => None, - Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - variant_expr(variants, variant_node_id) + if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) { + if let hir::ItemEnum(ref edef, _) = it.node { + for variant in &edef.variants { + if variant.node.data.id() == variant_node_id { + return variant.node.disr_expr.map(|e| { + let def_id = tcx.map.body_owner_def_id(e); + (&tcx.map.body(e).value, + tcx.tables.borrow().get(&def_id).cloned()) + }); + } } - _ => None - }, - Some(_) => None + } } - } else { - None } + None } /// * `def_id` is the id of the constant. @@ -90,17 +80,22 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>) - -> Option<(&'tcx Expr, Option>)> { + -> Option<(&'tcx Expr, + Option<&'a ty::Tables<'tcx>>, + Option>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { match tcx.map.find(node_id) { None => None, - Some(ast_map::NodeItem(it)) => match it.node { - hir::ItemConst(ref ty, body) => { - Some((&tcx.map.body(body).value, - tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, + Some(ast_map::NodeItem(&hir::Item { + node: hir::ItemConst(ref ty, body), .. + })) | + Some(ast_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Const(ref ty, body), .. + })) => { + Some((&tcx.map.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), + tcx.ast_ty_to_prim_ty(ty))) + } Some(ast_map::NodeTraitItem(ti)) => match ti.node { hir::TraitItemKind::Const(ref ty, default) => { if let Some(substs) = substs { @@ -111,6 +106,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.map.local_def_id(trait_id); let default_value = default.map(|body| { (&tcx.map.body(body).value, + tcx.tables.borrow().get(&def_id).cloned(), tcx.ast_ty_to_prim_ty(ty)) }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) @@ -126,18 +122,12 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => None }, - Some(ast_map::NodeImplItem(ii)) => match ii.node { - hir::ImplItemKind::Const(ref ty, body) => { - Some((&tcx.map.body(body).value, - tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, Some(_) => None } } else { - let expr_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id))) + let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (&body.value, Some(tcx.item_tables(def_id)), + Some(tcx.sess.cstore.item_type(tcx, def_id))) }); match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { @@ -148,34 +138,38 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // substitutions for the reference to it. if let Some(trait_id) = trait_id { if let Some(substs) = substs { - resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs) + resolve_trait_associated_const(tcx, def_id, expr_tables_ty, + trait_id, substs) } else { None } } else { - expr_ty + expr_tables_ty } }, - Some(Def::Const(..)) => expr_ty, + Some(Def::Const(..)) => expr_tables_ty, _ => None } } } fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option<&'tcx hir::Body> + -> Option<(&'tcx hir::Body, Option<&'a ty::Tables<'tcx>>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| { if fn_like.constness() == hir::Constness::Const { - Some(tcx.map.body(fn_like.body())) + Some((tcx.map.body(fn_like.body()), + tcx.tables.borrow().get(&def_id).cloned())) } else { None } }) } else { if tcx.sess.cstore.is_const_fn(def_id) { - tcx.sess.cstore.maybe_get_item_body(tcx, def_id) + tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (body, Some(tcx.item_tables(def_id))) + }) } else { None } @@ -230,30 +224,38 @@ pub fn note_const_eval_err<'a, 'tcx>( } } -pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> ConstVal { - match eval_const_expr_checked(tcx, e) { - Ok(r) => r, - // non-const path still needs to be a fatal error, because enums are funky - Err(s) => { - report_const_eval_err(tcx, &s, e.span, "expression").emit(); - match s.kind { - NonConstPath | - UnimplementedConstVal(_) => tcx.sess.abort_if_errors(), - _ => {} - } - Dummy - }, - } +pub struct ConstContext<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: Option<&'a ty::Tables<'tcx>>, + fn_args: Option> } -pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> EvalResult -{ - eval_const_expr_partial(tcx, e, ExprTypeChecked, None) -} +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { + let def_id = tcx.map.body_owner_def_id(body); + ConstContext { + tcx: tcx, + tables: tcx.tables.borrow().get(&def_id).cloned(), + fn_args: None + } + } -pub type FnArgMap<'a> = Option<&'a DefIdMap>; + pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self { + ConstContext { + tcx: tcx, + tables: Some(tables), + fn_args: None + } + } + + /// Evaluate a constant expression in a context where the expression isn't + /// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, + /// but a few places need to evaluate constants during type-checking, like + /// computing the length of an array. (See also the FIXME above EvalHint.) + pub fn eval(&self, e: &Expr, ty_hint: EvalHint<'tcx>) -> EvalResult { + eval_const_expr_partial(self, e, ty_hint) + } +} #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -433,20 +435,16 @@ macro_rules! signal { } } -/// Evaluate a constant expression in a context where the expression isn't -/// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, -/// but a few places need to evaluate constants during type-checking, like -/// computing the length of an array. (See also the FIXME above EvalHint.) -pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr, - ty_hint: EvalHint<'tcx>, - fn_args: FnArgMap) -> EvalResult { +fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, + e: &Expr, + ty_hint: EvalHint<'tcx>) -> EvalResult { + let tcx = cx.tcx; // Try to compute the type of the expression based on the EvalHint. // (See also the definition of EvalHint, and the FIXME above EvalHint.) let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(tcx.tables().expr_ty(e)) + cx.tables.map(|tables| tables.expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -457,7 +455,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - tcx.tables().expr_ty_opt(e) + cx.tables.and_then(|tables| tables.expr_ty_opt(e)) } }; let result = match e.node { @@ -510,14 +508,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => {}, } } - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Float(f) => Float(-f), Integral(i) => Integral(math!(e, -i)), const_val => signal!(e, NegateOn(const_val)), } } hir::ExprUnary(hir::UnNot, ref inner) => { - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Integral(i) => Integral(math!(e, !i)), Bool(b) => Bool(!b), const_val => signal!(e, NotOn(const_val)), @@ -533,8 +531,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // gives us a type through a type-suffix, cast or const def type // we need to re-eval the other value of the BinOp if it was // not inferred - match (eval_const_expr_partial(tcx, &a, ty_hint, fn_args)?, - eval_const_expr_partial(tcx, &b, b_ty, fn_args)?) { + match (cx.eval(a, ty_hint)?, + cx.eval(b, b_ty)?) { (Float(a), Float(b)) => { use std::cmp::Ordering::*; match op.node { @@ -604,13 +602,13 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match tcx.tables().expr_ty_opt(&base) { + match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) { Some(t) => UncheckedExprHint(t), None => ty_hint } }; - let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) { + let val = match cx.eval(base, base_hint) { Ok(val) => val, Err(ConstEvalErr { kind: ErroneousReferencedConstant( box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) | @@ -623,7 +621,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // we had a type hint, so we can't have an unknown type None => bug!(), }; - eval_const_expr_partial(tcx, &base, hint, fn_args)? + cx.eval(base, hint)? }, Err(e) => return Err(e), }; @@ -633,22 +631,29 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } hir::ExprPath(ref qpath) => { - let def = tcx.tables().qpath_def(qpath, e.id); + let def = cx.tables.map(|tables| tables.qpath_def(qpath, e.id)).unwrap_or_else(|| { + // There are no tables so we can only handle already-resolved HIR. + match *qpath { + hir::QPath::Resolved(_, ref path) => path.def, + hir::QPath::TypeRelative(..) => Def::Err + } + }); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(tcx.tables().node_id_item_substs(e.id) + Some(cx.tables.and_then(|tables| tables.node_id_item_substs(e.id)) .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None }; - if let Some((expr, ty)) = lookup_const_by_id(tcx, def_id, substs) { + if let Some((expr, tables, ty)) = lookup_const_by_id(tcx, def_id, substs) { let item_hint = match ty { Some(ty) => ty_hint.checked_or(ty), None => ty_hint, }; - match eval_const_expr_partial(tcx, expr, item_hint, None) { + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; + match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -660,8 +665,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }, Def::VariantCtor(variant_def, ..) => { - if let Some(const_expr) = lookup_variant_by_id(tcx, variant_def) { - match eval_const_expr_partial(tcx, const_expr, ty_hint, None) { + if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; + match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -673,11 +679,11 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } Def::StructCtor(..) => { - ConstVal::Struct(e.id) + ConstVal::Struct(Default::default()) } Def::Local(def_id) => { - debug!("Def::Local({:?}): {:?}", def_id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { + debug!("Def::Local({:?}): {:?}", def_id, cx.fn_args); + if let Some(val) = cx.fn_args.as_ref().and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -690,14 +696,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprCall(ref callee, ref args) => { let sub_ty_hint = ty_hint.erase_hint(); - let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?; + let callee_val = cx.eval(callee, sub_ty_hint)?; let did = match callee_val { Function(did) => did, Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), callee => signal!(e, CallOn(callee)), }; - let body = match lookup_const_fn_by_id(tcx, did) { - Some(body) => body, + let (body, tables) = match lookup_const_fn_by_id(tcx, did) { + Some(x) => x, None => signal!(e, NonConstPath), }; @@ -710,19 +716,19 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut call_args = DefIdMap(); for (arg, arg_expr) in arg_defs.into_iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); - let arg_val = eval_const_expr_partial( - tcx, - arg_expr, - arg_hint, - fn_args - )?; + let arg_val = cx.eval(arg_expr, arg_hint)?; debug!("const call arg: {:?}", arg); if let Some(def_id) = arg { assert!(call_args.insert(def_id, arg_val).is_none()); } } debug!("const call({:?})", call_args); - eval_const_expr_partial(tcx, &body.value, ty_hint, Some(&call_args))? + let callee_cx = ConstContext { + tcx: tcx, + tables: tables, + fn_args: Some(call_args) + }; + callee_cx.eval(&body.value, ty_hint)? }, hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { Ok(val) => val, @@ -730,46 +736,49 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, hir::ExprBlock(ref block) => { match block.expr { - Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?, + Some(ref expr) => cx.eval(expr, ty_hint)?, None => signal!(e, UnimplementedConstVal("empty block")), } } - hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?, - hir::ExprTup(_) => Tuple(e.id), - hir::ExprStruct(..) => Struct(e.id), + hir::ExprType(ref e, _) => cx.eval(e, ty_hint)?, + hir::ExprTup(ref fields) => { + let field_hint = ty_hint.erase_hint(); + Tuple(fields.iter().map(|e| cx.eval(e, field_hint)).collect::>()?) + } + hir::ExprStruct(_, ref fields, _) => { + let field_hint = ty_hint.erase_hint(); + Struct(fields.iter().map(|f| { + cx.eval(&f.expr, field_hint).map(|v| (f.name.node, v)) + }).collect::>()?) + } hir::ExprIndex(ref arr, ref idx) => { if !tcx.sess.features.borrow().const_indexing { signal!(e, IndexOpFeatureGated); } let arr_hint = ty_hint.erase_hint(); - let arr = eval_const_expr_partial(tcx, arr, arr_hint, fn_args)?; + let arr = cx.eval(arr, arr_hint)?; let idx_hint = ty_hint.checked_or(tcx.types.usize); - let idx = match eval_const_expr_partial(tcx, idx, idx_hint, fn_args)? { + let idx = match cx.eval(idx, idx_hint)? { Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), Integral(_) => bug!(), _ => signal!(idx, IndexNotInt), }; assert_eq!(idx as usize as u64, idx); match arr { - Array(_, n) if idx >= n => { - signal!(e, IndexOutOfBounds { len: n, index: idx }) + Array(ref v) => { + if let Some(elem) = v.get(idx as usize) { + elem.clone() + } else { + let n = v.len() as u64; + assert_eq!(n as usize as u64, n); + signal!(e, IndexOutOfBounds { len: n, index: idx }) + } } - Array(v, n) => if let hir::ExprArray(ref v) = tcx.map.expect_expr(v).node { - assert_eq!(n as usize as u64, n); - eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)? - } else { - bug!() - }, - Repeat(_, n) if idx >= n => { + Repeat(.., n) if idx >= n => { signal!(e, IndexOutOfBounds { len: n, index: idx }) } - Repeat(elem, _) => eval_const_expr_partial( - tcx, - &tcx.map.expect_expr(elem), - ty_hint, - fn_args, - )?, + Repeat(ref elem, _) => (**elem).clone(), ByteStr(ref data) if idx >= data.len() as u64 => { signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx }) @@ -781,31 +790,38 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => signal!(e, IndexedNonVec), } } - hir::ExprArray(ref v) => Array(e.id, v.len() as u64), - hir::ExprRepeat(_, n) => { + hir::ExprArray(ref v) => { + let elem_hint = ty_hint.erase_hint(); + Array(v.iter().map(|e| cx.eval(e, elem_hint)).collect::>()?) + } + hir::ExprRepeat(ref elem, count) => { + let elem_hint = ty_hint.erase_hint(); let len_hint = ty_hint.checked_or(tcx.types.usize); - let n = &tcx.map.body(n).value; - Repeat( - e.id, - match eval_const_expr_partial(tcx, n, len_hint, fn_args)? { - Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), - Integral(_) => signal!(e, RepeatCountNotNatural), - _ => signal!(e, RepeatCountNotInt), - }, - ) + let n = if let Some(ty) = ety { + // For cross-crate constants, we have the type already, + // but not the body for `count`, so use the type. + match ty.sty { + ty::TyArray(_, n) => n as u64, + _ => bug!() + } + } else { + let n = &tcx.map.body(count).value; + match ConstContext::new(tcx, count).eval(n, len_hint)? { + Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), + Integral(_) => signal!(e, RepeatCountNotNatural), + _ => signal!(e, RepeatCountNotInt), + } + }; + Repeat(Box::new(cx.eval(elem, elem_hint)?), n) }, hir::ExprTupField(ref base, index) => { let base_hint = ty_hint.erase_hint(); - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Tuple(tup_id) = c { - if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node { - if index.node < fields.len() { - eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args)? - } else { - signal!(e, TupleIndexOutOfBounds); - } + let c = cx.eval(base, base_hint)?; + if let Tuple(ref fields) = c { + if let Some(elem) = fields.get(index.node) { + elem.clone() } else { - bug!() + signal!(e, TupleIndexOutOfBounds); } } else { signal!(base, ExpectedConstTuple); @@ -813,20 +829,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprField(ref base, field_name) => { let base_hint = ty_hint.erase_hint(); - // Get the base expression if it is a struct and it is constant - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Struct(struct_id) = c { - if let hir::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node { - // Check that the given field exists and evaluate it - // if the idents are compared run-pass/issue-19244 fails - if let Some(f) = fields.iter().find(|f| f.name.node - == field_name.node) { - eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args)? - } else { - signal!(e, MissingStructField); - } + let c = cx.eval(base, base_hint)?; + if let Struct(ref fields) = c { + if let Some(f) = fields.get(&field_name.node) { + f.clone() } else { - bug!() + signal!(e, MissingStructField); } } else { signal!(base, ExpectedConstStruct); @@ -909,17 +917,17 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: DefId, - default_value: Option<(&'tcx Expr, Option>)>, + default_value: Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, Option>)> +) -> Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option>)> { let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); tcx.populate_implementations_for_trait_if_necessary(trait_id); - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); @@ -1160,36 +1168,40 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal) } } -pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - span: Span, - a: &Expr, - b: &Expr) -> Result { - let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) { - Ok(a) => a, - Err(e) => { - report_const_eval_err(tcx, &e, a.span, "expression").emit(); - return Err(ErrorReported); - } - }; - let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) { - Ok(b) => b, - Err(e) => { - report_const_eval_err(tcx, &e, b.span, "expression").emit(); - return Err(ErrorReported); - } - }; - compare_const_vals(tcx, span, &a, &b) +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn compare_lit_exprs(&self, + span: Span, + a: &Expr, + b: &Expr) -> Result { + let tcx = self.tcx; + let a = match self.eval(a, ExprTypeChecked) { + Ok(a) => a, + Err(e) => { + report_const_eval_err(tcx, &e, a.span, "expression").emit(); + return Err(ErrorReported); + } + }; + let b = match self.eval(b, ExprTypeChecked) { + Ok(b) => b, + Err(e) => { + report_const_eval_err(tcx, &e, b.span, "expression").emit(); + return Err(ErrorReported); + } + }; + compare_const_vals(tcx, span, &a, &b) + } } /// Returns the value of the length-valued expression pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - count_expr: &hir::Expr, + count: hir::BodyId, reason: &str) -> Result { let hint = UncheckedExprHint(tcx.types.usize); - match eval_const_expr_partial(tcx, count_expr, hint, None) { + let count_expr = &tcx.map.body(count).value; + match ConstContext::new(tcx, count).eval(count_expr, hint) { Ok(Integral(Usize(count))) => { let val = count.as_u64(tcx.sess.target.uint_type); assert_eq!(val as usize as u64, val); diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 42394f4745f66..fbd15b6eb1035 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -119,8 +119,7 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result { ConstVal::Tuple(_) | ConstVal::Function(_) | ConstVal::Array(..) | - ConstVal::Repeat(..) | - ConstVal::Dummy => bug!("{:?} not printable in a pattern", value) + ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value) } } @@ -261,12 +260,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub tables: &'a ty::Tables<'gcx>, pub errors: Vec, } impl<'a, 'gcx, 'tcx> Pattern<'tcx> { - pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &hir::Pat) -> Self { - let mut pcx = PatternContext::new(tcx); + pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, + tables: &'a ty::Tables<'gcx>, + pat: &hir::Pat) -> Self { + let mut pcx = PatternContext::new(tcx, tables); let result = pcx.lower_pattern(pat); if !pcx.errors.is_empty() { span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors) @@ -277,12 +279,12 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> { } impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { - PatternContext { tcx: tcx, errors: vec![] } + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, tables: &'a ty::Tables<'gcx>) -> Self { + PatternContext { tcx: tcx, tables: tables, errors: vec![] } } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.tcx.tables().node_id_to_type(pat.id); + let mut ty = self.tables.node_id_to_type(pat.id); let kind = match pat.node { PatKind::Wild => PatternKind::Wild, @@ -309,7 +311,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { @@ -334,7 +336,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyTuple(ref tys) => { let subpatterns = @@ -355,7 +357,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Binding(bm, def_id, ref ident, ref sub) => { let id = self.tcx.map.as_local_node_id(def_id).unwrap(); - let var_ty = self.tcx.tables().node_id_to_type(pat.id); + let var_ty = self.tables.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), _ => None, @@ -392,7 +394,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), @@ -411,7 +413,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { @@ -569,16 +571,21 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pat_id: ast::NodeId, span: Span) -> Pattern<'tcx> { - let ty = self.tcx.tables().node_id_to_type(id); - let def = self.tcx.tables().qpath_def(qpath, id); + let ty = self.tables.node_id_to_type(id); + let def = self.tables.qpath_def(qpath, id); let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let tcx = self.tcx.global_tcx(); - let substs = tcx.tables().node_id_item_substs(id) + let substs = self.tables.node_id_item_substs(id) .unwrap_or_else(|| tcx.intern_substs(&[])); match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { - Some((const_expr, _const_ty)) => { - return self.lower_const_expr(const_expr, pat_id, span); + Some((const_expr, const_tables, _const_ty)) => { + // Enter the inlined constant's tables temporarily. + let old_tables = self.tables; + self.tables = const_tables.expect("missing tables after typeck"); + let pat = self.lower_const_expr(const_expr, pat_id, span); + self.tables = old_tables; + return pat; } None => { self.errors.push(PatternError::StaticInPattern(span)); @@ -597,7 +604,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> { - match eval::eval_const_expr_checked(self.tcx.global_tcx(), expr) { + let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables); + match const_cx.eval(expr, eval::EvalHint::ExprTypeChecked) { Ok(value) => { PatternKind::Constant { value: value } } @@ -613,7 +621,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pat_id: ast::NodeId, span: Span) -> Pattern<'tcx> { - let pat_ty = self.tcx.tables().expr_ty(expr); + let pat_ty = self.tables.expr_ty(expr); debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); match pat_ty.sty { ty::TyFloat(_) => { @@ -659,8 +667,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { hir::ExprPath(ref qpath) => qpath, _ => bug!() }; - let ty = self.tcx.tables().node_id_to_type(callee.id); - let def = self.tcx.tables().qpath_def(qpath, callee.id); + let ty = self.tables.node_id_to_type(callee.id); + let def = self.tables.qpath_def(qpath, callee.id); match def { Def::Fn(..) | Def::Method(..) => self.lower_lit(expr), _ => { @@ -676,8 +684,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } hir::ExprStruct(ref qpath, ref fields, None) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); - let pat_ty = self.tcx.tables().node_id_to_type(expr.id); + let def = self.tables.qpath_def(qpath, expr.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 597344a2c82d0..cd933c0059945 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -26,6 +26,7 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(const_fn)] +#![cfg_attr(not(stage0), feature(i128))] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index ee75a3596e18a..4623e52ffc2fd 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -23,7 +23,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(shared)] #![feature(collections_range)] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 63abc09a07672..442c139f14c06 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1334,9 +1334,10 @@ pub fn build_output_filenames(input: &Input, .values() .filter(|a| a.is_none()) .count(); - let ofile = if unnamed_output_types > 1 { - sess.warn("ignoring specified output filename because multiple outputs were \ - requested"); + let ofile = if unnamed_output_types > 1 && + sess.opts.output_types.contains_key(&OutputType::Exe) { + sess.warn("ignoring specified output filename for 'link' output because multiple \ + outputs were requested"); None } else { Some(out_file.clone()) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index ca31022b04c64..25049b3d2badb 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(libc)] diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index cc288619cdee0..afacfb6e3f9fd 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -39,6 +39,7 @@ use syntax_pos; use graphviz as dot; +use std::cell::Cell; use std::fs::File; use std::io::{self, Write}; use std::iter; @@ -236,7 +237,11 @@ impl PpSourceMode { arenas, id, |tcx, _, _, _| { - let annotation = TypedAnnotation { tcx: tcx }; + let empty_tables = ty::Tables::empty(); + let annotation = TypedAnnotation { + tcx: tcx, + tables: Cell::new(&empty_tables) + }; let _ignore = tcx.dep_graph.in_ignore(); f(&annotation, payload, ast_map.forest.krate()) }), @@ -488,6 +493,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { struct TypedAnnotation<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: Cell<&'a ty::Tables<'tcx>>, } impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { @@ -511,7 +517,13 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) -> io::Result<()> { - pprust_hir::PpAnn::nested(&self.tcx.map, state, nested) + let old_tables = self.tables.get(); + if let pprust_hir::Nested::Body(id) = nested { + self.tables.set(self.tcx.body_tables(id)); + } + pprust_hir::PpAnn::nested(&self.tcx.map, state, nested)?; + self.tables.set(old_tables); + Ok(()) } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { @@ -525,7 +537,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { pp::space(&mut s.s)?; pp::word(&mut s.s, "as")?; pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?; + pp::word(&mut s.s, &self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), @@ -751,7 +763,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, } blocks::Code::FnLike(fn_like) => { let (bccx, analysis_data) = - borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg); + borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.body(), &cfg); let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 887e586a3112e..ede35d052ad51 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -149,7 +149,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 09a0c7f9be4ea..bcae7b262c626 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(custom_attribute)] #![allow(unused_attributes)] diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index d02e4f9b165d8..ea0a0034c3e92 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -17,7 +17,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c021ffee81899..8d86e7e2e8b9e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { } fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { - let ty = cx.tcx.tables().node_id_to_type(e.id); + let ty = cx.tables.node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } } @@ -738,8 +738,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // is this a recursive call? let self_recursive = if node_id != ast::DUMMY_NODE_ID { match method { - Some(ref method) => expr_refers_to_this_method(cx.tcx, method, node_id), - None => expr_refers_to_this_fn(cx.tcx, id, node_id), + Some(ref method) => expr_refers_to_this_method(cx, method, node_id), + None => expr_refers_to_this_fn(cx, id, node_id), } } else { false @@ -787,43 +787,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Functions for identifying if the given Expr NodeId `id` // represents a call to the function `fn_id`/method `method`. - fn expr_refers_to_this_fn(tcx: TyCtxt, fn_id: ast::NodeId, id: ast::NodeId) -> bool { - match tcx.map.get(id) { + fn expr_refers_to_this_fn(cx: &LateContext, fn_id: ast::NodeId, id: ast::NodeId) -> bool { + match cx.tcx.map.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - tcx.tables().qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.id) } else { return false; }; - def.def_id() == tcx.map.local_def_id(fn_id) + def.def_id() == cx.tcx.map.local_def_id(fn_id) } _ => false, } } // Check if the expression `id` performs a call to `method`. - fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - method: &ty::AssociatedItem, - id: ast::NodeId) - -> bool { + fn expr_refers_to_this_method(cx: &LateContext, + method: &ty::AssociatedItem, + id: ast::NodeId) + -> bool { use rustc::ty::adjustment::*; // Check for method calls and overloaded operators. - let opt_m = tcx.tables().method_map.get(&ty::MethodCall::expr(id)).cloned(); + let opt_m = cx.tables.method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { - if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { + if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) { return true; } } // Check for overloaded autoderef method calls. - let opt_adj = tcx.tables().adjustments.get(&id).cloned(); + let opt_adj = cx.tables.adjustments.get(&id).cloned(); if let Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) = opt_adj { for i in 0..autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); - if let Some(m) = tcx.tables().method_map.get(&method_call) - .cloned() { - if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { + if let Some(m) = cx.tables.method_map.get(&method_call).cloned() { + if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) { return true; } } @@ -831,19 +830,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { } // Check for calls to methods via explicit paths (e.g. `T::method()`). - match tcx.map.get(id) { + match cx.tcx.map.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - tcx.tables().qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.id) } else { return false; }; match def { Def::Method(def_id) => { - let substs = tcx.tables().node_id_item_substs(callee.id) - .unwrap_or_else(|| tcx.intern_substs(&[])); + let substs = cx.tables.node_id_item_substs(callee.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); method_call_refers_to_method( - tcx, method, def_id, substs, id) + cx.tcx, method, def_id, substs, id) } _ => false, } @@ -882,8 +881,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // checking, so it's always local let node_id = tcx.map.as_local_node_id(method.def_id).unwrap(); - let param_env = Some(ty::ParameterEnvironment::for_item(tcx, node_id)); - tcx.infer_ctxt(None, param_env, Reveal::NotSpecializable).enter(|infcx| { + let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); + tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. @@ -1073,7 +1072,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { expr: &hir::Expr) -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { let def = if let hir::ExprPath(ref qpath) = expr.node { - cx.tcx.tables().qpath_def(qpath, expr.id) + cx.tables.qpath_def(qpath, expr.id) } else { return None; }; @@ -1081,7 +1080,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tcx.tables().node_id_to_type(expr.id); + let typ = cx.tables.node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => { let from = bare_fn.sig.skip_binder().inputs()[0]; diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index efccc4abd43b8..60497fe171ccb 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -26,7 +26,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![cfg_attr(test, feature(test))] #![feature(box_patterns)] diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 570365c407f48..2a77e9a4a7c8b 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -16,7 +16,7 @@ use rustc::ty::{self, AdtKind, Ty, TyCtxt}; use rustc::ty::layout::{Layout, Primitive}; use rustc::traits::Reveal; use middle::const_val::ConstVal; -use rustc_const_eval::eval_const_expr_partial; +use rustc_const_eval::ConstContext; use rustc_const_eval::EvalHint::ExprTypeChecked; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; @@ -89,14 +89,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } hir::ExprBinary(binop, ref l, ref r) => { - if is_comparison(binop) && !check_limits(cx.tcx, binop, &l, &r) { + if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { cx.span_lint(UNUSED_COMPARISONS, e.span, "comparison is useless due to type limits"); } if binop.node.is_shift() { - let opt_ty_bits = match cx.tcx.tables().node_id_to_type(l.id).sty { + let opt_ty_bits = match cx.tables.node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), _ => None, @@ -110,7 +110,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { false } } else { - match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(cx.tcx, cx.tables); + match const_cx.eval(&r, ExprTypeChecked) { Ok(ConstVal::Integral(i)) => { i.is_negative() || i.to_u64() @@ -129,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } hir::ExprLit(ref lit) => { - match cx.tcx.tables().node_id_to_type(e.id).sty { + match cx.tables.node_id_to_type(e.id).sty { ty::TyInt(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | @@ -274,11 +275,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } - fn check_limits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - binop: hir::BinOp, - l: &hir::Expr, - r: &hir::Expr) - -> bool { + fn check_limits(cx: &LateContext, + binop: hir::BinOp, + l: &hir::Expr, + r: &hir::Expr) + -> bool { let (lit, expr, swap) = match (&l.node, &r.node) { (&hir::ExprLit(_), _) => (l, r, true), (_, &hir::ExprLit(_)) => (r, l, false), @@ -287,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // Normalize the binop so that the literal is always on the RHS in // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; - match tcx.tables().node_id_to_type(expr.id).sty { + match cx.tables.node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i128 = match lit.node { @@ -696,7 +697,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { if gens.ty_params.is_empty() { // sizes only make sense for non-generic types let t = cx.tcx.item_type(cx.tcx.map.local_def_id(it.id)); - let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let layout = cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let ty = cx.tcx.erase_regions(&t); ty.layout(&infcx).unwrap_or_else(|e| { bug!("failed to get layout for `{}`: {}", t, e) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index b7ee688117d93..48d9f5e72c26d 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { return; } - let t = cx.tcx.tables().expr_ty(&expr); + let t = cx.tables.expr_ty(&expr); let warned = match t.sty { ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyNever => return, @@ -440,7 +440,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { _ => return, } - if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) { + if let Some(adjustment) = cx.tables.adjustments.get(&e.id) { if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind { match autoref { Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 938f346e0bf82..b1615b9e38bde 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -20,7 +20,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(box_syntax)] diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index b27b164bd47aa..3c14d38cc3821 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -8,59 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::map as ast_map; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; -use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange, NestedVisitorMap}; - -use cstore::CrateMetadata; use encoder::EncodeContext; use schema::*; use rustc::hir; -use rustc::hir::def::Def; -use rustc::hir::def_id::DefId; -use rustc::ty::{self, TyCtxt, Ty}; - -use syntax::ast; +use rustc::ty; use rustc_serialize::Encodable; #[derive(RustcEncodable, RustcDecodable)] pub struct Ast<'tcx> { - id_range: IdRange, - body: Lazy, - side_tables: LazySeq<(ast::NodeId, TableEntry<'tcx>)>, + pub body: Lazy, + pub tables: Lazy>, pub nested_bodies: LazySeq, pub rvalue_promotable_to_static: bool, } -#[derive(RustcEncodable, RustcDecodable)] -enum TableEntry<'tcx> { - TypeRelativeDef(Def), - NodeType(Ty<'tcx>), - ItemSubsts(ty::ItemSubsts<'tcx>), - Adjustment(ty::adjustment::Adjustment<'tcx>), -} - impl<'a, 'tcx> EncodeContext<'a, 'tcx> { - pub fn encode_body(&mut self, body: hir::BodyId) -> Lazy> { - let body = self.tcx.map.body(body); - - let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map); - id_visitor.visit_body(body); + pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy> { + let body = self.tcx.map.body(body_id); + let lazy_body = self.lazy(body); - let body_pos = self.position(); - body.encode(self).unwrap(); - - let tables_pos = self.position(); - let tables_count = { - let mut visitor = SideTableEncodingIdVisitor { - ecx: self, - count: 0, - }; - visitor.visit_body(body); - visitor.count - }; + let tables = self.tcx.body_tables(body_id); + let lazy_tables = self.lazy(tables); let nested_pos = self.position(); let nested_count = { @@ -76,44 +48,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tcx.rvalue_promotable_to_static.borrow()[&body.value.id]; self.lazy(&Ast { - id_range: id_visitor.result(), - body: Lazy::with_position(body_pos), - side_tables: LazySeq::with_position_and_length(tables_pos, tables_count), + body: lazy_body, + tables: lazy_tables, nested_bodies: LazySeq::with_position_and_length(nested_pos, nested_count), rvalue_promotable_to_static: rvalue_promotable_to_static }) } } -struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> { - ecx: &'a mut EncodeContext<'b, 'tcx>, - count: usize, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.ecx.tcx.map) - } - - fn visit_id(&mut self, id: ast::NodeId) { - debug!("Encoding side tables for id {}", id); - - let tcx = self.ecx.tcx; - let mut encode = |entry: Option| { - if let Some(entry) = entry { - (id, entry).encode(self.ecx).unwrap(); - self.count += 1; - } - }; - - encode(tcx.tables().type_relative_path_defs.get(&id).cloned() - .map(TableEntry::TypeRelativeDef)); - encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType)); - encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); - } -} - struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> { ecx: &'a mut EncodeContext<'b, 'tcx>, count: usize, @@ -132,41 +74,3 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for NestedBodyEncodingVisitor<'a, 'b, 'tcx> { self.visit_body(body); } } - -/// Decodes an item's body from its AST in the cdata's metadata and adds it to the -/// ast-map. -pub fn decode_body<'a, 'tcx>(cdata: &CrateMetadata, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, - ast: Ast<'tcx>) - -> &'tcx hir::Body { - debug!("> Decoding inlined fn: {}", tcx.item_path_str(def_id)); - - let cnt = ast.id_range.max.as_usize() - ast.id_range.min.as_usize(); - let start = tcx.sess.reserve_node_ids(cnt); - let id_ranges = [ast.id_range, - IdRange { - min: start, - max: ast::NodeId::new(start.as_usize() + cnt), - }]; - - for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) { - match entry { - TableEntry::TypeRelativeDef(def) => { - tcx.tables.borrow_mut().type_relative_path_defs.insert(id, def); - } - TableEntry::NodeType(ty) => { - tcx.tables.borrow_mut().node_types.insert(id, ty); - } - TableEntry::ItemSubsts(item_substs) => { - tcx.tables.borrow_mut().item_substs.insert(id, item_substs); - } - TableEntry::Adjustment(adj) => { - tcx.tables.borrow_mut().adjustments.insert(id, adj); - } - } - } - - let body = ast.body.decode((cdata, tcx, id_ranges)); - ast_map::map_decoded_body(&tcx.map, def_id, body, tcx.sess.next_node_id()) -} diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index aab4034b7705a..efc19abb33e1b 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -97,7 +97,6 @@ pub struct CStore { used_link_args: RefCell>, statically_included_foreign_items: RefCell>, pub dllimport_foreign_items: RefCell>, - pub inlined_item_cache: RefCell>>, pub visible_parent_map: RefCell>, } @@ -112,7 +111,6 @@ impl CStore { statically_included_foreign_items: RefCell::new(FxHashSet()), dllimport_foreign_items: RefCell::new(FxHashSet()), visible_parent_map: RefCell::new(FxHashMap()), - inlined_item_cache: RefCell::new(FxHashMap()), } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 64513fa41b219..3d025e984b040 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -434,27 +434,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { def_id: DefId) -> Option<&'tcx hir::Body> { - self.dep_graph.read(DepNode::MetaData(def_id)); - - if let Some(&cached) = self.inlined_item_cache.borrow().get(&def_id) { - return cached.map(|root_id| { - // Already inline - debug!("maybe_get_item_body({}): already inline", tcx.item_path_str(def_id)); - tcx.map.expect_inlined_body(root_id) - }); + if let Some(cached) = tcx.map.get_inlined_body(def_id) { + return Some(cached); } + self.dep_graph.read(DepNode::MetaData(def_id)); debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id)); - let inlined = self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index); - - self.inlined_item_cache.borrow_mut().insert(def_id, inlined.map(|body| { - let root_id = tcx.map.get_parent_node(body.value.id); - assert_eq!(tcx.map.get_parent_node(root_id), root_id); - root_id - })); - - inlined + self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index) } fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index dad956afb5e60..f3a673898b25c 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,13 +10,11 @@ // Decoding metadata from a single crate's metadata -use astencode::decode_body; use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary}; use schema::*; use rustc::hir::map::{DefKey, DefPath, DefPathData}; use rustc::hir; -use rustc::hir::intravisit::IdRange; use rustc::middle::cstore::LinkagePreference; use rustc::hir::def::{self, Def, CtorKind}; @@ -40,7 +38,7 @@ use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; -use syntax::ast::{self, NodeId}; +use syntax::ast; use syntax::codemap; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; use rustc_i128::{u128, i128}; @@ -50,8 +48,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> { cdata: Option<&'a CrateMetadata>, sess: Option<&'a Session>, tcx: Option>, - from_id_range: IdRange, - to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, @@ -67,18 +63,12 @@ pub trait Metadata<'a, 'tcx>: Copy { fn tcx(self) -> Option> { None } fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { - let id_range = IdRange { - min: NodeId::from_u32(u32::MIN), - max: NodeId::from_u32(u32::MAX), - }; let tcx = self.tcx(); DecodeContext { opaque: opaque::Decoder::new(self.raw_bytes(), pos), cdata: self.cdata(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), tcx: tcx, - from_id_range: id_range, - to_id_range: id_range, last_filemap_index: 0, lazy_state: LazyState::NoNode, } @@ -128,26 +118,6 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> } } -// HACK(eddyb) Only used by astencode to customize the from/to IdRange's. -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>, [IdRange; 2]) { - fn raw_bytes(self) -> &'a [u8] { - self.0.raw_bytes() - } - fn cdata(self) -> Option<&'a CrateMetadata> { - Some(self.0) - } - fn tcx(self) -> Option> { - Some(self.1) - } - - fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { - let mut dcx = (self.0, self.1).decoder(pos); - dcx.from_id_range = self.2[0]; - dcx.to_id_range = self.2[1]; - dcx - } -} - impl<'a, 'tcx: 'a, T: Decodable> Lazy { pub fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position); @@ -256,28 +226,6 @@ impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result { - let id = u32::decode(self)?; - - // from_id_range should be non-empty - assert!(!self.from_id_range.empty()); - // Make sure that translating the NodeId will actually yield a - // meaningful result - if !self.from_id_range.contains(NodeId::from_u32(id)) { - bug!("NodeId::decode: {} out of DecodeContext range ({:?} -> {:?})", - id, - self.from_id_range, - self.to_id_range); - } - - // Use wrapping arithmetic because otherwise it introduces control flow. - // Maybe we should just have the control flow? -- aatch - Ok(NodeId::from_u32(id.wrapping_sub(self.from_id_range.min.as_u32()) - .wrapping_add(self.to_id_range.min.as_u32()))) - } -} - impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { let cnum = CrateNum::from_u32(u32::decode(self)?); @@ -829,7 +777,14 @@ impl<'a, 'tcx> CrateMetadata { -> Option<&'tcx hir::Body> { if self.is_proc_macro(id) { return None; } self.entry(id).ast.map(|ast| { - decode_body(self, tcx, self.local_def_id(id), ast.decode(self)) + let def_id = self.local_def_id(id); + let ast = ast.decode(self); + + let tables = ast.tables.decode((self, tcx)); + tcx.tables.borrow_mut().insert(def_id, tcx.alloc_tables(tables)); + + let body = ast.body.decode((self, tcx)); + tcx.map.intern_inlined_body(def_id, body) }) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c3bcdf42d4ede..7de768b7b9049 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1037,7 +1037,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.tables().closure_tys[&def_id]), + ty: self.lazy(&tcx.closure_tys.borrow()[&def_id]), }; Entry { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 3986cc507d4be..484e0df658303 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_patterns)] #![feature(conservative_impl_trait)] diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index cfdc1bf27df35..7347841a5f1ef 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -169,7 +169,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = tcx.tables().upvar_capture(ty::UpvarId { + let by_ref = hir.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id }).map_or(false, |capture| match capture { @@ -195,13 +195,12 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, } pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, - item_id: ast::NodeId, body_id: hir::BodyId) -> Mir<'tcx> { let tcx = hir.tcx(); let ast_expr = &tcx.map.body(body_id).value; - let ty = tcx.tables().expr_ty_adjusted(ast_expr); - let span = tcx.map.span(item_id); + let ty = hir.tables().expr_ty_adjusted(ast_expr); + let span = tcx.map.span(tcx.map.body_owner(body_id)); let mut builder = Builder::new(hir, span, 0, ty); let extent = tcx.region_maps.temporary_scope(ast_expr.id) @@ -306,7 +305,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let lvalue = Lvalue::Local(Local::new(index + 1)); if let Some(pattern) = pattern { - let pattern = Pattern::from_hir(self.hir.tcx(), pattern); + let pattern = Pattern::from_hir(self.hir.tcx(), self.hir.tables(), pattern); scope = self.declare_bindings(scope, ast_body.span, &pattern); unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue)); } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index b355c8f2c4c6f..4b3d62fd6d6ef 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -61,7 +61,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let remainder_extent = cx.tcx.region_maps.lookup_code_extent(remainder_extent); - let pattern = Pattern::from_hir(cx.tcx, &local.pat); + let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Let { @@ -82,7 +82,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { - let block_ty = cx.tcx.tables().node_id_to_type(block.id); + let block_ty = cx.tables().node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { ty: block_ty, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index cc65fdede092f..fe10fb57c35e8 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,7 +17,7 @@ use hair::cx::to_ref::ToRef; use rustc::hir::map; use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; -use rustc_const_eval as const_eval; +use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; @@ -33,7 +33,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); let mut expr = make_mirror_unadjusted(cx, self); - let adj = cx.tcx.tables().adjustments.get(&self.id).cloned(); + let adj = cx.tables().adjustments.get(&self.id).cloned(); debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}", expr, @@ -80,13 +80,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { let i = i as u32; let adjusted_ty = expr.ty.adjust_for_autoderef(cx.tcx, self.id, self.span, i, |mc| { - cx.tcx.tables().method_map.get(&mc).map(|m| m.ty) + cx.tables().method_map.get(&mc).map(|m| m.ty) }); debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty); let method_key = ty::MethodCall::autoderef(self.id, i); - let meth_ty = cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty); + let meth_ty = cx.tables().method_map.get(&method_key).map(|m| m.ty); let kind = if let Some(meth_ty) = meth_ty { debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty); @@ -217,7 +217,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { - let expr_ty = cx.tcx.tables().expr_ty(expr); + let expr_ty = cx.tables().expr_ty(expr); let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); let kind = match expr.node { @@ -236,7 +236,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprCall(ref fun, ref args) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and // build the appropriate UFCS call expression with the @@ -285,9 +285,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, None }; if let Some((adt_def, index)) = adt_data { - let substs = cx.tcx - .tables() - .node_id_item_substs(fun.id) + let substs = cx.tables().node_id_item_substs(fun.id) .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let field_refs = args.iter() .enumerate() @@ -307,7 +305,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } else { ExprKind::Call { - ty: cx.tcx.tables().node_id_to_type(fun.id), + ty: cx.tables().node_id_to_type(fun.id), fun: fun.to_ref(), args: args.to_ref(), } @@ -337,7 +335,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -361,7 +359,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) }, hir::ExprBinary(op, ref lhs, ref rhs) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -421,7 +419,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprIndex(ref lhs, ref index) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), @@ -437,7 +435,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), @@ -450,7 +448,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNot, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), @@ -466,7 +464,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), @@ -500,8 +498,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, base: base.as_ref().map(|base| { FruInfo { base: base.to_ref(), - field_types: cx.tcx.tables().fru_field_types[&expr.id] - .clone(), + field_types: cx.tables().fru_field_types[&expr.id].clone(), } }), } @@ -541,7 +538,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprClosure(..) => { - let closure_ty = cx.tcx.tables().expr_ty(expr); + let closure_ty = cx.tables().expr_ty(expr); let (def_id, substs) = match closure_ty.sty { ty::TyClosure(def_id, substs) => (def_id, substs), _ => { @@ -562,7 +559,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprPath(ref qpath) => { - let def = cx.tcx.tables().qpath_def(qpath, expr.id); + let def = cx.tables().qpath_def(qpath, expr.id); convert_path_expr(cx, expr, def) } @@ -575,17 +572,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } // Now comes the rote stuff: - hir::ExprRepeat(ref v, c) => { - let c = &cx.tcx.map.body(c).value; + hir::ExprRepeat(ref v, count) => { + let tcx = cx.tcx.global_tcx(); + let c = &cx.tcx.map.body(count).value; + let count = match ConstContext::new(tcx, count).eval(c, EvalHint::ExprTypeChecked) { + Ok(ConstVal::Integral(ConstInt::Usize(u))) => u, + Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other), + Err(s) => fatal_const_eval_err(tcx, &s, c.span, "expression") + }; + ExprKind::Repeat { value: v.to_ref(), count: TypedConstVal { - ty: cx.tcx.tables().expr_ty(c), + ty: cx.tcx.types.usize, span: c.span, - value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) { - ConstVal::Integral(ConstInt::Usize(u)) => u, - other => bug!("constant evaluation of repeat count yielded {:?}", other), - }, + value: count } } } @@ -627,7 +628,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } hir::ExprField(ref source, name) => { - let index = match cx.tcx.tables().expr_ty_adjusted(source).sty { + let index = match cx.tables().expr_ty_adjusted(source).sty { ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node), ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty), }; @@ -679,7 +680,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &hir::Expr, method_call: ty::MethodCall) -> Expr<'tcx> { - let callee = cx.tcx.tables().method_map[&method_call]; + let callee = cx.tables().method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); Expr { temp_lifetime: temp_lifetime, @@ -703,7 +704,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { - patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, p)).collect(), + patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, cx.tables(), p)).collect(), guard: arm.guard.to_ref(), body: arm.body.to_ref(), } @@ -713,9 +714,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, def: Def) -> ExprKind<'tcx> { - let substs = cx.tcx - .tables() - .node_id_item_substs(expr.id) + let substs = cx.tables().node_id_item_substs(expr.id) .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let def_id = match def { // A regular function, constructor function or a constant. @@ -728,7 +727,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::StructCtor(def_id, CtorKind::Const) | Def::VariantCtor(def_id, CtorKind::Const) => { - match cx.tcx.tables().node_id_to_type(expr.id).sty { + match cx.tables().node_id_to_type(expr.id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. ty::TyAdt(adt_def, substs) => { @@ -776,7 +775,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, id_var, index, closure_expr_id); - let var_ty = cx.tcx.tables().node_id_to_type(id_var); + let var_ty = cx.tables().node_id_to_type(id_var); let body_id = match cx.tcx.map.find(closure_expr_id) { Some(map::NodeExpr(expr)) => { @@ -793,7 +792,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; // FIXME free regions in closures are not right - let closure_ty = cx.tcx.tables().node_id_to_type(closure_expr_id); + let closure_ty = cx.tables().node_id_to_type(closure_expr_id); // FIXME we're just hard-coding the idea that the // signature will be &self or &mut self and hence will @@ -869,7 +868,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) { + let upvar_capture = match cx.tables().upvar_capture(upvar_id) { Some(c) => c, None => { span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id); @@ -948,7 +947,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); argrefs.extend(args.iter() .map(|arg| { - let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg); + let arg_ty = cx.tables().expr_ty_adjusted(arg); let adjusted_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: arg_ty, @@ -990,7 +989,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // line up (this is because `*x` and `x[y]` represent lvalues): // to find the type &T of the content returned by the method; - let ref_ty = cx.tcx.tables().method_map[&method_call].ty.fn_ret(); + let ref_ty = cx.tables().method_map[&method_call].ty.fn_ret(); let ref_ty = cx.tcx.no_late_bound_regions(&ref_ty).unwrap(); // callees always have all late-bound regions fully instantiated, @@ -1019,9 +1018,9 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tcx.tables().upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id); - let var_ty = cx.tcx.tables().node_id_to_type(id_var); + let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { temp_lifetime: temp_lifetime, ty: var_ty, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 7d111fccd0056..4b553a71b8325 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,9 +18,8 @@ use hair::*; use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; -use rustc_const_eval as const_eval; +use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; use rustc_data_structures::indexed_vec::Idx; -use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; use rustc::hir::map::blocks::FnLikeNode; use rustc::infer::InferCtxt; @@ -52,17 +51,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { MirSource::Promoted(..) => bug!(), }; - let src_node_id = src.item_id(); - - // We are going to be accessing various tables - // generated by TypeckItemBody; we also assume - // that the body passes type check. These tables - // are not individually tracked, so just register - // a read here. - let src_def_id = infcx.tcx.map.local_def_id(src_node_id); - infcx.tcx.dep_graph.read(DepNode::TypeckItemBody(src_def_id)); - - let attrs = infcx.tcx.map.attrs(src_node_id); + let attrs = infcx.tcx.map.attrs(src.item_id()); // Some functions always have overflow checks enabled, // however, they may not get codegen'd, depending on @@ -128,7 +117,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { - Literal::Value { value: const_eval::eval_const_expr(self.tcx.global_tcx(), e) } + let tcx = self.tcx.global_tcx(); + match ConstContext::with_tables(tcx, self.tables()).eval(e, EvalHint::ExprTypeChecked) { + Ok(value) => Literal::Value { value: value }, + Err(s) => fatal_const_eval_err(tcx, &s, e.span, "expression") + } } pub fn trait_method(&mut self, @@ -177,6 +170,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx } + pub fn tables(&self) -> &'a ty::Tables<'gcx> { + self.infcx.tables.expect_interned() + } + pub fn check_overflow(&self) -> bool { self.check_overflow } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a608275cefa06..e7493850aa7cd 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -17,7 +17,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![crate_name = "rustc_mir"] #![crate_type = "rlib"] #![crate_type = "dylib"] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![unstable(feature = "rustc_private", issue = "27812")] #![feature(associated_consts)] diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index cbc53ea3c51c7..453c3e43b6b86 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -18,19 +18,18 @@ use build; use rustc::dep_graph::DepNode; -use rustc::hir::def_id::DefId; use rustc::mir::Mir; use rustc::mir::transform::MirSource; use rustc::mir::visit::MutVisitor; use pretty; use hair::cx::Cx; -use rustc::infer::InferCtxtBuilder; +use rustc::infer::InferCtxt; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use rustc::hir; -use rustc::hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap}; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use syntax::abi::Abi; use syntax::ast; use syntax_pos::Span; @@ -80,34 +79,50 @@ struct BuildMir<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -/// Helper type of a temporary returned by BuildMir::cx(...). -/// Necessary because we can't write the following bound: -/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Cx<'b, 'gcx, 'tcx>). -struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - src: MirSource, - def_id: DefId, - infcx: InferCtxtBuilder<'a, 'gcx, 'tcx> -} +fn build<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + body_id: hir::BodyId) + -> (Mir<'tcx>, MirSource) { + let tcx = infcx.tcx.global_tcx(); -impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { - fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id()); - let def_id = self.tcx.map.local_def_id(src.item_id()); - CxBuilder { - src: src, - infcx: self.tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable), - def_id: def_id - } + let item_id = tcx.map.body_owner(body_id); + let src = MirSource::from_node(tcx, item_id); + let cx = Cx::new(infcx, src); + if let MirSource::Fn(id) = src { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); + + let ty = tcx.item_type(tcx.map.local_def_id(id)); + let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty { + (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None))) + } else { + (ty.fn_abi(), None) + }; + + let body = tcx.map.body(body_id); + let explicit_arguments = + body.arguments + .iter() + .enumerate() + .map(|(index, arg)| { + (fn_sig.inputs()[index], Some(&*arg.pat)) + }); + + let arguments = implicit_argument.into_iter().chain(explicit_arguments); + (build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src) + } else { + (build::construct_const(cx, body_id), src) } } -impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { - fn build(&'tcx mut self, f: F) - where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> Mir<'tcx> - { - let (src, def_id) = (self.src, self.def_id); - self.infcx.enter(|infcx| { - let mut mir = f(Cx::new(&infcx, src)); +impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let (mut mir, src) = build(&infcx, body_id); // Convert the Mir to global types. let tcx = infcx.tcx.global_tcx(); @@ -117,152 +132,32 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { }; globalizer.visit_mir(&mut mir); let mir = unsafe { - mem::transmute::>(mir) + mem::transmute::>(mir) }; pretty::dump_mir(tcx, "mir_map", &0, src, &mir); let mir = tcx.alloc_mir(mir); + let def_id = tcx.map.local_def_id(src.item_id()); assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none()); }); - } -} - -impl<'a, 'gcx> BuildMir<'a, 'gcx> { - fn build_const_integer(&mut self, body: hir::BodyId) { - let body = self.tcx.map.body(body); - // FIXME(eddyb) Closures should have separate - // function definition IDs and expression IDs. - // Type-checking should not let closures get - // this far in an integer constant position. - if let hir::ExprClosure(..) = body.value.node { - return; - } - self.cx(MirSource::Const(body.value.id)).build(|cx| { - build::construct_const(cx, body.value.id, body.id()) - }); - } -} - -impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) - } - - // Const and static items. - fn visit_item(&mut self, item: &'tcx hir::Item) { - match item.node { - hir::ItemConst(_, expr) => { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - hir::ItemStatic(_, m, expr) => { - self.cx(MirSource::Static(item.id, m)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - _ => {} - } - intravisit::walk_item(self, item); - } - - // Trait associated const defaults. - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::TraitItemKind::Const(_, Some(expr)) = item.node { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - intravisit::walk_trait_item(self, item); - } - - // Impl associated const. - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, expr) = item.node { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - intravisit::walk_impl_item(self, item); - } - - // Repeat counts, i.e. [expr; constant]. - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if let hir::ExprRepeat(_, count) = expr.node { - self.build_const_integer(count); - } - intravisit::walk_expr(self, expr); - } - - // Array lengths, i.e. [T; constant]. - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyArray(_, length) = ty.node { - self.build_const_integer(length); - } - intravisit::walk_ty(self, ty); - } - - // Enum variant discriminant values. - fn visit_variant(&mut self, v: &'tcx hir::Variant, - g: &'tcx hir::Generics, item_id: ast::NodeId) { - if let Some(expr) = v.node.disr_expr { - self.build_const_integer(expr); - } - intravisit::walk_variant(self, v, g, item_id); - } - - fn visit_fn(&mut self, - fk: FnKind<'tcx>, - decl: &'tcx hir::FnDecl, - body_id: hir::BodyId, - span: Span, - id: ast::NodeId) { - // fetch the fully liberated fn signature (that is, all bound - // types/lifetimes replaced) - let fn_sig = match self.tcx.tables().liberated_fn_sigs.get(&id) { - Some(f) => f.clone(), - None => { - span_bug!(span, "no liberated fn sig for {:?}", id); - } - }; - - let (abi, implicit_argument) = if let FnKind::Closure(..) = fk { - (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None))) - } else { - let def_id = self.tcx.map.local_def_id(id); - (self.tcx.item_type(def_id).fn_abi(), None) - }; let body = self.tcx.map.body(body_id); - let explicit_arguments = - body.arguments - .iter() - .enumerate() - .map(|(index, arg)| { - (fn_sig.inputs()[index], Some(&*arg.pat)) - }); - - let arguments = implicit_argument.into_iter().chain(explicit_arguments); - self.cx(MirSource::Fn(id)).build(|cx| { - build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) - }); - - intravisit::walk_fn(self, fk, decl, body_id, span, id); + self.visit_body(body); } } fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, closure_expr_id: ast::NodeId, - body_id: ast::NodeId) + body_id: hir::BodyId) -> Ty<'tcx> { - let closure_ty = tcx.tables().node_id_to_type(closure_expr_id); + let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id); // We're just hard-coding the idea that the signature will be // &self or &mut self and hence will have a bound region with // number 0, hokey. let region = ty::Region::ReFree(ty::FreeRegion { - scope: tcx.region_maps.item_extent(body_id), + scope: tcx.region_maps.item_extent(body_id.node_id), bound_region: ty::BoundRegion::BrAnon(0), }); let region = tcx.mk_region(region); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 2a4b2b515cc68..ec678339066bc 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -97,11 +97,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { // Ignore drops, if the temp gets promoted, // then it's constant and thus drop is noop. // Storage live ranges are also irrelevant. - match context { - LvalueContext::Drop | - LvalueContext::StorageLive | - LvalueContext::StorageDead => return, - _ => {} + if context.is_drop() || context.is_storage_marker() { + return; } let temp = &mut self.temps[index]; @@ -118,15 +115,17 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { _ => { /* mark as unpromotable below */ } } } else if let TempState::Defined { ref mut uses, .. } = *temp { - match context { - LvalueContext::Borrow {..} | - LvalueContext::Consume | - LvalueContext::Inspect => { - *uses += 1; - return; - } - _ => { /* mark as unpromotable below */ } + // We always allow borrows, even mutable ones, as we need + // to promote mutable borrows of some ZSTs e.g. `&mut []`. + let allowed_use = match context { + LvalueContext::Borrow {..} => true, + _ => context.is_nonmutating_use() + }; + if allowed_use { + *uses += 1; + return; } + /* mark as unpromotable below */ } *temp = TempState::Unpromotable; } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index d144651fb7db6..fea27ee5c5483 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1038,7 +1038,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, ty, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 4c86331a52576..0fabbe6678ad8 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -725,7 +725,7 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { return; } let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); - tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut checker = TypeChecker::new(&infcx, src.item_id()); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index d1d9a201567bb..8f12817511ad3 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -26,10 +26,9 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::CastKind; -use rustc_const_eval::{ConstEvalErr, compare_lit_exprs}; -use rustc_const_eval::{eval_const_expr_partial}; +use rustc_const_eval::{ConstEvalErr, ConstContext}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; -use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; +use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath, BadType}; use rustc_const_eval::ErrKind::UnresolvedPath; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_math::{ConstMathErr, Op}; @@ -61,15 +60,18 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { promotable: bool, mut_rvalue_borrows: NodeSet, param_env: ty::ParameterEnvironment<'tcx>, + tables: &'a ty::Tables<'tcx>, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn check_const_eval(&self, expr: &'gcx hir::Expr) { - if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + if let Err(err) = const_cx.eval(expr, ExprTypeChecked) { match err.kind { UnimplementedConstVal(_) => {} IndexOpFeatureGated => {} ErroneousReferencedConstant(_) => {} + BadType(_) => {} _ => { self.tcx.sess.add_lint(CONST_ERR, expr.id, @@ -111,8 +113,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { NestedVisitorMap::None } - fn visit_nested_body(&mut self, body: hir::BodyId) { - match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body.node_id) { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body_id.node_id) { Entry::Occupied(_) => return, Entry::Vacant(entry) => { // Prevent infinite recursion on re-entry. @@ -120,7 +122,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } } - let item_id = self.tcx.map.body_owner(body); + let item_id = self.tcx.map.body_owner(body_id); let outer_in_fn = self.in_fn; self.in_fn = match MirSource::from_node(self.tcx, item_id) { @@ -128,19 +130,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { _ => false }; - let body = self.tcx.map.body(body); + let outer_tables = self.tables; + self.tables = self.tcx.item_tables(self.tcx.map.local_def_id(item_id)); + + let body = self.tcx.map.body(body_id); if !self.in_fn { self.check_const_eval(&body.value); } - let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - let outer_param_env = mem::replace(&mut self.param_env, param_env); - self.tcx.infer_ctxt(None, Some(self.param_env.clone()), Reveal::NotSpecializable) - .enter(|infcx| euv::ExprUseVisitor::new(self, &infcx).consume_body(body)); + let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let param_env = infcx.parameter_environment.clone(); + let outer_penv = mem::replace(&mut self.param_env, param_env); + euv::ExprUseVisitor::new(self, &infcx).consume_body(body); + outer_penv + }); self.visit_body(body); - self.param_env = outer_param_env; + self.param_env = outer_penv; + self.tables = outer_tables; self.in_fn = outer_in_fn; } @@ -150,10 +158,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(lit); } PatKind::Range(ref start, ref end) => { - self.check_const_eval(start); - self.check_const_eval(end); - - match compare_lit_exprs(self.tcx, p.span, start, end) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + match const_cx.compare_lit_exprs(p.span, start, end) { Ok(Ordering::Less) | Ok(Ordering::Equal) => {} Ok(Ordering::Greater) => { @@ -193,7 +199,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { let outer = self.promotable; self.promotable = true; - let node_ty = self.tcx.tables().node_id_to_type(ex.id); + let node_ty = self.tables.node_id_to_type(ex.id); check_expr(self, ex, node_ty); check_adjustments(self, ex); @@ -219,7 +225,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } if self.in_fn && self.promotable { - match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + match const_cx.eval(ex, ExprTypeChecked) { Ok(_) => {} Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) | Err(ConstEvalErr { kind: MiscCatchAll, .. }) | @@ -230,6 +237,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), .. }) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), .. }) | Err(ConstEvalErr { kind: IndexOpFeatureGated, .. }) => {} + Err(ConstEvalErr { kind: BadType(_), .. }) => {} Err(msg) => { self.tcx.sess.add_lint(CONST_ERR, ex.id, @@ -262,14 +270,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node match e.node { hir::ExprUnary(..) | hir::ExprBinary(..) | - hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => { + hir::ExprIndex(..) if v.tables.method_map.contains_key(&method_call) => { v.promotable = false; } hir::ExprBox(_) => { v.promotable = false; } hir::ExprUnary(op, ref inner) => { - match v.tcx.tables().node_id_to_type(inner.id).sty { + match v.tables.node_id_to_type(inner.id).sty { ty::TyRawPtr(_) => { assert!(op == hir::UnDeref); @@ -279,7 +287,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprBinary(op, ref lhs, _) => { - match v.tcx.tables().node_id_to_type(lhs.id).sty { + match v.tables.node_id_to_type(lhs.id).sty { ty::TyRawPtr(_) => { assert!(op.node == hir::BiEq || op.node == hir::BiNe || op.node == hir::BiLe || op.node == hir::BiLt || @@ -301,7 +309,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprPath(ref qpath) => { - let def = v.tcx.tables().qpath_def(qpath, e.id); + let def = v.tables.qpath_def(qpath, e.id); match def { Def::VariantCtor(..) | Def::StructCtor(..) | Def::Fn(..) | Def::Method(..) => {} @@ -337,7 +345,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } // The callee is an arbitrary expression, it doesn't necessarily have a definition. let def = if let hir::ExprPath(ref qpath) = callee.node { - v.tcx.tables().qpath_def(qpath, callee.id) + v.tables.qpath_def(qpath, callee.id) } else { Def::Err }; @@ -359,14 +367,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let method = v.tcx.tables().method_map[&method_call]; + let method = v.tables.method_map[&method_call]; match v.tcx.associated_item(method.def_id).container { ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty), ty::TraitContainer(_) => v.promotable = false } } hir::ExprStruct(..) => { - if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty { + if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { v.promotable = false; @@ -420,7 +428,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { use rustc::ty::adjustment::*; - match v.tcx.tables().adjustments.get(&e.id).map(|adj| adj.kind) { + match v.tables.adjustments.get(&e.id).map(|adj| adj.kind) { None | Some(Adjust::NeverToAny) | Some(Adjust::ReifyFnPointer) | @@ -429,7 +437,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp Some(Adjust::DerefRef { autoderefs, .. }) => { if (0..autoderefs as u32) - .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { + .any(|autoderef| v.tables.is_overloaded_autoderef(e.id, autoderef)) { v.promotable = false; } } @@ -440,6 +448,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.visit_all_item_likes_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor { tcx: tcx, + tables: &ty::Tables::empty(), in_fn: false, promotable: false, mut_rvalue_borrows: NodeSet(), diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 670ef426c2dd5..143c1efed5a93 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(rustc_diagnostic_macros)] #![feature(staged_api)] diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index 3da4f24b6c2fe..78b591a48cca5 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -14,11 +14,11 @@ use rustc::dep_graph::DepNode; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; -use rustc::ty::{self, TyCtxt, ParameterEnvironment}; +use rustc::ty::{self, TyCtxt}; use rustc::traits::Reveal; use rustc::hir; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use syntax::ast; use syntax_pos::Span; @@ -33,28 +33,19 @@ struct RvalueContext<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } - fn visit_fn(&mut self, - fk: intravisit::FnKind<'tcx>, - fd: &'tcx hir::FnDecl, - b: hir::BodyId, - s: Span, - fn_id: ast::NodeId) { - // FIXME (@jroesch) change this to be an inference context - let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - self.tcx.infer_ctxt(None, Some(param_env.clone()), - Reveal::NotSpecializable).enter(|infcx| { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + let body = self.tcx.map.body(body_id); + self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { let mut delegate = RvalueContextDelegate { tcx: infcx.tcx, - param_env: ¶m_env + param_env: &infcx.parameter_environment }; - let body = infcx.tcx.map.body(b); - let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); - euv.consume_body(body); + euv::ExprUseVisitor::new(&mut delegate, &infcx).consume_body(body); }); - intravisit::walk_fn(self, fk, fd, b, s, fn_id) + self.visit_body(body); } } diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index e814050e96097..296c133115f4e 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -13,7 +13,7 @@ #![crate_type = "dylib"] #![crate_type = "rlib"] #![feature(staged_api)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![allow(bad_style)] pub struct Intrinsic { diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 91e0fd636c9c1..8d4e61ad8e54e 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -57,7 +57,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(staged_api)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 81863a3fadfd3..ef7a1f695ffb4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -392,6 +392,7 @@ struct PrivacyVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, curitem: DefId, in_foreign: bool, + tables: &'a ty::Tables<'tcx>, } impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { @@ -435,6 +436,14 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { NestedVisitorMap::All(&self.tcx.map) } + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; + } + fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_curitem = replace(&mut self.curitem, self.tcx.map.local_def_id(item.id)); intravisit::walk_item(self, item); @@ -445,12 +454,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method = self.tcx.tables().method_map[&method_call]; + let method = self.tables.method_map[&method_call]; self.check_method(expr.span, method.def_id); } hir::ExprStruct(ref qpath, ref expr_fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); - let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap(); + let def = self.tables.qpath_def(qpath, expr.id); + let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields @@ -511,15 +520,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { match pattern.node { PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, pattern.id); - let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap(); + let def = self.tables.qpath_def(qpath, pattern.id); + let adt = self.tables.pat_ty(pattern).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); for field in fields { self.check_field(field.span, adt, variant.field_named(field.node.name)); } } PatKind::TupleStruct(_, ref fields, ddpos) => { - match self.tcx.tables().pat_ty(pattern).sty { + match self.tables.pat_ty(pattern).sty { // enum fields have no privacy at this time ty::TyAdt(def, _) if !def.is_enum() => { let expected_len = def.struct_variant().fields.len(); @@ -1203,6 +1212,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, curitem: DefId::local(CRATE_DEF_INDEX), in_foreign: false, tcx: tcx, + tables: &ty::Tables::empty(), }; intravisit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1eeb356480cf2..39a9194cf5e60 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 093a739c69ffa..424017ebd12bb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -99,7 +99,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } - fn nest(&mut self, scope_id: NodeId, f: F) + fn nest_scope(&mut self, scope_id: NodeId, f: F) where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>) { let parent_scope = self.cur_scope; @@ -108,6 +108,16 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.cur_scope = parent_scope; } + fn nest_tables(&mut self, item_id: NodeId, f: F) + where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>) + { + let old_tables = self.save_ctxt.tables; + let item_def_id = self.tcx.map.local_def_id(item_id); + self.save_ctxt.tables = self.tcx.item_tables(item_def_id); + f(self); + self.save_ctxt.tables = old_tables; + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -337,7 +347,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&arg.pat); let span_utils = self.span.clone(); for &(id, ref p, ..) in &collector.collected_paths { - let typ = match self.tcx.tables().node_types.get(&id) { + let typ = match self.save_ctxt.tables.node_types.get(&id) { Some(s) => s.to_string(), None => continue, }; @@ -378,7 +388,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { - self.process_formals(&sig.decl.inputs, &method_data.qualname); + self.nest_tables(id, |v| { + v.process_formals(&sig.decl.inputs, &method_data.qualname) + }); } // If the method is defined in an impl, then try and find the corresponding @@ -448,7 +460,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // walk the fn body if let Some(body) = body { - self.nest(id, |v| v.visit_block(body)); + self.nest_tables(id, |v| v.nest_scope(id, |v| v.visit_block(body))); } } @@ -520,7 +532,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.function(fn_data.clone().lower(self.tcx)); } - self.process_formals(&decl.inputs, &fn_data.qualname); + self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); } @@ -532,7 +544,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_ty(&ret_ty); } - self.nest(item.id, |v| v.visit_block(&body)); + self.nest_tables(item.id, |v| v.nest_scope(item.id, |v| v.visit_block(&body))); } fn process_static_or_const_item(&mut self, @@ -991,7 +1003,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { match p.node { PatKind::Struct(ref path, ref fields, _) => { visit::walk_path(self, path); - let adt = match self.tcx.tables().node_id_to_type_opt(p.id) { + let adt = match self.save_ctxt.tables.node_id_to_type_opt(p.id) { Some(ty) => ty.ty_adt_def().unwrap(), None => { visit::walk_pat(self, p); @@ -1032,7 +1044,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ast::Mutability::Immutable => value.to_string(), _ => String::new(), }; - let typ = match self.tcx.tables().node_types.get(&id) { + let typ = match self.save_ctxt.tables.node_types.get(&id) { Some(typ) => { let typ = typ.to_string(); if !value.is_empty() { @@ -1286,7 +1298,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, self.process_trait(item, generics, trait_refs, methods), Mod(ref m) => { self.process_mod(item); - self.nest(item.id, |v| visit::walk_mod(v, m)); + self.nest_scope(item.id, |v| visit::walk_mod(v, m)); } Ty(ref ty, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); @@ -1349,6 +1361,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visit::walk_path(self, path); } + ast::TyKind::Array(ref element, ref length) => { + self.visit_ty(element); + self.nest_tables(length.id, |v| v.visit_expr(length)); + } _ => visit::walk_ty(self, t), } } @@ -1367,7 +1383,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id); - let adt = match self.tcx.tables().expr_ty_opt(&hir_expr) { + let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) { Some(ty) => ty.ty_adt_def().unwrap(), None => { visit::walk_expr(self, ex); @@ -1399,7 +1415,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, return; } }; - let ty = match self.tcx.tables().expr_ty_adjusted_opt(&hir_node) { + let ty = match self.save_ctxt.tables.expr_ty_adjusted_opt(&hir_node) { Some(ty) => &ty.sty, None => { visit::walk_expr(self, ex); @@ -1427,7 +1443,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => { let mut id = String::from("$"); id.push_str(&ex.id.to_string()); - self.process_formals(&decl.inputs, &id); // walk arg and return types for arg in &decl.inputs { @@ -1439,7 +1454,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } // walk the body - self.nest(ex.id, |v| v.visit_expr(body)); + self.nest_tables(ex.id, |v| { + v.process_formals(&decl.inputs, &id); + v.nest_scope(ex.id, |v| v.visit_expr(body)) + }); } ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) | ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => { @@ -1455,6 +1473,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visit::walk_block(self, block); opt_else.as_ref().map(|el| visit::walk_expr(self, el)); } + ast::ExprKind::Repeat(ref element, ref count) => { + self.visit_expr(element); + self.nest_tables(count.id, |v| v.visit_expr(count)); + } _ => { visit::walk_expr(self, ex) } @@ -1492,7 +1514,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } else { "".to_string() }; - let typ = self.tcx.tables().node_types + let typ = self.save_ctxt.tables.node_types .get(&id).map(|t| t.to_string()).unwrap_or(String::new()); value.push_str(": "); value.push_str(&typ); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 43e3b1dd2b50a..0fbe29880b999 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -15,7 +15,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(custom_attribute)] #![allow(unused_attributes)] @@ -84,6 +84,7 @@ pub mod recorder { pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, + tables: &'l ty::Tables<'tcx>, analysis: &'l ty::CrateAnalysis<'tcx>, span_utils: SpanUtils<'tcx>, } @@ -93,24 +94,6 @@ macro_rules! option_try( ); impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { - pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>, - analysis: &'l ty::CrateAnalysis<'tcx>) - -> SaveContext<'l, 'tcx> { - let span_utils = SpanUtils::new(&tcx.sess); - SaveContext::from_span_utils(tcx, analysis, span_utils) - } - - pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx, 'tcx>, - analysis: &'l ty::CrateAnalysis<'tcx>, - span_utils: SpanUtils<'tcx>) - -> SaveContext<'l, 'tcx> { - SaveContext { - tcx: tcx, - analysis: analysis, - span_utils: span_utils, - } - } - // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec { let mut result = Vec::new(); @@ -460,7 +443,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { let hir_node = self.tcx.map.expect_expr(expr.id); - let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node); + let ty = self.tables.expr_ty_adjusted_opt(&hir_node); if ty.is_none() || ty.unwrap().sty == ty::TyError { return None; } @@ -474,7 +457,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { return None; } }; - match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); @@ -493,7 +476,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::Struct(ref path, ..) => { - match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); @@ -514,7 +497,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method_id = self.tcx.tables().method_map[&method_call].def_id; + let method_id = self.tables.method_map[&method_call].def_id; let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), @@ -551,7 +534,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => { - self.tcx.tables().qpath_def(qpath, id) + self.tables.qpath_def(qpath, id) } Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { @@ -914,7 +897,12 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, root_path.pop(); let output = &mut output_file; - let save_ctxt = SaveContext::new(tcx, analysis); + let save_ctxt = SaveContext { + tcx: tcx, + tables: &ty::Tables::empty(), + analysis: analysis, + span_utils: SpanUtils::new(&tcx.sess), + }; macro_rules! dump { ($new_dumper: expr) => {{ diff --git a/src/librustc_trans/back/rpath.rs b/src/librustc_trans/back/rpath.rs index ccaa0d4e1b1b0..9c982be3fa03e 100644 --- a/src/librustc_trans/back/rpath.rs +++ b/src/librustc_trans/back/rpath.rs @@ -51,7 +51,13 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec { fn rpaths_to_flags(rpaths: &[String]) -> Vec { let mut ret = Vec::new(); for rpath in rpaths { - ret.push(format!("-Wl,-rpath,{}", &(*rpath))); + if rpath.contains(',') { + ret.push("-Wl,-rpath".into()); + ret.push("-Xlinker".into()); + ret.push(rpath.clone()); + } else { + ret.push(format!("-Wl,-rpath,{}", &(*rpath))); + } } return ret; } @@ -258,4 +264,19 @@ mod tests { assert_eq!(res, "$ORIGIN/../lib"); } } + + #[test] + fn test_xlinker() { + let args = rpaths_to_flags(&[ + "a/normal/path".to_string(), + "a,comma,path".to_string() + ]); + + assert_eq!(args, vec![ + "-Wl,-rpath,a/normal/path".to_string(), + "-Wl,-rpath".to_string(), + "-Xlinker".to_string(), + "a,comma,path".to_string() + ]); + } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 257d6c01e4a65..58d0c46850353 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -234,18 +234,37 @@ fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, trait_closure_kind={:?}, llfn={:?})", llfn_closure_kind, trait_closure_kind, Value(llfn)); - match (llfn_closure_kind, trait_closure_kind) { + match needs_fn_once_adapter_shim(llfn_closure_kind, trait_closure_kind) { + Ok(true) => trans_fn_once_adapter_shim(ccx, + def_id, + substs, + method_instance, + llfn), + Ok(false) => llfn, + Err(()) => { + bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}", + llfn_closure_kind, + trait_closure_kind); + } + } +} + +pub fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind, + trait_closure_kind: ty::ClosureKind) + -> Result +{ + match (actual_closure_kind, trait_closure_kind) { (ty::ClosureKind::Fn, ty::ClosureKind::Fn) | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) | (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => { // No adapter needed. - llfn + Ok(false) } (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => { // The closure fn `llfn` is a `fn(&self, ...)`. We want a // `fn(&mut self, ...)`. In fact, at trans time, these are // basically the same thing, so we can just return llfn. - llfn + Ok(false) } (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => { @@ -257,13 +276,9 @@ fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, // fn call_once(mut self, ...) { call_mut(&mut self, ...) } // // These are both the same at trans time. - trans_fn_once_adapter_shim(ccx, def_id, substs, method_instance, llfn) - } - _ => { - bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}", - llfn_closure_kind, - trait_closure_kind); + Ok(true) } + _ => Err(()), } } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 2bc42a461528d..ff8a14474e57d 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -205,6 +205,7 @@ use rustc::mir::visit::Visitor as MirVisitor; use syntax::abi::Abi; use syntax_pos::DUMMY_SP; use base::custom_coerce_unsize_info; +use callee::needs_fn_once_adapter_shim; use context::SharedCrateContext; use common::fulfill_obligation; use glue::{self, DropGlueKind}; @@ -568,7 +569,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { callee_substs, self.param_substs); - if let Some((callee_def_id, callee_substs)) = dispatched { + if let StaticDispatchResult::Dispatched { + def_id: callee_def_id, + substs: callee_substs, + fn_once_adjustment, + } = dispatched { // if we have a concrete impl (which we might not have // in the case of something compiler generated like an // object shim or a closure that is handled differently), @@ -581,6 +586,17 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { callee_substs, self.param_substs); self.output.push(trans_item); + + // This call will instantiate an FnOnce adapter, which drops + // the closure environment. Therefore we need to make sure + // that we collect the drop-glue for the environment type. + if let Some(env_ty) = fn_once_adjustment { + let env_ty = glue::get_drop_glue_type(self.scx, env_ty); + if self.scx.type_needs_drop(env_ty) { + let dg = DropGlueKind::Ty(env_ty); + self.output.push(TransItem::DropGlue(dg)); + } + } } } } @@ -793,15 +809,13 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, bug!("encountered unexpected type"); } } - - } fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, fn_def_id: DefId, fn_substs: &'tcx Substs<'tcx>, param_substs: &'tcx Substs<'tcx>) - -> Option<(DefId, &'tcx Substs<'tcx>)> { + -> StaticDispatchResult<'tcx> { debug!("do_static_dispatch(fn_def_id={}, fn_substs={:?}, param_substs={:?})", def_id_to_string(scx.tcx(), fn_def_id), fn_substs, @@ -818,10 +832,30 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, debug!(" => regular function"); // The function is not part of an impl or trait, no dispatching // to be done - Some((fn_def_id, fn_substs)) + StaticDispatchResult::Dispatched { + def_id: fn_def_id, + substs: fn_substs, + fn_once_adjustment: None, + } } } +enum StaticDispatchResult<'tcx> { + // The call could be resolved statically as going to the method with + // `def_id` and `substs`. + Dispatched { + def_id: DefId, + substs: &'tcx Substs<'tcx>, + + // If this is a call to a closure that needs an FnOnce adjustment, + // this contains the new self type of the call (= type of the closure + // environment) + fn_once_adjustment: Option>, + }, + // This goes to somewhere that we don't know at compile-time + Unknown +} + // Given a trait-method and substitution information, find out the actual // implementation of the trait method. fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, @@ -829,7 +863,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, trait_id: DefId, callee_substs: &'tcx Substs<'tcx>, param_substs: &'tcx Substs<'tcx>) - -> Option<(DefId, &'tcx Substs<'tcx>)> { + -> StaticDispatchResult<'tcx> { let tcx = scx.tcx(); debug!("do_static_trait_method_dispatch(trait_method={}, \ trait_id={}, \ @@ -850,17 +884,56 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // the actual function: match vtbl { traits::VtableImpl(impl_data) => { - Some(traits::find_method(tcx, trait_method.name, rcvr_substs, &impl_data)) + let (def_id, substs) = traits::find_method(tcx, + trait_method.name, + rcvr_substs, + &impl_data); + StaticDispatchResult::Dispatched { + def_id: def_id, + substs: substs, + fn_once_adjustment: None, + } } traits::VtableClosure(closure_data) => { - Some((closure_data.closure_def_id, closure_data.substs.substs)) + let closure_def_id = closure_data.closure_def_id; + let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap(); + let actual_closure_kind = tcx.closure_kind(closure_def_id); + + let needs_fn_once_adapter_shim = + match needs_fn_once_adapter_shim(actual_closure_kind, + trait_closure_kind) { + Ok(true) => true, + _ => false, + }; + + let fn_once_adjustment = if needs_fn_once_adapter_shim { + Some(tcx.mk_closure_from_closure_substs(closure_def_id, + closure_data.substs)) + } else { + None + }; + + StaticDispatchResult::Dispatched { + def_id: closure_def_id, + substs: closure_data.substs.substs, + fn_once_adjustment: fn_once_adjustment, + } } - // Trait object and function pointer shims are always - // instantiated in-place, and as they are just an ABI-adjusting - // indirect call they do not have any dependencies. - traits::VtableFnPointer(..) | + traits::VtableFnPointer(ref data) => { + // If we know the destination of this fn-pointer, we'll have to make + // sure that this destination actually gets instantiated. + if let ty::TyFnDef(def_id, substs, _) = data.fn_ty.sty { + // The destination of the pointer might be something that needs + // further dispatching, such as a trait method, so we do that. + do_static_dispatch(scx, def_id, substs, param_substs) + } else { + StaticDispatchResult::Unknown + } + } + // Trait object shims are always instantiated in-place, and as they are + // just an ABI-adjusting indirect call they do not have any dependencies. traits::VtableObject(..) => { - None + StaticDispatchResult::Unknown } _ => { bug!("static call to invalid vtable: {:?}", vtbl) @@ -994,8 +1067,19 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, // Walk all methods of the trait, including those of its supertraits let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); let methods = methods.filter_map(|method| method) - .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, - param_substs)) + .filter_map(|(def_id, substs)| { + if let StaticDispatchResult::Dispatched { + def_id, + substs, + // We already add the drop-glue for the closure env + // unconditionally below. + fn_once_adjustment: _ , + } = do_static_dispatch(scx, def_id, substs, param_substs) { + Some((def_id, substs)) + } else { + None + } + }) .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id)) .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs)); output.extend(methods); @@ -1203,6 +1287,7 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, visitor.visit_mir(&mir); for promoted in &mir.promoted { + visitor.mir = promoted; visitor.visit_mir(promoted); } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 13163518f941e..eb6ea8fa94b0a 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -465,7 +465,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let obligation_cause = traits::ObligationCause::misc(span, diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 2e2644d91bb6c..a9c1edfdc66cc 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -95,8 +95,6 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { let sym = ccx.symbol_map() .get(TransItem::Static(id)) .expect("Local statics should always be in the SymbolMap"); - // Make sure that this is never executed for something inlined. - assert!(!ccx.tcx().map.is_inlined_node_id(id)); let defined_in_current_codegen_unit = ccx.codegen_unit() .items() diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 413b643740861..5efdd129a32b8 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -851,7 +851,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout { - self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| { + self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { ty.layout(&infcx).unwrap_or_else(|e| { match e { ty::layout::LayoutError::SizeOverflow(_) => diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index f6428465eda20..1473e55b2643c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1738,14 +1738,6 @@ pub fn create_global_var_metadata(cx: &CrateContext, let tcx = cx.tcx(); - // Don't create debuginfo for globals inlined from other crates. The other - // crate should already contain debuginfo for it. More importantly, the - // global might not even exist in un-inlined form anywhere which would lead - // to a linker errors. - if tcx.map.is_inlined_node_id(node_id) { - return; - } - let node_def_id = tcx.map.local_def_id(node_id); let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 4fe07c9b86abf..b24f00ee6976d 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -80,7 +80,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'t } match t.sty { ty::TyBox(typ) if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) => { - scx.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| { + scx.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { let layout = t.layout(&infcx).unwrap(); if layout.size(&scx.tcx().data_layout).bytes() == 0 { // `Box` does not allocate. diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 3a4171e1d0ec6..d8c0bde963e33 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(box_patterns)] diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 13e659a5ae0e8..9ac2bea3b82fb 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -101,7 +101,6 @@ impl<'tcx> Const<'tcx> { bug!("MIR must not use `{:?}` (which refers to a local ID)", cv) } ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false), - ConstVal::Dummy => bug!(), }; assert!(!ty.has_erasable_regions()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 75c25a605af25..bc984949fc69d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1660,8 +1660,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 } hir::TyArray(ref ty, length) => { - let e = &tcx.map.body(length).value; - if let Ok(length) = eval_length(tcx.global_tcx(), e, "array length") { + if let Ok(length) = eval_length(tcx.global_tcx(), length, "array length") { tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length) } else { self.tcx().types.err diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 9412c9105c7aa..0551887e2e8a0 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -99,10 +99,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_ty.sig, opt_kind); - self.tables.borrow_mut().closure_tys.insert(expr_def_id, fn_ty); + self.tables.borrow_mut().closure_tys.insert(expr.id, fn_ty); match opt_kind { Some(kind) => { - self.tables.borrow_mut().closure_kinds.insert(expr_def_id, kind); + self.tables.borrow_mut().closure_kinds.insert(expr.id, kind); } None => {} } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index be10b77bd8b90..3960dc9edbd27 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -227,7 +227,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_param_env, normalize_cause.clone()); - tcx.infer_ctxt(None, Some(trait_param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| { let inh = Inherited::new(ccx, infcx); let infcx = &inh.infcx; let fulfillment_cx = &inh.fulfillment_cx; @@ -747,7 +747,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); let tcx = ccx.tcx; - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); // The below is for the most part highly similar to the procedure diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index e13c4ea314f06..9cd54bd94c817 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -81,7 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); - tcx.infer_ctxt(None, Some(impl_param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(impl_param_env, Reveal::NotSpecializable).enter(|infcx| { let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5c3da4237bef2..f331c561f0c40 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -801,13 +801,19 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // If so, add "synthetic impls". let steps = self.steps.clone(); for step in steps.iter() { - let closure_def_id = match step.self_ty.sty { - ty::TyClosure(a, _) => a, + let closure_id = match step.self_ty.sty { + ty::TyClosure(def_id, _) => { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + id + } else { + continue; + } + } _ => continue, }; let closure_kinds = &self.tables.borrow().closure_kinds; - let closure_kind = match closure_kinds.get(&closure_def_id) { + let closure_kind = match closure_kinds.get(&closure_id) { Some(&k) => k, None => { return Err(MethodError::ClosureAmbiguity(trait_def_id)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e1cfc64f3c728..ceb97c63d1327 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -105,7 +105,7 @@ use lint; use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap}; -use std::cell::{Cell, Ref, RefCell}; +use std::cell::{Cell, RefCell}; use std::cmp; use std::mem::replace; use std::ops::{self, Deref}; @@ -483,12 +483,11 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> { pub fn inherited(&'a self, id: ast::NodeId) -> InheritedBuilder<'a, 'gcx, 'tcx> { + let tables = ty::Tables::empty(); let param_env = ParameterEnvironment::for_item(self.tcx, id); InheritedBuilder { ccx: self, - infcx: self.tcx.infer_ctxt(Some(ty::Tables::empty()), - Some(param_env), - Reveal::NotSpecializable) + infcx: self.tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable) } } } @@ -612,8 +611,7 @@ pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult { let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeckItemBody(def_id)); let param_env = ParameterEnvironment::for_item(ccx.tcx, item_id); - ccx.tcx.infer_ctxt(None, Some(param_env), - Reveal::NotSpecializable).enter(|infcx| { + ccx.tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); for obligation in obligations.iter().map(|o| o.to_obligation()) { fulfillment_cx.register_predicate_obligation(&infcx, obligation); @@ -681,7 +679,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fcx.select_all_obligations_or_error(); // Casts can introduce new obligations. fcx.regionck_fn(fn_id, body); - fcx.resolve_type_vars_in_body(body, fn_id); + fcx.resolve_type_vars_in_body(body); }); } @@ -1248,7 +1246,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, fcx.select_all_obligations_or_error(); fcx.regionck_expr(body); - fcx.resolve_type_vars_in_body(body, id); + fcx.resolve_type_vars_in_body(body); }); } @@ -1871,17 +1869,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn item_substs(&self) -> Ref>> { - // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if - // it changes when we upgrade the snapshot compiler - fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.item_substs - } - - Ref::map(self.tables.borrow(), project_item_susbts) - } - pub fn opt_node_ty_substs(&self, id: ast::NodeId, f: F) where @@ -3872,8 +3859,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_array(unified, args.len()) } hir::ExprRepeat(ref element, count) => { - let count_expr = &tcx.map.body(count).value; - let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count") + let count = eval_length(self.tcx.global_tcx(), count, "repeat count") .unwrap_or(0); let uty = match expected { diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 5d927a503a116..95da5a97f6750 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -106,8 +106,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { expr: &hir::Expr, capture_clause: hir::CaptureClause) { - let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id); - if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) { + if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn); debug!("check_closure: adding closure {:?} as Fn", expr.id); } @@ -211,8 +210,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // main table and process any deferred resolutions. let closure_def_id = self.fcx.tcx.map.local_def_id(id); if let Some(&kind) = self.temp_closure_kinds.get(&id) { - self.fcx.tables.borrow_mut().closure_kinds - .insert(closure_def_id, kind); + self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind); debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); let mut deferred_call_resolutions = diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 6d32b7364f8ea..02ac7c196b5cb 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -33,10 +33,12 @@ use rustc::hir; // Entry point impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { - pub fn resolve_type_vars_in_body(&self, - body: &'gcx hir::Body, - item_id: ast::NodeId) { + pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) { assert_eq!(self.writeback_errors.get(), false); + + let item_id = self.tcx.map.body_owner(body.id()); + let item_def_id = self.tcx.map.local_def_id(item_id); + let mut wbcx = WritebackCx::new(self); for arg in &body.arguments { wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.id); @@ -49,6 +51,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_anon_types(); wbcx.visit_deferred_obligations(item_id); wbcx.visit_type_nodes(); + + let tables = self.tcx.alloc_tables(wbcx.tables); + self.tcx.tables.borrow_mut().insert(item_def_id, tables); } } @@ -63,6 +68,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, + tables: ty::Tables<'gcx>, + // Mapping from free regions of the function to the // early-bound versions of them, visible from the // outside of the function. This is needed by, and @@ -74,6 +81,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> { let mut wbcx = WritebackCx { fcx: fcx, + tables: ty::Tables::empty(), free_to_bound_regions: DefIdMap() }; @@ -113,10 +121,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tcx } - fn write_ty_to_tcx(&self, node_id: ast::NodeId, ty: Ty<'gcx>) { - debug!("write_ty_to_tcx({}, {:?})", node_id, ty); + fn write_ty_to_tables(&mut self, node_id: ast::NodeId, ty: Ty<'gcx>) { + debug!("write_ty_to_tables({}, {:?})", node_id, ty); assert!(!ty.needs_infer()); - self.tcx().tables.borrow_mut().node_types.insert(node_id, ty); + self.tables.node_types.insert(node_id, ty); } // Hacky hack: During type-checking, we treat *all* operators @@ -228,11 +236,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { self.visit_node_id(ResolvingPattern(p.span), p.id); - debug!("Type for pattern binding {} (id {}) resolved to {:?}", - self.tcx().map.node_to_pretty_string(p.id), - p.id, - self.tcx().tables().node_id_to_type(p.id)); - intravisit::walk_pat(self, p); } @@ -243,13 +246,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { let var_ty = self.fcx.local_ty(l.span, l.id); let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span)); - self.write_ty_to_tcx(l.id, var_ty); + self.write_ty_to_tables(l.id, var_ty); intravisit::walk_local(self, l); } } impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { - fn visit_upvar_borrow_map(&self) { + fn visit_upvar_borrow_map(&mut self) { if self.fcx.writeback_errors.get() { return; } @@ -267,11 +270,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); - self.tcx() - .tables - .borrow_mut() - .upvar_capture_map - .insert(*upvar_id, new_upvar_capture); + self.tables.upvar_capture_map.insert(*upvar_id, new_upvar_capture); } } @@ -280,13 +279,15 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { return } - for (def_id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { - let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); - self.tcx().tables.borrow_mut().closure_tys.insert(*def_id, closure_ty); + for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { + let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); + let def_id = self.tcx().map.local_def_id(id); + self.tcx().closure_tys.borrow_mut().insert(def_id, closure_ty); } - for (def_id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { - self.tcx().tables.borrow_mut().closure_kinds.insert(*def_id, closure_kind); + for (&id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { + let def_id = self.tcx().map.local_def_id(id); + self.tcx().closure_kinds.borrow_mut().insert(def_id, closure_kind); } } @@ -339,10 +340,10 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } } - fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_node_id(&mut self, reason: ResolveReason, id: ast::NodeId) { // Export associated path extensions. if let Some(def) = self.fcx.tables.borrow_mut().type_relative_path_defs.remove(&id) { - self.tcx().tables.borrow_mut().type_relative_path_defs.insert(id, def); + self.tables.type_relative_path_defs.insert(id, def); } // Resolve any borrowings for the node with id `id` @@ -351,7 +352,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { // Resolve the type of the node with id `id` let n_ty = self.fcx.node_ty(id); let n_ty = self.resolve(&n_ty, reason); - self.write_ty_to_tcx(id, n_ty); + self.write_ty_to_tables(id, n_ty); debug!("Node {} has type {:?}", id, n_ty); // Resolve any substitutions @@ -360,12 +361,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if !item_substs.is_noop() { debug!("write_substs_to_tcx({}, {:?})", id, item_substs); assert!(!item_substs.substs.needs_infer()); - self.tcx().tables.borrow_mut().item_substs.insert(id, item_substs); + self.tables.item_substs.insert(id, item_substs); } }); } - fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) { + fn visit_adjustments(&mut self, reason: ResolveReason, id: ast::NodeId) { let adjustments = self.fcx.tables.borrow_mut().adjustments.remove(&id); match adjustments { None => { @@ -408,13 +409,12 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { target: self.resolve(&adjustment.target, reason) }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); - self.tcx().tables.borrow_mut().adjustments.insert( - id, resolved_adjustment); + self.tables.adjustments.insert(id, resolved_adjustment); } } } - fn visit_method_map_entry(&self, + fn visit_method_map_entry(&mut self, reason: ResolveReason, method_call: MethodCall) { // Resolve any method map entry @@ -436,25 +436,25 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { //NB(jroesch): We need to match twice to avoid a double borrow which would cause an ICE if let Some(method) = new_method { - self.tcx().tables.borrow_mut().method_map.insert(method_call, method); + self.tables.method_map.insert(method_call, method); } } - fn visit_liberated_fn_sigs(&self) { + fn visit_liberated_fn_sigs(&mut self) { for (&node_id, fn_sig) in self.fcx.tables.borrow().liberated_fn_sigs.iter() { let fn_sig = self.resolve(fn_sig, ResolvingFnSig(node_id)); - self.tcx().tables.borrow_mut().liberated_fn_sigs.insert(node_id, fn_sig.clone()); + self.tables.liberated_fn_sigs.insert(node_id, fn_sig.clone()); } } - fn visit_fru_field_types(&self) { + fn visit_fru_field_types(&mut self) { for (&node_id, ftys) in self.fcx.tables.borrow().fru_field_types.iter() { let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id)); - self.tcx().tables.borrow_mut().fru_field_types.insert(node_id, ftys); + self.tables.fru_field_types.insert(node_id, ftys); } } - fn visit_deferred_obligations(&self, item_id: ast::NodeId) { + fn visit_deferred_obligations(&mut self, item_id: ast::NodeId) { let deferred_obligations = self.fcx.deferred_obligations.borrow(); let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| { let reason = ResolvingDeferredObligation(obligation.cause.span); @@ -496,7 +496,7 @@ enum ResolveReason { ResolvingLocal(Span), ResolvingPattern(Span), ResolvingUpvar(ty::UpvarId), - ResolvingClosure(DefId), + ResolvingClosure(ast::NodeId), ResolvingFnSig(ast::NodeId), ResolvingFieldTypes(ast::NodeId), ResolvingAnonTy(DefId), @@ -513,12 +513,12 @@ impl<'a, 'gcx, 'tcx> ResolveReason { ResolvingUpvar(upvar_id) => { tcx.expr_span(upvar_id.closure_expr_id) } + ResolvingClosure(id) | ResolvingFnSig(id) | ResolvingFieldTypes(id) | ResolvingTyNode(id) => { tcx.map.span(id) } - ResolvingClosure(did) | ResolvingAnonTy(did) => { tcx.def_span(did) } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index ba95a17989165..57df0fb2cee93 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -205,7 +205,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::ExactMatch).enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index a09bdf0533a15..08293c1d874a8 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -87,7 +87,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { + self.tcx.infer_ctxt((), 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) } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7ddf10375bf23..f832bf8d86e93 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -63,7 +63,7 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; -use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; +use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; @@ -1039,8 +1039,9 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, adt } - fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr) + fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId) -> Option { + let e = &ccx.tcx.map.body(body).value; debug!("disr expr, checking {}", ccx.tcx.map.node_to_pretty_string(e.id)); let ty_hint = repr_ty.to_ty(ccx.tcx); @@ -1052,9 +1053,9 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let hint = UncheckedExprHint(ty_hint); - match eval_const_expr_partial(ccx.tcx, e, hint, None) { + match ConstContext::new(ccx.tcx, body).eval(e, hint) { Ok(ConstVal::Integral(i)) => { - // FIXME: eval_const_expr_partial should return an error if the hint is wrong + // FIXME: eval should return an error if the hint is wrong match (repr_ty, i) { (attr::SignedInt(ast::IntTy::I8), ConstInt::I8(_)) | (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) | @@ -1103,7 +1104,6 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let variants = def.variants.iter().map(|v| { let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr()); let disr = if let Some(e) = v.node.disr_expr { - let e = &tcx.map.body(e).value; evaluate_disr_expr(ccx, repr_type, e) } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) { Some(disr) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ec17813ed2a52..6d30a85b58291 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -70,7 +70,7 @@ This API is completely unstable and subject to change. #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![allow(non_camel_case_types)] @@ -177,7 +177,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + ccx.tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index d66d2001f2304..93c0bd6d6d836 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,6 @@ arena = { path = "../libarena" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_const_eval = { path = "../librustc_const_eval" } -rustc_const_math = { path = "../librustc_const_math" } rustc_driver = { path = "../librustc_driver" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index faf39db572380..6a640e7b5ed80 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1692,22 +1692,10 @@ impl Clean for hir::Ty { BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), type_: box m.ty.clean(cx)}, TySlice(ref ty) => Vector(box ty.clean(cx)), - TyArray(ref ty, e) => { - use rustc_const_math::{ConstInt, ConstUsize}; - use rustc_const_eval::eval_const_expr; - use rustc::middle::const_val::ConstVal; - - let e = &cx.tcx.map.body(e).value; - let n = match eval_const_expr(cx.tcx, e) { - ConstVal::Integral(ConstInt::Usize(u)) => match u { - ConstUsize::Us16(u) => u.to_string(), - ConstUsize::Us32(u) => u.to_string(), - ConstUsize::Us64(u) => u.to_string(), - }, - // after type checking this can't fail - _ => unreachable!(), - }; - FixedVector(box ty.clean(cx), n) + TyArray(ref ty, length) => { + use rustc_const_eval::eval_length; + let n = eval_length(cx.tcx, length, "array length").unwrap(); + FixedVector(box ty.clean(cx), n.to_string()) }, TyTup(ref tys) => Tuple(tys.clean(cx)), TyPath(hir::QPath::Resolved(None, ref path)) => { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 47616044879cd..503ef4c3183d2 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -16,7 +16,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_patterns)] #![feature(box_syntax)] @@ -33,7 +33,6 @@ extern crate getopts; extern crate libc; extern crate rustc; extern crate rustc_const_eval; -extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_trans; extern crate rustc_driver; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 0979860189ca1..cfa09361ccec7 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -25,7 +25,7 @@ Core encoding and decoding interfaces. html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/", test(attr(allow(unused_variables), deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(collections)] diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 2cd9362a65791..1ab62130cd3dd 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -1061,8 +1061,7 @@ impl Clone for RawTable { } } -impl Drop for RawTable { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable { fn drop(&mut self) { if self.capacity == 0 { return; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 84b50f04463fe..175fe30db661c 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -259,6 +259,15 @@ impl OsStr { /// Yields a `&str` slice if the `OsStr` is valid Unicode. /// /// This conversion may entail doing a check for UTF-8 validity. + /// + /// # Examples + /// + /// ``` + /// use std::ffi::OsStr; + /// + /// let os_str = OsStr::new("foo"); + /// assert_eq!(os_str.to_str(), Some("foo")); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_str(&self) -> Option<&str> { self.inner.to_str() @@ -267,6 +276,20 @@ impl OsStr { /// Converts an `OsStr` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. + /// + /// # Examples + /// + /// Calling `to_string_lossy` on an `OsStr` with valid unicode: + /// + /// ``` + /// use std::ffi::OsStr; + /// + /// let os_str = OsStr::new("foo"); + /// assert_eq!(os_str.to_string_lossy(), "foo"); + /// ``` + /// + /// Had `os_str` contained invalid unicode, the `to_string_lossy` call might + /// have returned `"fo�"`. #[stable(feature = "rust1", since = "1.0.0")] pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f1e3996e825bf..08a5c0971b75d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,11 +221,11 @@ // Always use alloc_system during stage0 since jemalloc might be unavailable or // disabled (Issue #30592) -#![cfg_attr(stage0, feature(alloc_system))] +#![cfg_attr(any(stage0, not(feature = "jemalloc")), feature(alloc_system))] // Turn warnings into errors, but only after stage0, where it can be useful for // code to emit warnings during language transitions -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] // std may use features in a platform-specific way #![allow(unused_features)] @@ -250,13 +250,14 @@ #![feature(const_fn)] #![feature(core_float)] #![feature(core_intrinsics)] -#![feature(dropck_parametricity)] +#![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(float_extras)] #![feature(float_from_str_radix)] #![feature(fn_traits)] #![feature(fnbox)] #![feature(fused)] +#![feature(generic_param_attrs)] #![feature(hashmap_hasher)] #![feature(heap_api)] #![feature(inclusive_range)] @@ -332,7 +333,7 @@ extern crate libc; // We always need an unwinder currently for backtraces extern crate unwind; -#[cfg(stage0)] +#[cfg(any(stage0, not(feature = "jemalloc")))] extern crate alloc_system; // compiler-rt intrinsics diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index ed1f08f9c9090..e203789ce81d9 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -52,7 +52,7 @@ pub struct TcpStream(net_imp::TcpStream); /// // ... /// } /// -/// // accept connections and process them, spawning a new thread for each one +/// // accept connections and process them serially /// for stream in listener.incoming() { /// match stream { /// Ok(stream) => { diff --git a/src/libstd/path.rs b/src/libstd/path.rs index d13baea40a9ff..3f9bf70adde22 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1428,8 +1428,8 @@ impl Path { /// ``` /// use std::path::Path; /// - /// let path_str = Path::new("foo.txt").to_str(); - /// assert_eq!(path_str, Some("foo.txt")); + /// let path = Path::new("foo.txt"); + /// assert_eq!(path.to_str(), Some("foo.txt")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn to_str(&self) -> Option<&str> { @@ -1444,12 +1444,17 @@ impl Path { /// /// # Examples /// + /// Calling `to_string_lossy` on a `Path` with valid unicode: + /// /// ``` /// use std::path::Path; /// - /// let path_str = Path::new("foo.txt").to_string_lossy(); - /// assert_eq!(path_str, "foo.txt"); + /// let path = Path::new("foo.txt"); + /// assert_eq!(path.to_string_lossy(), "foo.txt"); /// ``` + /// + /// Had `os_str` contained invalid unicode, the `to_string_lossy` call might + /// have returned `"fo�.txt"`. #[stable(feature = "rust1", since = "1.0.0")] pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 5981b482a9728..ced0288766bb1 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -502,7 +502,7 @@ mod prim_str { } /// [`Hash`]: hash/trait.Hash.html /// /// Due to a temporary restriction in Rust's type system, these traits are only -/// implemented on tuples of arity 32 or less. In the future, this may change. +/// implemented on tuples of arity 12 or less. In the future, this may change. /// /// # Examples /// diff --git a/src/libstd/process.rs b/src/libstd/process.rs index e15c37aaf2491..aa76b79253582 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -260,11 +260,18 @@ impl fmt::Debug for ChildStderr { /// ``` /// use std::process::Command; /// -/// let output = Command::new("sh") -/// .arg("-c") -/// .arg("echo hello") -/// .output() -/// .expect("failed to execute process"); +/// let output = if cfg!(target_os = "windows") { +/// Command::new("cmd") +/// .args(&["/C", "echo hello"]) +/// .output() +/// .expect("failed to execute process") +/// } else { +/// Command::new("sh") +/// .arg("-c") +/// .arg("echo hello") +/// .output() +/// .expect("failed to execute process") +/// }; /// /// let hello = output.stdout; /// ``` @@ -793,6 +800,48 @@ impl Child { self.handle.wait().map(ExitStatus) } + /// Attempts to collect the exit status of the child if it has already + /// exited. + /// + /// This function will not block the calling thread and will only advisorily + /// check to see if the child process has exited or not. If the child has + /// exited then on Unix the process id is reaped. This function is + /// guaranteed to repeatedly return a successful exit status so long as the + /// child has already exited. + /// + /// If the child has exited, then `Ok(status)` is returned. If the exit + /// status is not available at this time then an error is returned with the + /// error kind `WouldBlock`. If an error occurs, then that error is returned. + /// + /// Note that unlike `wait`, this function will not attempt to drop stdin. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```no_run + /// #![feature(process_try_wait)] + /// + /// use std::io; + /// use std::process::Command; + /// + /// let mut child = Command::new("ls").spawn().unwrap(); + /// + /// match child.try_wait() { + /// Ok(status) => println!("exited with: {}", status), + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// println!("status not ready yet, let's really wait"); + /// let res = child.wait(); + /// println!("result: {:?}", res); + /// } + /// Err(e) => println!("error attempting to wait: {}", e), + /// } + /// ``` + #[unstable(feature = "process_try_wait", issue = "38903")] + pub fn try_wait(&mut self) -> io::Result { + self.handle.try_wait().map(ExitStatus) + } + /// Simultaneously waits for the child to exit and collect all remaining /// output on the stdout/stderr handles, returning an `Output` /// instance. @@ -925,7 +974,11 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn smoke() { - let p = Command::new("true").spawn(); + let p = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 0"]).spawn() + } else { + Command::new("true").spawn() + }; assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().unwrap().success()); @@ -943,7 +996,11 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn exit_reported_right() { - let p = Command::new("false").spawn(); + let p = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 1"]).spawn() + } else { + Command::new("false").spawn() + }; assert!(p.is_ok()); let mut p = p.unwrap(); assert!(p.wait().unwrap().code() == Some(1)); @@ -982,9 +1039,15 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn stdout_works() { - let mut cmd = Command::new("echo"); - cmd.arg("foobar").stdout(Stdio::piped()); - assert_eq!(run_output(cmd), "foobar\n"); + if cfg!(target_os = "windows") { + let mut cmd = Command::new("cmd"); + cmd.args(&["/C", "echo foobar"]).stdout(Stdio::piped()); + assert_eq!(run_output(cmd), "foobar\r\n"); + } else { + let mut cmd = Command::new("echo"); + cmd.arg("foobar").stdout(Stdio::piped()); + assert_eq!(run_output(cmd), "foobar\n"); + } } #[test] @@ -1044,10 +1107,18 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_process_status() { - let mut status = Command::new("false").status().unwrap(); + let mut status = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap() + } else { + Command::new("false").status().unwrap() + }; assert!(status.code() == Some(1)); - status = Command::new("true").status().unwrap(); + status = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap() + } else { + Command::new("true").status().unwrap() + }; assert!(status.success()); } @@ -1063,7 +1134,11 @@ mod tests { #[cfg_attr(target_os = "android", ignore)] fn test_process_output_output() { let Output {status, stdout, stderr} - = Command::new("echo").arg("hello").output().unwrap(); + = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap() + } else { + Command::new("echo").arg("hello").output().unwrap() + }; let output_str = str::from_utf8(&stdout).unwrap(); assert!(status.success()); @@ -1075,7 +1150,11 @@ mod tests { #[cfg_attr(target_os = "android", ignore)] fn test_process_output_error() { let Output {status, stdout, stderr} - = Command::new("mkdir").arg(".").output().unwrap(); + = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap() + } else { + Command::new("mkdir").arg(".").output().unwrap() + }; assert!(status.code() == Some(1)); assert_eq!(stdout, Vec::new()); @@ -1085,14 +1164,22 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_finish_once() { - let mut prog = Command::new("false").spawn().unwrap(); + let mut prog = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() + } else { + Command::new("false").spawn().unwrap() + }; assert!(prog.wait().unwrap().code() == Some(1)); } #[test] #[cfg_attr(target_os = "android", ignore)] fn test_finish_twice() { - let mut prog = Command::new("false").spawn().unwrap(); + let mut prog = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() + } else { + Command::new("false").spawn().unwrap() + }; assert!(prog.wait().unwrap().code() == Some(1)); assert!(prog.wait().unwrap().code() == Some(1)); } @@ -1100,8 +1187,12 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_wait_with_output_once() { - let prog = Command::new("echo").arg("hello").stdout(Stdio::piped()) - .spawn().unwrap(); + let prog = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap() + } else { + Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap() + }; + let Output {status, stdout, stderr} = prog.wait_with_output().unwrap(); let output_str = str::from_utf8(&stdout).unwrap(); diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index f6dbe01d7bdbf..f8426e3b5782f 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -280,8 +280,7 @@ impl Mutex { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for Mutex { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex { fn drop(&mut self) { // This is actually safe b/c we know that there is no further usage of // this mutex (it's up to the user to arrange for a mutex to get diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 0a11c71706b7e..adbb98e4b1f4f 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -310,8 +310,7 @@ impl RwLock { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for RwLock { - #[unsafe_destructor_blind_to_params] +unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock { fn drop(&mut self) { // IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`. unsafe { self.inner.destroy() } diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index aa42672202559..0dc1739c1a15a 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -237,6 +237,7 @@ impl Process { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(|_| ()) } } + pub fn wait(&mut self) -> io::Result { use sys::cvt_r; if let Some(status) = self.status { @@ -247,4 +248,20 @@ impl Process { self.status = Some(ExitStatus::new(status)); Ok(ExitStatus::new(status)) } + + pub fn try_wait(&mut self) -> io::Result { + if let Some(status) = self.status { + return Ok(status) + } + let mut status = 0 as c_int; + let pid = cvt(unsafe { + libc::waitpid(self.pid, &mut status, libc::WNOHANG) + })?; + if pid == 0 { + Err(io::Error::from_raw_os_error(libc::EWOULDBLOCK)) + } else { + self.status = Some(ExitStatus::new(status)); + Ok(ExitStatus::new(status)) + } + } } diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 910d802f05902..dc7b2fc9a6bab 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -265,6 +265,7 @@ pub const FILE_CURRENT: DWORD = 1; pub const FILE_END: DWORD = 2; pub const WAIT_OBJECT_0: DWORD = 0x00000000; +pub const WAIT_TIMEOUT: DWORD = 258; #[cfg(target_env = "msvc")] pub const MAX_SYM_NAME: usize = 2000; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 7dc8959e1b683..d2ad81023e7fe 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -340,6 +340,21 @@ impl Process { } } + pub fn try_wait(&mut self) -> io::Result { + unsafe { + match c::WaitForSingleObject(self.handle.raw(), 0) { + c::WAIT_OBJECT_0 => {} + c::WAIT_TIMEOUT => { + return Err(io::Error::from_raw_os_error(c::WSAEWOULDBLOCK)) + } + _ => return Err(io::Error::last_os_error()), + } + let mut status = 0; + cvt(c::GetExitCodeProcess(self.handle.raw(), &mut status))?; + Ok(ExitStatus(status)) + } + } + pub fn handle(&self) -> &Handle { &self.handle } pub fn into_handle(self) -> Handle { self.handle } diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index 6854f1e14fa13..e4b8d457e2d29 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -34,7 +34,7 @@ pub use self::duration::Duration; mod duration; /// A measurement of a monotonically increasing clock. -/// Opaque and useful only with `Duration`. +/// Opaque and useful only with `Duration`. /// /// Instants are always guaranteed to be greater than any previously measured /// instant when created, and are often useful for tasks such as measuring @@ -73,7 +73,7 @@ pub struct Instant(time::Instant); /// A measurement of the system clock, useful for talking to /// external entities like the file system or other processes. /// -/// Distinct from the `Instant` type, this time measurement **is not +/// Distinct from the [`Instant`] type, this time measurement **is not /// monotonic**. This means that you can save a file to the file system, then /// save another file to the file system, **and the second file has a /// `SystemTime` measurement earlier than the first**. In other words, an @@ -81,15 +81,20 @@ pub struct Instant(time::Instant); /// earlier `SystemTime`! /// /// Consequently, comparing two `SystemTime` instances to learn about the -/// duration between them returns a `Result` instead of an infallible `Duration` +/// duration between them returns a [`Result`] instead of an infallible [`Duration`] /// to indicate that this sort of time drift may happen and needs to be handled. /// -/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH` +/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`] /// constant is provided in this module as an anchor in time to learn /// information about a `SystemTime`. By calculating the duration from this /// fixed point in time, a `SystemTime` can be converted to a human-readable time, /// or perhaps some other string representation. /// +/// [`Instant`]: ../../std/time/struct.Instant.html +/// [`Result`]: ../../std/result/enum.Result.html +/// [`Duration`]: ../../std/time/struct.Duration.html +/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html +/// /// Example: /// /// ```no_run @@ -117,14 +122,38 @@ pub struct Instant(time::Instant); #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTime(time::SystemTime); -/// An error returned from the `duration_since` method on `SystemTime`, -/// used to learn how far in the opposite direction a system time lies. +/// An error returned from the `duration_since` and `elapsed` methods on +/// `SystemTime`, used to learn how far in the opposite direction a system time +/// lies. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread::sleep; +/// use std::time::{Duration, SystemTime}; +/// +/// let sys_time = SystemTime::now(); +/// sleep(Duration::from_secs(1)); +/// let new_sys_time = SystemTime::now(); +/// match sys_time.duration_since(new_sys_time) { +/// Ok(_) => {} +/// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), +/// } +/// ``` #[derive(Clone, Debug)] #[stable(feature = "time2", since = "1.8.0")] pub struct SystemTimeError(Duration); impl Instant { /// Returns an instant corresponding to "now". + /// + /// # Examples + /// + /// ``` + /// use std::time::Instant; + /// + /// let now = Instant::now(); + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn now() -> Instant { Instant(time::Instant::now()) @@ -138,6 +167,18 @@ impl Instant { /// only be possible if `earlier` was created after `self`. Because /// `Instant` is monotonic, the only time that this should happen should be /// a bug. + /// + /// # Examples + /// + /// ```no_run + /// use std::time::{Duration, Instant}; + /// use std::thread::sleep; + /// + /// let now = Instant::now(); + /// sleep(Duration::new(1, 0)); + /// let new_now = Instant::now(); + /// println!("{:?}", new_now.duration_since(now)); + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn duration_since(&self, earlier: Instant) -> Duration { self.0.sub_instant(&earlier.0) @@ -218,6 +259,14 @@ impl fmt::Debug for Instant { impl SystemTime { /// Returns the system time corresponding to "now". + /// + /// # Examples + /// + /// ``` + /// use std::time::SystemTime; + /// + /// let sys_time = SystemTime::now(); + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn now() -> SystemTime { SystemTime(time::SystemTime::now()) @@ -229,11 +278,26 @@ impl SystemTime { /// guaranteed to always be before later measurements (due to anomalies such /// as the system clock being adjusted either forwards or backwards). /// - /// If successful, `Ok(Duration)` is returned where the duration represents + /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents /// the amount of time elapsed from the specified measurement to this one. /// - /// Returns an `Err` if `earlier` is later than `self`, and the error + /// Returns an [`Err`] if `earlier` is later than `self`, and the error /// contains how far from `self` the time is. + /// + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// ``` + /// use std::time::SystemTime; + /// + /// let sys_time = SystemTime::now(); + /// let difference = sys_time.duration_since(sys_time) + /// .expect("SystemTime::duration_since failed"); + /// println!("{:?}", difference); + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn duration_since(&self, earlier: SystemTime) -> Result { @@ -244,12 +308,28 @@ impl SystemTime { /// /// This function may fail as the underlying system clock is susceptible to /// drift and updates (e.g. the system clock could go backwards), so this - /// function may not always succeed. If successful, `Ok(duration)` is + /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is /// returned where the duration represents the amount of time elapsed from /// this time measurement to the current time. /// - /// Returns an `Err` if `self` is later than the current system time, and + /// Returns an [`Err`] if `self` is later than the current system time, and /// the error contains how far from the current system time `self` is. + /// + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Duration`]: ../../std/time/struct.Duration.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// + /// # Examples + /// + /// ```no_run + /// use std::thread::sleep; + /// use std::time::{Duration, SystemTime}; + /// + /// let sys_time = SystemTime::now(); + /// let one_sec = Duration::from_secs(1); + /// sleep(one_sec); + /// assert!(sys_time.elapsed().unwrap() >= one_sec); + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn elapsed(&self) -> Result { SystemTime::now().duration_since(*self) @@ -300,9 +380,11 @@ impl fmt::Debug for SystemTime { /// /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with /// respect to the system clock. Using `duration_since` on an existing -/// `SystemTime` instance can tell how far away from this point in time a +/// [`SystemTime`] instance can tell how far away from this point in time a /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a -/// `SystemTime` instance to represent another fixed point in time. +/// [`SystemTime`] instance to represent another fixed point in time. +/// +/// [`SystemTime`]: ../../std/time/struct.SystemTime.html #[stable(feature = "time2", since = "1.8.0")] pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH); @@ -310,9 +392,28 @@ impl SystemTimeError { /// Returns the positive duration which represents how far forward the /// second system time was from the first. /// - /// A `SystemTimeError` is returned from the `duration_since` - /// operation whenever the second system time represents a point later + /// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`] + /// methods of [`SystemTime`] whenever the second system time represents a point later /// in time than the `self` of the method call. + /// + /// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since + /// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed + /// [`SystemTime`]: ../../std/time/struct.SystemTime.html + /// + /// # Examples + /// + /// ```no_run + /// use std::thread::sleep; + /// use std::time::{Duration, SystemTime}; + /// + /// let sys_time = SystemTime::now(); + /// sleep(Duration::from_secs(1)); + /// let new_sys_time = SystemTime::now(); + /// match sys_time.duration_since(new_sys_time) { + /// Ok(_) => {} + /// Err(e) => println!("SystemTimeError difference: {:?}", e.duration()), + /// } + /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn duration(&self) -> Duration { self.0 diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 53dafadb5d568..89f4a97a25442 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -285,7 +285,7 @@ impl char { /// Basic usage: /// /// ``` - /// for i in '\n'.escape_default() { + /// for i in '\n'.escape_debug() { /// println!("{}", i); /// } /// ``` @@ -300,7 +300,7 @@ impl char { /// Collecting into a `String`: /// /// ``` - /// let quote: String = '\n'.escape_default().collect(); + /// let quote: String = '\n'.escape_debug().collect(); /// /// assert_eq!(quote, "\\n"); /// ``` diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index 11724e74cdaec..d52d1549b5173 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -29,7 +29,7 @@ html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![no_std] #![feature(char_escape_debug)] diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs index 21543e2ad073e..7a5667b96a50c 100644 --- a/src/libstd_unicode/tables.rs +++ b/src/libstd_unicode/tables.rs @@ -68,81 +68,33 @@ fn trie_lookup_range_table(c: char, r: &'static BoolTrie) -> bool { } } +pub struct SmallBoolTrie { + r1: &'static [u8], // first level + r2: &'static [u64], // leaves +} + +impl SmallBoolTrie { + fn lookup(&self, c: char) -> bool { + let c = c as usize; + match self.r1.get(c >> 6) { + Some(&child) => trie_range_leaf(c, self.r2[child as usize]), + None => false, + } + } +} + pub mod general_category { - pub const Cc_table: &'static super::BoolTrie = &super::BoolTrie { - r1: [ - 0x00000000ffffffff, 0x8000000000000000, 0x00000000ffffffff, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 + pub const Cc_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie { + r1: &[ + 0, 1, 0 ], - r2: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ], - r3: &[ - 0x0000000000000000 - ], - r4: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ], - r5: &[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ], - r6: &[ - 0x0000000000000000 + r2: &[ + 0x00000000ffffffff, 0x8000000000000000 ], }; pub fn Cc(c: char) -> bool { - super::trie_lookup_range_table(c, Cc_table) + Cc_table.lookup(c) } pub const N_table: &'static super::BoolTrie = &super::BoolTrie { @@ -1193,156 +1145,41 @@ pub mod derived_property { } pub mod property { - pub const Pattern_White_Space_table: &'static super::BoolTrie = &super::BoolTrie { - r1: [ - 0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 - ], - r2: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + pub const Pattern_White_Space_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie { + r1: &[ + 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 ], - r3: &[ - 0x0000000000000000, 0x000003000000c000 - ], - r4: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ], - r5: &[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ], - r6: &[ - 0x0000000000000000 + r2: &[ + 0x0000000100003e00, 0x0000000000000000, 0x0000000000000020, 0x000003000000c000 ], }; pub fn Pattern_White_Space(c: char) -> bool { - super::trie_lookup_range_table(c, Pattern_White_Space_table) + Pattern_White_Space_table.lookup(c) } - pub const White_Space_table: &'static super::BoolTrie = &super::BoolTrie { - r1: [ - 0x0000000100003e00, 0x0000000000000000, 0x0000000100000020, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 - ], - r2: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ], - r3: &[ - 0x0000000000000000, 0x0000000000000001, 0x00008300000007ff, 0x0000000080000000 - ], - r4: [ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ], - r5: &[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ], - r6: &[ - 0x0000000000000000 + pub const White_Space_table: &'static super::SmallBoolTrie = &super::SmallBoolTrie { + r1: &[ + 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 + ], + r2: &[ + 0x0000000100003e00, 0x0000000000000000, 0x0000000100000020, 0x0000000000000001, + 0x00008300000007ff, 0x0000000080000000 ], }; pub fn White_Space(c: char) -> bool { - super::trie_lookup_range_table(c, White_Space_table) + White_Space_table.lookup(c) } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 5d6808284f67e..00bf744507713 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -22,7 +22,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(associated_consts)] #![feature(const_fn)] diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index cbc2b2263f20e..bdec86158a4ec 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -17,7 +17,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(proc_macro_internals)] #![feature(rustc_private)] diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 44067b3132c1d..92fdb45caaaef 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -21,7 +21,7 @@ #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(custom_attribute)] #![allow(unused_attributes)] diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 01daa938142b1..370757c060910 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -52,7 +52,7 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))] #![deny(missing_docs)] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(box_syntax)] #![feature(staged_api)] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 82acbf934881d..30c34746c34e4 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -31,7 +31,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(asm)] #![feature(libc)] diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index add45ccb362e9..7fa2ce650fd6c 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -12,7 +12,7 @@ #![crate_name = "unwind"] #![crate_type = "rlib"] #![unstable(feature = "panic_unwind", issue = "32837")] -#![cfg_attr(not(stage0), deny(warnings))] +#![deny(warnings)] #![feature(cfg_target_vendor)] #![feature(staged_api)] diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs index b8f3f714a84ec..3c688d58fd195 100644 --- a/src/test/compile-fail/const-eval-overflow.rs +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -15,6 +15,8 @@ // change this warn to a deny, then the compiler will exit before // those errors are detected. +#![warn(const_err)] + use std::fmt; use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; @@ -80,7 +82,8 @@ const VALS_I64: (i64, i64, i64, i64) = ); const VALS_U8: (u8, u8, u8, u8) = - (-(u8::MIN as i8) as u8, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u8::MIN as i8) as u8, u8::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -93,7 +96,8 @@ const VALS_U8: (u8, u8, u8, u8) = ); const VALS_U16: (u16, u16, u16, u16) = - (-(u16::MIN as i16) as u16, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u16::MIN as i16) as u16, u16::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -106,7 +110,8 @@ const VALS_U16: (u16, u16, u16, u16) = ); const VALS_U32: (u32, u32, u32, u32) = - (-(u32::MIN as i32) as u32, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u32::MIN as i32) as u32, u32::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -119,7 +124,8 @@ const VALS_U32: (u32, u32, u32, u32) = ); const VALS_U64: (u64, u64, u64, u64) = - (-(u64::MIN as i64) as u64, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u64::MIN as i64) as u64, u64::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow diff --git a/src/test/compile-fail/i128-feature-libs.rs b/src/test/compile-fail/i128-feature-libs.rs new file mode 100644 index 0000000000000..b29ac50fd377f --- /dev/null +++ b/src/test/compile-fail/i128-feature-libs.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn testl() { + ::std::u128::MAX; //~ ERROR use of unstable library feature 'i128' +} + +fn testl2() { + ::std::i128::MAX; //~ ERROR use of unstable library feature 'i128' +} diff --git a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs index bed10c87ae185..4c16f0397562b 100644 --- a/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs +++ b/src/test/compile-fail/imports/rfc-1560-warning-cycle.rs @@ -23,6 +23,7 @@ mod bar { //~^ WARN `Foo` is ambiguous //~| WARN hard error in a future release //~| NOTE see issue #38260 + //~| NOTE #[warn(legacy_imports)] on by default } } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 82804bb747406..086938334c78a 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -9,5 +9,7 @@ // except according to those terms. #![deny(warnings)] //~ NOTE: lint level defined here -use std::thread; //~ ERROR: unused import +use std::thread; +//~^ ERROR: unused import +//~| NOTE: #[deny(unused_imports)] implied by #[deny(warnings)] fn main() {} diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs deleted file mode 100644 index b2e6072c9855c..0000000000000 --- a/src/test/compile-fail/lint-group-style.rs +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#![deny(bad_style)] -//~^ NOTE lint level defined here -#![allow(dead_code)] - -fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name - -#[allow(bad_style)] -mod test { - fn CamelCase() {} - - #[forbid(bad_style)] - //~^ NOTE lint level defined here - //~^^ NOTE lint level defined here - mod bad { - fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name - - static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name - } - - mod warn { - #![warn(bad_style)] - //~^ NOTE lint level defined here - //~| NOTE lint level defined here - - fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name - - struct snake_case; //~ WARN type `snake_case` should have a camel case name - } -} - -fn main() {} diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 2f74325d19c7d..0e68ff752e5a9 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -11,15 +11,20 @@ // compile-flags: -F unused_features // aux-build:lint_output_format.rs -#![feature(foo)] //~ ERROR unused or unknown feature +#![feature(foo)] +//~^ ERROR unused or unknown feature +//~| NOTE requested on the command line with `-F unused-features` #![feature(test_feature)] extern crate lint_output_format; use lint_output_format::{foo, bar}; -//~^ WARNING use of deprecated item: text, +//~^ WARNING use of deprecated item: text +//~| NOTE #[warn(deprecated)] on by default fn main() { - let _x = foo(); //~ WARNING #[warn(deprecated)] on by default + let _x = foo(); + //~^ WARNING use of deprecated item: text + //~| NOTE #[warn(deprecated)] on by default let _y = bar(); } diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index 500aaf52324b0..15094492248e6 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -402,3 +402,155 @@ impl ChangeArgumentTypeTrait for Foo { fn method_name(&self, _x: char) { } } + + +struct Bar(T); + +// Add Type Parameter To Impl -------------------------------------------------- +trait AddTypeParameterToImpl { + fn id(t: T) -> T; +} + +#[cfg(cfail1)] +impl AddTypeParameterToImpl for Bar { + fn id(t: u32) -> u32 { t } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddTypeParameterToImpl for Bar { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn id(t: T) -> T { t } +} + + + +// Change Self Type of Impl ---------------------------------------------------- +trait ChangeSelfTypeOfImpl { + fn id(self) -> Self; +} + +#[cfg(cfail1)] +impl ChangeSelfTypeOfImpl for u32 { + fn id(self) -> Self { self } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeSelfTypeOfImpl for u64 { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn id(self) -> Self { self } +} + + + +// Add Lifetime Bound to Impl -------------------------------------------------- +trait AddLifetimeBoundToImplParameter { + fn id(self) -> Self; +} + +#[cfg(cfail1)] +impl AddLifetimeBoundToImplParameter for T { + fn id(self) -> Self { self } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddLifetimeBoundToImplParameter for T { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn id(self) -> Self { self } +} + + + +// Add Trait Bound to Impl Parameter ------------------------------------------- +trait AddTraitBoundToImplParameter { + fn id(self) -> Self; +} + +#[cfg(cfail1)] +impl AddTraitBoundToImplParameter for T { + fn id(self) -> Self { self } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddTraitBoundToImplParameter for T { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn id(self) -> Self { self } +} + + + +// Add #[no_mangle] to Method -------------------------------------------------- +trait AddNoMangleToMethod { + fn add_no_mangle_to_method(&self) { } +} + +#[cfg(cfail1)] +impl AddNoMangleToMethod for Foo { + fn add_no_mangle_to_method(&self) { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddNoMangleToMethod for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + #[no_mangle] + fn add_no_mangle_to_method(&self) { } +} + + +// Make Method #[inline] ------------------------------------------------------- +trait MakeMethodInline { + fn make_method_inline(&self) -> u8 { 0 } +} + +#[cfg(cfail1)] +impl MakeMethodInline for Foo { + fn make_method_inline(&self) -> u8 { 0 } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl MakeMethodInline for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + #[inline] + fn make_method_inline(&self) -> u8 { 0 } +} diff --git a/src/test/run-pass/issue-38074.rs b/src/test/run-pass/issue-38074.rs new file mode 100644 index 0000000000000..5c9a63b861663 --- /dev/null +++ b/src/test/run-pass/issue-38074.rs @@ -0,0 +1,27 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(platform_intrinsics, repr_simd)] + +extern "platform-intrinsic" { + fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; +} + +#[repr(simd)] +#[derive(Clone, Copy)] +#[allow(non_camel_case_types)] +struct u64x2(u64, u64); + +fn main() { + let a = u64x2(1, 2); + let r: u64x2 = unsafe { simd_shuffle2(a, a, [0-0, 0-0]) }; + assert_eq!(r.0, 1); + assert_eq!(r.1, 1); +} diff --git a/src/test/run-pass/path-lookahead.rs b/src/test/run-pass/path-lookahead.rs index 017259af190fc..5c195c8a4c63a 100644 --- a/src/test/run-pass/path-lookahead.rs +++ b/src/test/run-pass/path-lookahead.rs @@ -10,11 +10,11 @@ // Parser test for #37765 -fn with_parens(arg: T) -> String { //~WARN dead_code - return (::to_string(&arg)); //~WARN unused_parens +fn with_parens(arg: T) -> String { //~WARN function is never used: `with_parens` + return (::to_string(&arg)); //~WARN unnecessary parentheses around `return` value } -fn no_parens(arg: T) -> String { //~WARN dead_code +fn no_parens(arg: T) -> String { //~WARN function is never used: `no_parens` return ::to_string(&arg); } diff --git a/src/test/run-pass/try-wait.rs b/src/test/run-pass/try-wait.rs new file mode 100644 index 0000000000000..fdaf0cfd5b0c8 --- /dev/null +++ b/src/test/run-pass/try-wait.rs @@ -0,0 +1,65 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(process_try_wait)] + +use std::env; +use std::io; +use std::process::Command; +use std::thread; +use std::time::Duration; + +fn main() { + let args = env::args().collect::>(); + if args.len() != 1 { + match &args[1][..] { + "sleep" => thread::sleep(Duration::new(1_000, 0)), + _ => {} + } + return + } + + let mut me = Command::new(env::current_exe().unwrap()) + .arg("sleep") + .spawn() + .unwrap(); + let err = me.try_wait().unwrap_err(); + assert_eq!(err.kind(), io::ErrorKind::WouldBlock); + let err = me.try_wait().unwrap_err(); + assert_eq!(err.kind(), io::ErrorKind::WouldBlock); + + me.kill().unwrap(); + me.wait().unwrap(); + + let status = me.try_wait().unwrap(); + assert!(!status.success()); + let status = me.try_wait().unwrap(); + assert!(!status.success()); + + let mut me = Command::new(env::current_exe().unwrap()) + .arg("return-quickly") + .spawn() + .unwrap(); + loop { + match me.try_wait() { + Ok(res) => { + assert!(res.success()); + break + } + Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + thread::sleep(Duration::from_millis(1)); + } + Err(e) => panic!("error in try_wait: {}", e), + } + } + + let status = me.try_wait().unwrap(); + assert!(status.success()); +} diff --git a/src/test/ui/custom-derive/auxiliary/plugin.rs b/src/test/ui/custom-derive/auxiliary/plugin.rs new file mode 100644 index 0000000000000..c5ba2aa9413e7 --- /dev/null +++ b/src/test/ui/custom-derive/auxiliary/plugin.rs @@ -0,0 +1,28 @@ +// 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. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro, proc_macro_lib)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Bar)] +pub fn derive_bar(input: TokenStream) -> TokenStream { + panic!("lolnope"); +} diff --git a/src/test/ui/custom-derive/issue-36935.rs b/src/test/ui/custom-derive/issue-36935.rs new file mode 100644 index 0000000000000..22d603563de17 --- /dev/null +++ b/src/test/ui/custom-derive/issue-36935.rs @@ -0,0 +1,23 @@ +// 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. + +// aux-build:plugin.rs + +#![feature(proc_macro)] + +#[macro_use] extern crate plugin; + +#[derive(Foo, Bar)] +struct Baz { + a: i32, + b: i32, +} + +fn main() {} diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr new file mode 100644 index 0000000000000..213366a307d40 --- /dev/null +++ b/src/test/ui/custom-derive/issue-36935.stderr @@ -0,0 +1,8 @@ +error: custom derive attribute panicked + --> $DIR/issue-36935.rs:17:15 + | +17 | #[derive(Foo, Bar)] + | ^^^ + | + = help: message: lolnope + diff --git a/src/test/run-pass/issue-28189.rs b/src/test/ui/lint/command-line-lint-group-allow.rs similarity index 75% rename from src/test/run-pass/issue-28189.rs rename to src/test/ui/lint/command-line-lint-group-allow.rs index 0e624a778583d..cdb9684933d9b 100644 --- a/src/test/run-pass/issue-28189.rs +++ b/src/test/ui/lint/command-line-lint-group-allow.rs @@ -1,4 +1,4 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct S(T) where [T; (||{}, 1).1]: Copy; +// compile-flags: -A bad-style fn main() { - + let _InappropriateCamelCasing = true; } diff --git a/src/test/ui/lint/command-line-lint-group-deny.rs b/src/test/ui/lint/command-line-lint-group-deny.rs new file mode 100644 index 0000000000000..1248601c1e44a --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -D bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr new file mode 100644 index 0000000000000..23fac66cc6c98 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-deny.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D non-snake-case` implied by `-D bad-style` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/command-line-lint-group-forbid.rs b/src/test/ui/lint/command-line-lint-group-forbid.rs new file mode 100644 index 0000000000000..ae16db44864c9 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -F bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr new file mode 100644 index 0000000000000..0babd7f6fe47a --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -0,0 +1,10 @@ +error: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-forbid.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-F non-snake-case` implied by `-F bad-style` + +error: aborting due to previous error + diff --git a/src/test/ui/lint/command-line-lint-group-warn.rs b/src/test/ui/lint/command-line-lint-group-warn.rs new file mode 100644 index 0000000000000..7d65c802788bf --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -W bad-style + +fn main() { + let _InappropriateCamelCasing = true; +} diff --git a/src/test/ui/lint/command-line-lint-group-warn.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr new file mode 100644 index 0000000000000..998c892c7e349 --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-warn.stderr @@ -0,0 +1,8 @@ +warning: variable `_InappropriateCamelCasing` should have a snake case name such as `_inappropriate_camel_casing` + --> $DIR/command-line-lint-group-warn.rs:14:9 + | +14 | let _InappropriateCamelCasing = true; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-W non-snake-case` implied by `-W bad-style` + diff --git a/src/test/ui/lint/lint-group-style.rs b/src/test/ui/lint/lint-group-style.rs new file mode 100644 index 0000000000000..2bd760e417a89 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.rs @@ -0,0 +1,36 @@ +// Copyright 2014–2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![deny(bad_style)] +#![allow(dead_code)] + +fn CamelCase() {} + +#[allow(bad_style)] +mod test { + fn CamelCase() {} + + #[forbid(bad_style)] + mod bad { + fn CamelCase() {} + + static bad: isize = 1; + } + + mod warn { + #![warn(bad_style)] + + fn CamelCase() {} + + struct snake_case; + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr new file mode 100644 index 0000000000000..9c0f4866af690 --- /dev/null +++ b/src/test/ui/lint/lint-group-style.stderr @@ -0,0 +1,67 @@ +error: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:14:1 + | +14 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] +note: lint level defined here + --> $DIR/lint-group-style.rs:11:9 + | +11 | #![deny(bad_style)] + | ^^^^^^^^^ + +error: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:22:9 + | +22 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] +note: lint level defined here + --> $DIR/lint-group-style.rs:20:14 + | +20 | #[forbid(bad_style)] + | ^^^^^^^^^ + +error: static variable `bad` should have an upper case name such as `BAD` + --> $DIR/lint-group-style.rs:24:9 + | +24 | static bad: isize = 1; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] +note: lint level defined here + --> $DIR/lint-group-style.rs:20:14 + | +20 | #[forbid(bad_style)] + | ^^^^^^^^^ + +warning: function `CamelCase` should have a snake case name such as `camel_case` + --> $DIR/lint-group-style.rs:30:9 + | +30 | fn CamelCase() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] +note: lint level defined here + --> $DIR/lint-group-style.rs:28:17 + | +28 | #![warn(bad_style)] + | ^^^^^^^^^ + +warning: type `snake_case` should have a camel case name such as `SnakeCase` + --> $DIR/lint-group-style.rs:32:9 + | +32 | struct snake_case; + | ^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] +note: lint level defined here + --> $DIR/lint-group-style.rs:28:17 + | +28 | #![warn(bad_style)] + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 0d2a2ef751666..881b6321d25d6 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,6 +4,7 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | + = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -16,6 +17,7 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -27,6 +29,8 @@ error: variable `theOtherTwo` should have a snake case name such as `the_other_t | 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ + | + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: aborting due to 3 previous errors diff --git a/src/test/ui/span/issue-27522.rs b/src/test/ui/span/issue-27522.rs new file mode 100644 index 0000000000000..81fcb007eb491 --- /dev/null +++ b/src/test/ui/span/issue-27522.rs @@ -0,0 +1,19 @@ +// 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. + +// Point at correct span for self type + +struct SomeType {} + +trait Foo { + fn handler(self: &SomeType); +} + +fn main() {} diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr new file mode 100644 index 0000000000000..71130f4947a68 --- /dev/null +++ b/src/test/ui/span/issue-27522.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched method receiver + --> $DIR/issue-27522.rs:16:22 + | +16 | fn handler(self: &SomeType); + | ^^^^^^^^^ expected Self, found struct `SomeType` + | + = note: expected type `&Self` + = note: found type `&SomeType` + +error: aborting due to previous error + diff --git a/src/test/ui/span/multispan-import-lint.stderr b/src/test/ui/span/multispan-import-lint.stderr index b581584eee7e2..4b1ca7f98bbf6 100644 --- a/src/test/ui/span/multispan-import-lint.stderr +++ b/src/test/ui/span/multispan-import-lint.stderr @@ -1,6 +1,8 @@ -warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd`, #[warn(unused_imports)] on by default +warning: unused imports: `Eq`, `Ord`, `PartialEq`, `PartialOrd` --> $DIR/multispan-import-lint.rs:11:16 | 11 | use std::cmp::{Eq, Ord, min, PartialEq, PartialOrd}; | ^^ ^^^ ^^^^^^^^^ ^^^^^^^^^^ + | + = note: #[warn(unused_imports)] on by default diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs index ed690c08a1ed2..7e4f40af9cea6 100644 --- a/src/tools/compiletest/src/procsrv.rs +++ b/src/tools/compiletest/src/procsrv.rs @@ -11,6 +11,7 @@ use std::env; use std::ffi::OsString; use std::io::prelude::*; +use std::io; use std::path::PathBuf; use std::process::{Child, Command, ExitStatus, Output, Stdio}; @@ -52,7 +53,7 @@ pub fn run(lib_path: &str, args: &[String], env: Vec<(String, String)>, input: Option) - -> Option { + -> io::Result { let mut cmd = Command::new(prog); cmd.args(args) @@ -64,21 +65,17 @@ pub fn run(lib_path: &str, cmd.env(&key, &val); } - match cmd.spawn() { - Ok(mut process) => { - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - let Output { status, stdout, stderr } = process.wait_with_output().unwrap(); - - Some(Result { - status: status, - out: String::from_utf8(stdout).unwrap(), - err: String::from_utf8(stderr).unwrap(), - }) - } - Err(..) => None, + let mut process = cmd.spawn()?; + if let Some(input) = input { + process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); } + let Output { status, stdout, stderr } = process.wait_with_output().unwrap(); + + Ok(Result { + status: status, + out: String::from_utf8(stdout).unwrap(), + err: String::from_utf8(stderr).unwrap(), + }) } pub fn run_background(lib_path: &str, @@ -87,26 +84,21 @@ pub fn run_background(lib_path: &str, args: &[String], env: Vec<(String, String)>, input: Option) - -> Option { + -> io::Result { let mut cmd = Command::new(prog); cmd.args(args) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()); + .stdin(Stdio::piped()) + .stdout(Stdio::piped()); add_target_env(&mut cmd, lib_path, aux_path); for (key, val) in env { cmd.env(&key, &val); } - match cmd.spawn() { - Ok(mut process) => { - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - - Some(process) - } - Err(..) => None, + let mut process = cmd.spawn()?; + if let Some(input) = input { + process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); } + + Ok(process) } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 05f9beca3d11a..05d6e21e9aaea 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -21,13 +21,12 @@ use test::TestPaths; use uidiff; use util::logv; -use std::env; use std::collections::HashSet; +use std::env; use std::fmt; use std::fs::{self, File}; -use std::io::{self, BufReader}; use std::io::prelude::*; -use std::net::TcpStream; +use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; use std::process::{Command, Output, ExitStatus}; use std::str; @@ -506,8 +505,8 @@ actual:\n\ exe_file.to_str().unwrap().to_owned(), self.config.adb_test_dir.clone() ], - vec![("".to_owned(), "".to_owned())], - Some("".to_owned())) + Vec::new(), + None) .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); procsrv::run("", @@ -518,8 +517,8 @@ actual:\n\ "tcp:5039".to_owned(), "tcp:5039".to_owned() ], - vec![("".to_owned(), "".to_owned())], - Some("".to_owned())) + Vec::new(), + None) .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); let adb_arg = format!("export LD_LIBRARY_PATH={}; \ @@ -539,17 +538,23 @@ actual:\n\ "shell".to_owned(), adb_arg.clone() ], - vec![("".to_owned(), - "".to_owned())], - Some("".to_owned())) + Vec::new(), + None) .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); + + // Wait for the gdbserver to print out "Listening on port ..." + // at which point we know that it's started and then we can + // execute the debugger below. + let mut stdout = BufReader::new(process.stdout.take().unwrap()); + let mut line = String::new(); loop { - //waiting 1 second for gdbserver start - ::std::thread::sleep(::std::time::Duration::new(1,0)); - if TcpStream::connect("127.0.0.1:5039").is_ok() { + line.truncate(0); + stdout.read_line(&mut line).unwrap(); + if line.starts_with("Listening on port 5039") { break } } + drop(stdout); let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths @@ -569,7 +574,7 @@ actual:\n\ &gdb_path, None, &debugger_opts, - vec![("".to_owned(), "".to_owned())], + Vec::new(), None) .expect(&format!("failed to exec `{:?}`", gdb_path)); let cmdline = {