From ec9a9603cfab3ab4154800e66599d32e3cdd50c8 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 30 Dec 2016 21:18:17 -0800 Subject: [PATCH 01/53] Add PeekMut::pop A fairly common workflow is to put a bunch of stuff into a binary heap and then mutate the top value until its empty. This both makes that a bit more convenient (no need to save a boolean off and pop after to avoid borrowck issues), and a bit more efficient since you only shift once. --- src/libcollections/binary_heap.rs | 23 +++++++++++++++++++---- src/libcollectionstest/binary_heap.rs | 15 ++++++++++++++- src/libcollectionstest/lib.rs | 1 + 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index c5d5ad27d2304..c53b34d589bd0 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 = "0")] + 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/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)] From 5e42fa7e43075e73807c2f4ab25fa22f36fc0275 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 5 Jan 2017 19:36:35 -0800 Subject: [PATCH 02/53] Add a tracking issue --- src/libcollections/binary_heap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index c53b34d589bd0..7d245f79f6998 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -254,7 +254,7 @@ 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 = "0")] + #[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; From b6dc3a749c5e9cba5b513f72f61004253f62c801 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 2 Jan 2017 12:54:54 +0100 Subject: [PATCH 03/53] Remove some dead Python code. It was used to measure before/after size in cfaf66c94e29a38cd3264b4a55c85b90213543d9. --- src/etc/unicode.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/etc/unicode.py b/src/etc/unicode.py index bddc83f63d25d..c987cfc1bdecd 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -25,9 +25,6 @@ import fileinput, re, os, sys, operator -bytes_old = 0 -bytes_new = 0 - preamble = '''// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -379,8 +376,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,7 +428,6 @@ 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_property_module(f, mod, tbl, emit): f.write("pub mod %s {\n" % mod) @@ -543,4 +537,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) From 6dcc43c8a238736bd54ea21ff278f8b1e179d438 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 2 Jan 2017 13:52:20 +0100 Subject: [PATCH 04/53] Reduce the size of static data in std_unicode::tables. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `BoolTrie` works well for sets of code points spread out through most of Unicode’s range, but is uses a lot of space for sets with few, mostly low, code points. This switches a few of its instances to a similar but simpler trie data structure. ## Before `size_of::()` is 1552, which is added to `table.r3.len() * 8 + t.r5.len() + t.r6.len() * 8`: * `Cc_table`: 1632 * `White_Space_table`: 1656 * `Pattern_White_Space_table`: 1640 * Total: 4928 bytes ## After `size_of::()` is 32, which is added to `t.r1.len() + t.r2.len() * 8`: * `Cc_table`: 51 * `White_Space_table`: 273 * `Pattern_White_Space_table`: 193 * Total: 517 bytes ## Difference Every Rust program with `std` statically linked should be about 4 KB smaller. --- .gitignore | 13 +- src/etc/unicode.py | 64 ++++++++- src/libstd_unicode/tables.rs | 253 +++++++---------------------------- 3 files changed, 110 insertions(+), 220 deletions(-) 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/src/etc/unicode.py b/src/etc/unicode.py index c987cfc1bdecd..e5389c112e811 100755 --- a/src/etc/unicode.py +++ b/src/etc/unicode.py @@ -23,7 +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 +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 @@ -359,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): @@ -429,13 +445,49 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write(" };\n\n") +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): 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) } } From 2d17d8b2912a5397f910f9f637e92ed3c1ca9cbe Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 3 Jan 2017 09:45:02 -0800 Subject: [PATCH 05/53] rustc: use -Xlinker when specifying an rpath with ',' in it The `-Wl` option splits its parameters on commas, so if rustc specifies `-Wl,-rpath,` when `` contains commas, the path gets split up and the linker gets a partial path and spurious extra parameters. Gcc/clang support the more verbose `-Xlinker` option to pass options to the linker directly, so use it for comma-containing paths. Fixes rust issue #38795. --- src/librustc_trans/back/rpath.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) 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() + ]); + } } From f475739be78c7cd8052f9e49a9ba970a71990503 Mon Sep 17 00:00:00 2001 From: comex Date: Tue, 3 Jan 2017 20:24:53 +0100 Subject: [PATCH 06/53] Print attributes on expressions when pretty printing. --- src/librustc/hir/print.rs | 1 + 1 file changed, 1 insertion(+) 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 { From e987662d49ffbef7ffb93a98e9fc6df0a6d81ff2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 4 Jan 2017 10:01:27 -0500 Subject: [PATCH 07/53] trans: Collect drop-glue translation item for closure env in fn-once-adapters. --- src/librustc_trans/callee.rs | 33 ++++++++--- src/librustc_trans/collector.rs | 97 +++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 20 deletions(-) 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..1abc62c932682 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,47 @@ 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::VtableObject(..) => { - None + StaticDispatchResult::Unknown } _ => { bug!("static call to invalid vtable: {:?}", vtbl) @@ -994,8 +1058,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); From dcae65f2c38037f91ee09e9b6de7b837941914cf Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 4 Jan 2017 16:54:37 -0500 Subject: [PATCH 08/53] trans: Make the trans-item collector see through VTableFnPointer. --- src/librustc_trans/collector.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 1abc62c932682..094f293e5eba2 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -919,10 +919,19 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, 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(..) => { StaticDispatchResult::Unknown } From df5d12ed31df4357c19a3c0b80ddf0df9ac08006 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Jan 2017 10:26:40 -0800 Subject: [PATCH 09/53] compiletest: Fix flaky Android gdb test runs Local testing showed that I was able to reproduce an error where debuginfo tests on Android would fail with "connection reset by peer". Further investigation turned out that the gdb tests are android with bit of process management: * First an `adb forward` command is run to ensure that the host's port 5039 is the same as the emulator's. * Next an `adb shell` command is run to execute the `gdbserver` executable inside the emulator. This gdb server will attach to port 5039 and listen for remote gdb debugging sessions. * Finally, we run `gdb` on the host (not in the emulator) and then connect to this gdb server to send it commands. The problem was happening when the host's gdb was failing to connect to the remote gdbserver running inside the emulator. The previous test for this was that after `adb shell` executed we'd sleep for a second and then attempt to make a TCP connection to port 5039. If successful we'd run gdb and on failure we'd sleep again. It turns out, however, that as soon as we've executed `adb forward` all TCP connections to 5039 will succeed. This means that we would only ever sleep for at most one second, and if this wasn't enough time we'd just fail later because we would assume that gdbserver had started but it may not have done so yet. This commit fixes these issues by removing the TCP connection to test if gdbserver is ready to go. Instead we read the stdout of the process and wait for it to print that it's listening at which point we start running gdb. I've found that locally at least I was unable to reproduce the failure after these changes. Closes #38710 --- src/tools/compiletest/src/procsrv.rs | 48 ++++++++++++---------------- src/tools/compiletest/src/runtest.rs | 33 +++++++++++-------- 2 files changed, 39 insertions(+), 42 deletions(-) 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 = { From 4e078b74c0ba22a6280829f40db42432badde463 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 29 Dec 2016 09:47:34 -0800 Subject: [PATCH 10/53] Remove not(stage0) from deny(warnings) Historically this was done to accommodate bugs in lints, but there hasn't been a bug in a lint since this feature was added which the warnings affected. Let's completely purge warnings from all our stages by denying warnings in all stages. This will also assist in tracking down `stage0` code to be removed whenever we're updating the bootstrap compiler. --- src/liballoc/lib.rs | 2 +- src/liballoc_jemalloc/lib.rs | 2 +- src/liballoc_system/lib.rs | 2 +- src/libarena/lib.rs | 2 +- src/libcollections/lib.rs | 2 +- src/libcore/lib.rs | 2 +- src/libflate/lib.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/libgetopts/lib.rs | 2 +- src/libgraphviz/lib.rs | 2 +- src/liblog/lib.rs | 2 +- src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/lib.rs | 2 +- src/libproc_macro/lib.rs | 2 +- src/libproc_macro_plugin/lib.rs | 2 +- src/libproc_macro_tokens/lib.rs | 2 +- src/librand/lib.rs | 2 +- src/librustc/lib.rs | 2 +- src/librustc_back/lib.rs | 2 +- src/librustc_bitflags/lib.rs | 2 +- src/librustc_borrowck/lib.rs | 2 +- src/librustc_data_structures/lib.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_errors/lib.rs | 2 +- src/librustc_incremental/lib.rs | 2 +- src/librustc_lint/lib.rs | 2 +- src/librustc_llvm/lib.rs | 2 +- src/librustc_metadata/lib.rs | 2 +- src/librustc_mir/lib.rs | 2 +- src/librustc_passes/lib.rs | 2 +- src/librustc_platform_intrinsics/lib.rs | 2 +- src/librustc_plugin/lib.rs | 2 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_trans/lib.rs | 2 +- src/librustc_typeck/lib.rs | 2 +- src/librustdoc/lib.rs | 2 +- src/libserialize/lib.rs | 2 +- src/libstd/lib.rs | 2 +- src/libstd_unicode/lib.rs | 2 +- src/libsyntax/lib.rs | 2 +- src/libsyntax_ext/lib.rs | 2 +- src/libsyntax_pos/lib.rs | 2 +- src/libterm/lib.rs | 2 +- src/libtest/lib.rs | 2 +- src/libunwind/lib.rs | 2 +- 47 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index f9dfdc0e07536..9ca9f93f3d33a 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)] 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..82ca989c9efb0 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -26,7 +26,7 @@ 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)] diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index f9746f5694a49..ea2feac49f6ed 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)] 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/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/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_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/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_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/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_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/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_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/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/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_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_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..84fa2e9d6bbaa 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)] 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/lib.rs b/src/librustc_save_analysis/lib.rs index 43e3b1dd2b50a..3f7f3bdba017f 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)] 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_typeck/lib.rs b/src/librustc_typeck/lib.rs index ec17813ed2a52..75cd9e2f96772 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)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 47616044879cd..c6951d4edd678 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)] 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/lib.rs b/src/libstd/lib.rs index f1e3996e825bf..9557c520c5071 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -225,7 +225,7 @@ // 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)] 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/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)] From da908fcbed11465f82b1cf0e473efb23c01b3584 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 6 Jan 2017 21:54:24 +0200 Subject: [PATCH 11/53] rustc: keep track of tables everywhere as if they were per-body. --- src/Cargo.lock | 1 - src/librustc/cfg/construct.rs | 24 +- src/librustc/hir/map/blocks.rs | 19 - src/librustc/infer/mod.rs | 192 +++++++--- src/librustc/lint/context.rs | 46 ++- src/librustc/middle/const_val.rs | 15 +- src/librustc/middle/dead.rs | 47 ++- src/librustc/middle/effect.rs | 22 +- src/librustc/middle/expr_use_visitor.rs | 4 +- src/librustc/middle/intrinsicck.rs | 60 +-- src/librustc/middle/liveness.rs | 85 ++--- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 41 +- src/librustc/mir/mod.rs | 11 +- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/ty/context.rs | 26 +- src/librustc/ty/maps.rs | 2 + src/librustc/ty/mod.rs | 19 +- src/librustc/ty/util.rs | 4 +- src/librustc_borrowck/borrowck/check_loans.rs | 4 +- .../borrowck/gather_loans/gather_moves.rs | 12 +- .../borrowck/gather_loans/mod.rs | 36 +- src/librustc_borrowck/borrowck/mod.rs | 33 +- src/librustc_const_eval/check_match.rs | 18 +- src/librustc_const_eval/eval.rs | 360 +++++++++--------- src/librustc_const_eval/pattern.rs | 53 +-- src/librustc_driver/pretty.rs | 20 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/builtin.rs | 51 ++- src/librustc_lint/types.rs | 25 +- src/librustc_lint/unused.rs | 4 +- src/librustc_metadata/astencode.rs | 14 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_mir/build/mod.rs | 9 +- src/librustc_mir/hair/cx/block.rs | 4 +- src/librustc_mir/hair/cx/expr.rs | 81 ++-- src/librustc_mir/hair/cx/mod.rs | 12 +- src/librustc_mir/mir_map.rs | 201 +++------- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_passes/consts.rs | 65 ++-- src/librustc_passes/rvalues.rs | 27 +- src/librustc_privacy/lib.rs | 22 +- src/librustc_save_analysis/dump_visitor.rs | 50 ++- src/librustc_save_analysis/lib.rs | 36 +- src/librustc_trans/common.rs | 2 +- src/librustc_trans/context.rs | 2 +- src/librustc_trans/glue.rs | 2 +- src/librustc_trans/mir/constant.rs | 1 - src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 12 +- src/librustc_typeck/check/mod.rs | 24 +- src/librustc_typeck/check/upvar.rs | 6 +- src/librustc_typeck/check/writeback.rs | 21 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 2 +- src/librustc_typeck/collect.rs | 10 +- src/librustc_typeck/lib.rs | 2 +- src/librustdoc/Cargo.toml | 1 - src/librustdoc/clean/mod.rs | 20 +- src/librustdoc/lib.rs | 1 - src/test/compile-fail/const-eval-overflow.rs | 14 +- src/test/run-pass/issue-28189.rs | 15 - 68 files changed, 946 insertions(+), 979 deletions(-) delete mode 100644 src/test/run-pass/issue-28189.rs 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/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/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/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/lint/context.rs b/src/librustc/lint/context.rs index cce79820ca8da..f7f9a17ee51ee 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}; @@ -336,6 +336,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, @@ -703,22 +706,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 +782,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 +832,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 +1238,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/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/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..0860881bf6bd5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -211,13 +211,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 +231,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 +240,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() } @@ -524,6 +522,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>, @@ -777,6 +783,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..b2337372805a9 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -46,3 +46,5 @@ 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> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fa62e893a2875..86a9372989dc5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1921,6 +1921,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.tables.borrow() } + pub fn body_tables(self, body: hir::BodyId) -> &'a Tables<'gcx> { + self.item_tables(self.map.body_owner_def_id(body)) + } + + pub fn item_tables(self, _def_id: DefId) -> &'a Tables<'gcx> { + // HACK(eddyb) temporarily work around RefCell until proper per-body tables + unsafe { + mem::transmute::<&Tables, &Tables>(&self.tables()) + } + } + pub fn expr_span(self, id: NodeId) -> Span { match self.map.find(id) { Some(ast_map::NodeExpr(e)) => { @@ -2454,12 +2465,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 +2482,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_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_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..442d583907b1f 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -52,34 +52,25 @@ 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, &'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 { + if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) { + match it.node { hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - variant_expr(variants, variant_node_id) + for variant in variants { + if variant.node.data.id() == variant_node_id { + return variant.node.disr_expr.map(|e| { + (&tcx.map.body(e).value, tcx.body_tables(e)) + }); + } + } } - _ => None - }, - Some(_) => None + _ => {} + } } - } else { - None } + None } /// * `def_id` is the id of the constant. @@ -90,17 +81,20 @@ 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, &'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.item_tables(def_id), + 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 { @@ -110,7 +104,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.local_def_id(trait_id); let default_value = default.map(|body| { - (&tcx.map.body(body).value, + (&tcx.map.body(body).value, tcx.item_tables(def_id), tcx.ast_ty_to_prim_ty(ty)) }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) @@ -126,18 +120,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, 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 +136,37 @@ 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, &'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.body_tables(fn_like.body()))) } 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, tcx.item_tables(def_id)) + }) } else { None } @@ -230,30 +221,33 @@ 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: &'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 { + ConstContext::with_tables(tcx, tcx.body_tables(body)) + } + + pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self { + ConstContext { + tcx: tcx, + tables: tables, + fn_args: None + } + } -pub type FnArgMap<'a> = Option<&'a DefIdMap>; + /// 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 +427,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)) + Some(cx.tables.expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -457,7 +447,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.expr_ty_opt(e) } }; let result = match e.node { @@ -510,14 +500,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 +523,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 +594,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.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 +613,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 +623,23 @@ 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.qpath_def(qpath, e.id); 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.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::with_tables(tcx, tables); + match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -660,8 +651,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::with_tables(tcx, tables); + match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -673,11 +665,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 +682,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 +702,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 +722,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 +776,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 +815,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 +903,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, &'a ty::Tables<'tcx>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, Option>)> +) -> Option<(&'tcx Expr, &'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 +1154,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..86c11dc32da12 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; + 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_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_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/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_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index b27b164bd47aa..692e1e62c61a6 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -55,6 +55,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tables_pos = self.position(); let tables_count = { let mut visitor = SideTableEncodingIdVisitor { + tables: self.tcx.body_tables(body.id()), ecx: self, count: 0, }; @@ -87,6 +88,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> { ecx: &'a mut EncodeContext<'b, 'tcx>, + tables: &'a ty::Tables<'tcx>, count: usize, } @@ -98,7 +100,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { fn visit_id(&mut self, id: ast::NodeId) { debug!("Encoding side tables for id {}", id); - let tcx = self.ecx.tcx; + let tables = self.tables; let mut encode = |entry: Option| { if let Some(entry) = entry { (id, entry).encode(self.ecx).unwrap(); @@ -106,11 +108,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { } }; - 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)); + encode(tables.type_relative_path_defs.get(&id).cloned() + .map(TableEntry::TypeRelativeDef)); + encode(tables.node_types.get(&id).cloned().map(TableEntry::NodeType)); + encode(tables.item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); + encode(tables.adjustments.get(&id).cloned().map(TableEntry::Adjustment)); } } 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_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..aa5ebdf77a2ab 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,7 @@ 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; @@ -128,7 +128,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 +181,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/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/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/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_privacy/lib.rs b/src/librustc_privacy/lib.rs index 84fa2e9d6bbaa..ef7a1f695ffb4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -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_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 3f7f3bdba017f..0fbe29880b999 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -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/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/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/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/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..bc485223a43ba 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); @@ -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..0f5f8d889e810 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -228,11 +228,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); } @@ -280,13 +275,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); } } @@ -496,7 +493,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 +510,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 75cd9e2f96772..6d30a85b58291 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -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 c6951d4edd678..503ef4c3183d2 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -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/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/run-pass/issue-28189.rs b/src/test/run-pass/issue-28189.rs deleted file mode 100644 index 0e624a778583d..0000000000000 --- a/src/test/run-pass/issue-28189.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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. - -struct S(T) where [T; (||{}, 1).1]: Copy; - -fn main() { - -} From 4eea99e613a411e4037272fd028124ced8e065bd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 4 Jan 2017 04:01:58 +0200 Subject: [PATCH 12/53] rustc: store ty::Tables separately for each body (except closures'). --- src/librustc/dep_graph/dep_node.rs | 3 + src/librustc/hir/map/collector.rs | 38 +--- src/librustc/hir/map/mod.rs | 242 ++++++++--------------- src/librustc/ty/context.rs | 11 +- src/librustc/ty/maps.rs | 1 + src/librustc/ty/mod.rs | 35 ++-- src/librustc_const_eval/eval.rs | 72 ++++--- src/librustc_const_eval/pattern.rs | 2 +- src/librustc_metadata/astencode.rs | 120 ++--------- src/librustc_metadata/cstore.rs | 2 - src/librustc_metadata/cstore_impl.rs | 21 +- src/librustc_metadata/decoder.rs | 63 +----- src/librustc_mir/hair/cx/mod.rs | 13 +- src/librustc_trans/consts.rs | 2 - src/librustc_trans/debuginfo/metadata.rs | 8 - src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/writeback.rs | 57 +++--- 17 files changed, 220 insertions(+), 474 deletions(-) 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/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/ty/context.rs b/src/librustc/ty/context.rs index 0860881bf6bd5..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, @@ -399,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>>, @@ -651,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) } @@ -749,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())), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index b2337372805a9..59d22d270b15d 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -48,3 +48,4 @@ 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 86a9372989dc5..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,19 +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) -> &'a Tables<'gcx> { + 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) -> &'a Tables<'gcx> { - // HACK(eddyb) temporarily work around RefCell until proper per-body tables - unsafe { - mem::transmute::<&Tables, &Tables>(&self.tables()) - } + 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 { diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 442d583907b1f..bc72c8fb9b6fe 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -52,21 +52,20 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>)> { + -> 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); if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) { - match it.node { - hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - for variant in variants { - if variant.node.data.id() == variant_node_id { - return variant.node.disr_expr.map(|e| { - (&tcx.map.body(e).value, tcx.body_tables(e)) - }); - } + 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()) + }); } } - _ => {} } } } @@ -81,7 +80,8 @@ 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, &'a ty::Tables<'tcx>, + -> 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) { @@ -92,7 +92,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(ast_map::NodeImplItem(&hir::ImplItem { node: hir::ImplItemKind::Const(ref ty, body), .. })) => { - Some((&tcx.map.body(body).value, tcx.item_tables(def_id), + 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 { @@ -104,7 +105,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.local_def_id(trait_id); let default_value = default.map(|body| { - (&tcx.map.body(body).value, tcx.item_tables(def_id), + (&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) @@ -124,7 +126,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } else { let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (&body.value, tcx.item_tables(def_id), + (&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) { @@ -152,12 +154,13 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option<(&'tcx hir::Body, &'a ty::Tables<'tcx>)> + -> 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()), tcx.body_tables(fn_like.body()))) + Some((tcx.map.body(fn_like.body()), + tcx.tables.borrow().get(&def_id).cloned())) } else { None } @@ -165,7 +168,7 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } else { if tcx.sess.cstore.is_const_fn(def_id) { tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (body, tcx.item_tables(def_id)) + (body, Some(tcx.item_tables(def_id))) }) } else { None @@ -223,19 +226,24 @@ pub fn note_const_eval_err<'a, 'tcx>( pub struct ConstContext<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - tables: &'a ty::Tables<'tcx>, + tables: Option<&'a ty::Tables<'tcx>>, fn_args: Option> } impl<'a, 'tcx> ConstContext<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { - ConstContext::with_tables(tcx, tcx.body_tables(body)) + 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 fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self { ConstContext { tcx: tcx, - tables: tables, + tables: Some(tables), fn_args: None } } @@ -436,7 +444,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(cx.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 @@ -447,7 +455,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, '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). - cx.tables.expr_ty_opt(e) + cx.tables.and_then(|tables| tables.expr_ty_opt(e)) } }; let result = match e.node { @@ -594,7 +602,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match cx.tables.expr_ty_opt(&base) { + match cx.tables.and_then(|tables| tables.expr_ty_opt(&base)) { Some(t) => UncheckedExprHint(t), None => ty_hint } @@ -623,12 +631,18 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, } } hir::ExprPath(ref qpath) => { - let def = cx.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(cx.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 @@ -638,7 +652,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, Some(ty) => ty_hint.checked_or(ty), None => ty_hint, }; - let cx = ConstContext::with_tables(tcx, tables); + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { @@ -652,7 +666,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, }, Def::VariantCtor(variant_def, ..) => { if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { - let cx = ConstContext::with_tables(tcx, tables); + let cx = ConstContext { tcx: tcx, tables: tables, fn_args: None }; match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { @@ -903,10 +917,10 @@ 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, &'a ty::Tables<'tcx>, Option>)>, + default_value: Option<(&'tcx Expr, Option<&'a ty::Tables<'tcx>>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, 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={:?}", diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 86c11dc32da12..fbd15b6eb1035 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -582,7 +582,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { Some((const_expr, const_tables, _const_ty)) => { // Enter the inlined constant's tables temporarily. let old_tables = self.tables; - self.tables = const_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; diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 692e1e62c61a6..3c14d38cc3821 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -8,60 +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 { - tables: self.tcx.body_tables(body.id()), - 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 = { @@ -77,45 +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>, - tables: &'a ty::Tables<'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 tables = self.tables; - let mut encode = |entry: Option| { - if let Some(entry) = entry { - (id, entry).encode(self.ecx).unwrap(); - self.count += 1; - } - }; - - encode(tables.type_relative_path_defs.get(&id).cloned() - .map(TableEntry::TypeRelativeDef)); - encode(tables.node_types.get(&id).cloned().map(TableEntry::NodeType)); - encode(tables.item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tables.adjustments.get(&id).cloned().map(TableEntry::Adjustment)); - } -} - struct NestedBodyEncodingVisitor<'a, 'b: 'a, 'tcx: 'b> { ecx: &'a mut EncodeContext<'b, 'tcx>, count: usize, @@ -134,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_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index aa5ebdf77a2ab..4b553a71b8325 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -20,7 +20,6 @@ use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; 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 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/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_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bc485223a43ba..ceb97c63d1327 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -679,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); }); } @@ -1246,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); }); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 0f5f8d889e810..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 @@ -238,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; } @@ -262,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); } } @@ -336,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` @@ -348,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 @@ -357,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 => { @@ -405,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 @@ -433,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); From d28a5344fc7891c8c0762d6543ae5c4eb7333102 Mon Sep 17 00:00:00 2001 From: abhijeetbhagat Date: Tue, 3 Jan 2017 17:50:30 +0530 Subject: [PATCH 13/53] Fix process module tests to run on Windows --- src/libstd/process.rs | 85 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index e15c37aaf2491..2140d9c68f40b 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; /// ``` @@ -925,7 +932,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 +954,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 +997,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 +1065,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 +1092,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 +1108,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 +1122,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 +1145,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(); From 920ecd95b7a4b018e172c12c234f79af3d889a84 Mon Sep 17 00:00:00 2001 From: abhijeetbhagat Date: Wed, 4 Jan 2017 14:27:19 +0530 Subject: [PATCH 14/53] Fix formatting --- src/libstd/process.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 2140d9c68f40b..7fb30847a9f4b 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -932,7 +932,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn smoke() { - let p = if cfg!(target_os = "windows"){ + let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).spawn() } else { Command::new("true").spawn() @@ -954,7 +954,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn exit_reported_right() { - let p = if cfg!(target_os = "windows"){ + let p = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn() } else { Command::new("false").spawn() @@ -997,7 +997,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn stdout_works() { - if cfg!(target_os = "windows"){ + 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"); @@ -1065,14 +1065,14 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_process_status() { - let mut status = if cfg!(target_os = "windows"){ + 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 = if cfg!(target_os = "windows"){ + status = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap() } else { Command::new("true").status().unwrap() @@ -1092,7 +1092,7 @@ mod tests { #[cfg_attr(target_os = "android", ignore)] fn test_process_output_output() { let Output {status, stdout, stderr} - = if cfg!(target_os = "windows"){ + = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap() } else { Command::new("echo").arg("hello").output().unwrap() @@ -1108,7 +1108,7 @@ mod tests { #[cfg_attr(target_os = "android", ignore)] fn test_process_output_error() { let Output {status, stdout, stderr} - = if cfg!(target_os = "windows"){ + = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap() } else { Command::new("mkdir").arg(".").output().unwrap() @@ -1122,7 +1122,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_finish_once() { - let mut prog = if cfg!(target_os = "windows"){ + let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { Command::new("false").spawn().unwrap() @@ -1133,7 +1133,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_finish_twice() { - let mut prog = if cfg!(target_os = "windows"){ + let mut prog = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap() } else { Command::new("false").spawn().unwrap() @@ -1145,7 +1145,7 @@ mod tests { #[test] #[cfg_attr(target_os = "android", ignore)] fn test_wait_with_output_once() { - let prog = if cfg!(target_os = "windows"){ + 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() From 68f913e26be70e7a0a0d2bca03834c849c49cb30 Mon Sep 17 00:00:00 2001 From: abhijeetbhagat Date: Wed, 4 Jan 2017 14:39:16 +0530 Subject: [PATCH 15/53] Fix formatting --- src/libstd/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 7fb30847a9f4b..1a11d7ad9d7bc 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -260,7 +260,7 @@ impl fmt::Debug for ChildStderr { /// ``` /// use std::process::Command; /// -/// let output = if cfg!(target_os = "windows"){ +/// let output = if cfg!(target_os = "windows") { /// Command::new("cmd") /// .args(&["/C", "echo hello"]) /// .output() From 9df835005dce42647d7b0ee900a77ffead6be243 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 5 Jan 2017 02:33:09 +0200 Subject: [PATCH 16/53] Allow projections to be promoted to constants in MIR. --- src/librustc_mir/transform/promote_consts.rs | 25 +++++++++--------- src/librustc_trans/collector.rs | 1 + src/test/run-pass/issue-38074.rs | 27 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 src/test/run-pass/issue-38074.rs 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_trans/collector.rs b/src/librustc_trans/collector.rs index 094f293e5eba2..ff8a14474e57d 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1287,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/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); +} From 6499d137543e927f120149513cbd4597a43999a6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Jan 2017 11:16:48 -0800 Subject: [PATCH 17/53] rustbuild: Don't build target compilers in stage0 The `doc-book` and `doc-nomicon` steps accidentally depended on a rustbook compiled by a cross-compiled compiler, which isn't necessary. Be sure to set the `host` on these dependency edges to the build compiler to ensure that we're always using a tool compiled for the host platform. This was discovered trawling the build logs for the new dist bots and discovering that they're building one too many compilers in stage0. --- src/bootstrap/step.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index bf815a817ed87..c3e10405eb532 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -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") From 853f12d626cdd88ddee31e7aa9a4ee78d48bd12c Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 6 Jan 2017 02:49:28 +0100 Subject: [PATCH 18/53] Make members of {std,core}::{i128,u128} unstable Adding it in a stable form was an accident. It thankfully only leaked to nightly. Fixes #38860 --- src/libcore/num/i128.rs | 2 +- src/libcore/num/int_macros.rs | 23 +++++++++++----------- src/libcore/num/u128.rs | 2 +- src/libcore/num/uint_macros.rs | 23 +++++++++++----------- src/librustc_const_math/lib.rs | 1 + src/test/compile-fail/i128-feature-libs.rs | 17 ++++++++++++++++ 6 files changed, 44 insertions(+), 24 deletions(-) create mode 100644 src/test/compile-fail/i128-feature-libs.rs 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/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/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' +} From cd54cfd1eeb42d8d8e5439b43464a0a162cea896 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 6 Jan 2017 21:28:57 -0800 Subject: [PATCH 19/53] travis: Wrap submodules updates in travis_retry Let's try to squash some of those network issues with a `travis_retry` tool to just retry the command a few times. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From 461d231a604553ad1be9533a2875ecabf759d549 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 7 Jan 2017 07:55:06 -0800 Subject: [PATCH 20/53] rustbuild: Pass --retry 3 to curl Try to handle spurious network failures on Travis by automatically retrying failed downloads on Travis. --- src/bootstrap/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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): From ea20fbe9868fb01888fe8ba263d0657dec16eef8 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sat, 7 Jan 2017 13:41:16 -0500 Subject: [PATCH 21/53] Improve safety warning on ptr::swap --- src/libcore/ptr.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e3ca8eca76c57..0aa8e4319ce2f 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, which means they will be dereferenced. +/// +/// 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) { From 1096235a837f1a195fb7f5e1b4ebf15007960c08 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sat, 7 Jan 2017 14:27:04 -0500 Subject: [PATCH 22/53] thanks @eddyb --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 0aa8e4319ce2f..bf5a59c45e4d3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -75,7 +75,7 @@ pub const fn null_mut() -> *mut T { 0 as *mut T } /// # Safety /// /// This function copies the memory through the raw pointers passed to it -/// as arguments, which means they will be dereferenced. +/// as arguments. /// /// Ensure that these pointers are valid before calling `swap`. #[inline] From 623ca88e55c6d19307219e3edcc8fabf415340bc Mon Sep 17 00:00:00 2001 From: Kyle Aleshire Date: Wed, 4 Jan 2017 18:23:19 -0600 Subject: [PATCH 23/53] Warn that the name is ignored if a link target is emitted --- src/librustc_driver/driver.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 63abc09a07672..d51d1e888337b 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 output name requested with -o for \"link\" output because \ + multiple outputs were requested"); None } else { Some(out_file.clone()) From fd6977892ca9f967ce91e1563016ba9dda583aac Mon Sep 17 00:00:00 2001 From: Kyle Aleshire Date: Fri, 6 Jan 2017 19:13:59 -0600 Subject: [PATCH 24/53] Error message more like original --- src/librustc_driver/driver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index d51d1e888337b..442c139f14c06 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1336,8 +1336,8 @@ pub fn build_output_filenames(input: &Input, .count(); let ofile = if unnamed_output_types > 1 && sess.opts.output_types.contains_key(&OutputType::Exe) { - sess.warn("ignoring output name requested with -o for \"link\" output because \ - multiple outputs were requested"); + sess.warn("ignoring specified output filename for 'link' output because multiple \ + outputs were requested"); None } else { Some(out_file.clone()) From d141ba11746e32582fb10c8d1c6eb0f24dea659f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 5 Jan 2017 22:47:09 -0800 Subject: [PATCH 25/53] std: Add a nonblocking `Child::try_wait` method This commit adds a new method to the `Child` type in the `std::process` module called `try_wait`. This method is the same as `wait` except that it will not block the calling thread and instead only attempt to collect the exit status. On Unix this means that we call `waitpid` with the `WNOHANG` flag and on Windows it just means that we pass a 0 timeout to `WaitForSingleObject`. Currently it's possible to build this method out of tree, but it's unfortunately tricky to do so. Specifically on Unix you essentially lose ownership of the pid for the process once a call to `waitpid` has succeeded. Although `Child` tracks this state internally to be resilient to multiple calls to `wait` or a `kill` after a successful wait, if the child is waited on externally then the state inside of `Child` is not updated. This means that external implementations of this method must be extra careful to essentially not use a `Child`'s methods after a call to `waitpid` has succeeded (even in a nonblocking fashion). By adding this functionality to the standard library it should help canonicalize these external implementations and ensure they can continue to robustly reuse the `Child` type from the standard library without worrying about pid ownership. --- src/libstd/process.rs | 42 +++++++++++++ src/libstd/sys/unix/process/process_unix.rs | 17 ++++++ src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/process.rs | 15 +++++ src/test/run-pass/try-wait.rs | 65 +++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 src/test/run-pass/try-wait.rs diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 1a11d7ad9d7bc..aa76b79253582 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -800,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. 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/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()); +} From e3d9ecb9fc6883d62fcded5856639519f35181f3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 Jan 2017 15:09:55 +0300 Subject: [PATCH 26/53] Avoid large number of stage 0 warnings about --no-stack-check --- mk/main.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From fe49daeef43377d270cb3a34a51a9b5d88697f70 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sun, 8 Jan 2017 11:37:52 -0800 Subject: [PATCH 27/53] Don't restrict docs in compiler-docs mode --- src/bootstrap/doc.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) 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) } From 6cf3aafa10a87196f1f4e4dc646d68885baa40a7 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 23 Nov 2016 22:10:34 -0500 Subject: [PATCH 28/53] std: link to liballoc_system if compiled without the jemalloc feature fixes #36501 --- src/libstd/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9557c520c5071..87dce860278ca 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,7 +221,7 @@ // 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 @@ -332,7 +332,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 From f00bbe0fa3dc88d48bd04d9579458000c0dd0ad7 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 23 Dec 2016 09:05:53 -0500 Subject: [PATCH 29/53] fix Makefiles --- mk/crates.mk | 1 + 1 file changed, 1 insertion(+) 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 From fe71e30ed89726ef825d1c03e4dd3a4692cd9a60 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 18:55:36 -0800 Subject: [PATCH 30/53] note individual lint name set via lint group attribute in notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warning or error messages set via a lint group attribute (e.g. `#[deny(warnings)]`) should still make it clear which individual lint (by name) was triggered, similarly to how we include "on by default" language for default lints. This—and, while we're here, the existing "on by default" language—can be tucked into a note rather than cluttering the main error message. This occasions the slightest of refactorings (we now have to get the diagnostic-builder with the main message first, before matching on the lint source). This is in the matter of #36846. --- src/librustc/lint/context.rs | 53 +++++++++++-------- src/librustc/lint/mod.rs | 2 +- .../imports/rfc-1560-warning-cycle.rs | 1 + src/test/compile-fail/issue-30730.rs | 4 +- src/test/compile-fail/lint-group-style.rs | 20 +++++-- src/test/compile-fail/lint-output-format-2.rs | 11 ++-- src/test/run-pass/path-lookahead.rs | 6 +-- src/test/ui/span/issue-24690.stderr | 4 ++ src/test/ui/span/multispan-import-lint.stderr | 4 +- 9 files changed, 68 insertions(+), 37 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index f7f9a17ee51ee..d45583e832488 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -39,6 +39,7 @@ 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_pos::{MultiSpan, Span}; @@ -445,35 +446,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[..]), @@ -481,6 +465,27 @@ 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 => { + err.note(&format!("[-{} {}]", + match level { + Warn => 'W', Deny => 'D', Forbid => 'F', + Allow => bug!() + }, name.replace("_", "-"))); + }, + 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!("#[{}({})] implies #[{}({})]", + level_str, lint_attr_name, level_str, 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 \ @@ -648,6 +653,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 { @@ -659,7 +666,7 @@ 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")) }, @@ -671,7 +678,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))); } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 7e0da00694c4a..bf05b1310a909 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -336,7 +336,7 @@ 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, 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..6082740f427d7 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(warnings)] implies #[deny(unused_imports)] fn main() {} diff --git a/src/test/compile-fail/lint-group-style.rs b/src/test/compile-fail/lint-group-style.rs index b2e6072c9855c..a8c377034756a 100644 --- a/src/test/compile-fail/lint-group-style.rs +++ b/src/test/compile-fail/lint-group-style.rs @@ -12,7 +12,9 @@ //~^ NOTE lint level defined here #![allow(dead_code)] -fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name +fn CamelCase() {} +//~^ ERROR function `CamelCase` should have a snake case name +//~| NOTE #[deny(bad_style)] implies #[deny(non_snake_case)] #[allow(bad_style)] mod test { @@ -22,9 +24,13 @@ mod test { //~^ NOTE lint level defined here //~^^ NOTE lint level defined here mod bad { - fn CamelCase() {} //~ ERROR function `CamelCase` should have a snake case name + fn CamelCase() {} + //~^ ERROR function `CamelCase` should have a snake case name + //~| NOTE #[forbid(bad_style)] implies #[forbid(non_snake_case)] - static bad: isize = 1; //~ ERROR static variable `bad` should have an upper case name + static bad: isize = 1; + //~^ ERROR static variable `bad` should have an upper case name + //~| NOTE #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] } mod warn { @@ -32,9 +38,13 @@ mod test { //~^ NOTE lint level defined here //~| NOTE lint level defined here - fn CamelCase() {} //~ WARN function `CamelCase` should have a snake case name + fn CamelCase() {} + //~^ WARN function `CamelCase` should have a snake case name + //~| NOTE #[warn(bad_style)] implies #[warn(non_snake_case)] - struct snake_case; //~ WARN type `snake_case` should have a camel case name + struct snake_case; + //~^ WARN type `snake_case` should have a camel case name + //~| NOTE #[warn(bad_style)] implies #[warn(non_camel_case_types)] } } diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 2f74325d19c7d..8b76bedb003c0 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 [-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/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/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 0d2a2ef751666..9888fa64e3826 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(warnings)] implies #[deny(unused_variables)] 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(warnings)] implies #[deny(non_snake_case)] 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(warnings)] implies #[deny(non_snake_case)] error: aborting due to 3 previous errors 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 From 69cd9a318e7eebc4bbed075fa033846a009ba9d8 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 18:55:43 -0800 Subject: [PATCH 31/53] note lint group set on command line triggering individual lint Previously, the note/message for the source of a lint being the command line unconditionally named the individual lint, even if the actual command specified a lint group (e.g., `-D warnings`); here, we take note of the actual command options so we can be more specific. This remains in the matter of #36846. --- src/librustc/lint/context.rs | 28 +++++++++++++------ src/librustc/lint/mod.rs | 3 +- src/test/compile-fail/lint-output-format-2.rs | 2 +- .../ui/lint/command-line-lint-group-allow.rs | 15 ++++++++++ .../ui/lint/command-line-lint-group-deny.rs | 15 ++++++++++ .../lint/command-line-lint-group-deny.stderr | 10 +++++++ .../ui/lint/command-line-lint-group-forbid.rs | 15 ++++++++++ .../command-line-lint-group-forbid.stderr | 10 +++++++ .../ui/lint/command-line-lint-group-warn.rs | 15 ++++++++++ .../lint/command-line-lint-group-warn.stderr | 8 ++++++ 10 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/lint/command-line-lint-group-allow.rs create mode 100644 src/test/ui/lint/command-line-lint-group-deny.rs create mode 100644 src/test/ui/lint/command-line-lint-group-deny.stderr create mode 100644 src/test/ui/lint/command-line-lint-group-forbid.rs create mode 100644 src/test/ui/lint/command-line-lint-group-forbid.stderr create mode 100644 src/test/ui/lint/command-line-lint-group-warn.rs create mode 100644 src/test/ui/lint/command-line-lint-group-warn.stderr diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index d45583e832488..94d9beb04e0cd 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,6 +42,7 @@ 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; @@ -299,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())) @@ -310,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 => { @@ -469,12 +471,20 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, Default => { err.note(&format!("#[{}({})] on by default", level.as_str(), name)); }, - CommandLine => { - err.note(&format!("[-{} {}]", - match level { - Warn => 'W', Deny => 'D', Forbid => 'F', - Allow => bug!() - }, name.replace("_", "-"))); + 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!("`{} {}` implies `{} {}`", + flag, hyphen_case_flag_val, flag, hyphen_case_lint_name)); + } }, Node(lint_attr_name, src) => { def = Some(src); @@ -670,7 +680,7 @@ pub trait LintContext<'tcx>: Sized { 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() diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index bf05b1310a909..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, @@ -339,7 +340,7 @@ pub enum LintSource { 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/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs index 8b76bedb003c0..0e68ff752e5a9 100644 --- a/src/test/compile-fail/lint-output-format-2.rs +++ b/src/test/compile-fail/lint-output-format-2.rs @@ -13,7 +13,7 @@ #![feature(foo)] //~^ ERROR unused or unknown feature -//~| NOTE [-F unused-features] +//~| NOTE requested on the command line with `-F unused-features` #![feature(test_feature)] diff --git a/src/test/ui/lint/command-line-lint-group-allow.rs b/src/test/ui/lint/command-line-lint-group-allow.rs new file mode 100644 index 0000000000000..cdb9684933d9b --- /dev/null +++ b/src/test/ui/lint/command-line-lint-group-allow.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: -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..eafbf944dea97 --- /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 bad-style` implies `-D non-snake-case` + +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..0cf896060a27f --- /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 bad-style` implies `-F non-snake-case` + +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..4ffbff6cdb7ec --- /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 bad-style` implies `-W non-snake-case` + From 986929ea32cca53601539cda6504a1cf9e6ca9f7 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Wed, 4 Jan 2017 23:32:09 -0800 Subject: [PATCH 32/53] make lint-group-style test a UI rather than a compile-fail test As suggested by Niko Matsakis in review (https://github.com/rust-lang/rust/pull/38103#discussion_r94460982) regarding the endeavor prompted by #36846. --- src/test/compile-fail/lint-group-style.rs | 51 ----------------- src/test/ui/lint/lint-group-style.rs | 36 ++++++++++++ src/test/ui/lint/lint-group-style.stderr | 67 +++++++++++++++++++++++ 3 files changed, 103 insertions(+), 51 deletions(-) delete mode 100644 src/test/compile-fail/lint-group-style.rs create mode 100644 src/test/ui/lint/lint-group-style.rs create mode 100644 src/test/ui/lint/lint-group-style.stderr 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 a8c377034756a..0000000000000 --- a/src/test/compile-fail/lint-group-style.rs +++ /dev/null @@ -1,51 +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 -//~| NOTE #[deny(bad_style)] implies #[deny(non_snake_case)] - -#[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 - //~| NOTE #[forbid(bad_style)] implies #[forbid(non_snake_case)] - - static bad: isize = 1; - //~^ ERROR static variable `bad` should have an upper case name - //~| NOTE #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] - } - - 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 - //~| NOTE #[warn(bad_style)] implies #[warn(non_snake_case)] - - struct snake_case; - //~^ WARN type `snake_case` should have a camel case name - //~| NOTE #[warn(bad_style)] implies #[warn(non_camel_case_types)] - } -} - -fn main() {} 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..93f6399b22726 --- /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(bad_style)] implies #[deny(non_snake_case)] +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(bad_style)] implies #[forbid(non_snake_case)] +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(bad_style)] implies #[forbid(non_upper_case_globals)] +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(bad_style)] implies #[warn(non_snake_case)] +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(bad_style)] implies #[warn(non_camel_case_types)] +note: lint level defined here + --> $DIR/lint-group-style.rs:28:17 + | +28 | #![warn(bad_style)] + | ^^^^^^^^^ + +error: aborting due to 3 previous errors + From a56abddf76eee47bdf743cada82c9060f785706d Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Thu, 5 Jan 2017 20:01:22 -0800 Subject: [PATCH 33/53] note wording: lint implied by lint group, not lint group implies lint --- src/librustc/lint/context.rs | 8 ++++---- src/test/compile-fail/issue-30730.rs | 2 +- src/test/ui/lint/command-line-lint-group-deny.stderr | 2 +- src/test/ui/lint/command-line-lint-group-forbid.stderr | 2 +- src/test/ui/lint/command-line-lint-group-warn.stderr | 2 +- src/test/ui/lint/lint-group-style.stderr | 10 +++++----- src/test/ui/span/issue-24690.stderr | 6 +++--- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 94d9beb04e0cd..cfe5cc1739a7c 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -482,16 +482,16 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session, flag, hyphen_case_lint_name)); } else { let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); - err.note(&format!("`{} {}` implies `{} {}`", - flag, hyphen_case_flag_val, flag, hyphen_case_lint_name)); + 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!("#[{}({})] implies #[{}({})]", - level_str, lint_attr_name, level_str, name)); + err.note(&format!("#[{}({})] implied by #[{}({})]", + level_str, name, level_str, lint_attr_name)); } } } diff --git a/src/test/compile-fail/issue-30730.rs b/src/test/compile-fail/issue-30730.rs index 6082740f427d7..086938334c78a 100644 --- a/src/test/compile-fail/issue-30730.rs +++ b/src/test/compile-fail/issue-30730.rs @@ -11,5 +11,5 @@ #![deny(warnings)] //~ NOTE: lint level defined here use std::thread; //~^ ERROR: unused import -//~| NOTE: #[deny(warnings)] implies #[deny(unused_imports)] +//~| NOTE: #[deny(unused_imports)] implied by #[deny(warnings)] fn main() {} diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr index eafbf944dea97..23fac66cc6c98 100644 --- a/src/test/ui/lint/command-line-lint-group-deny.stderr +++ b/src/test/ui/lint/command-line-lint-group-deny.stderr @@ -4,7 +4,7 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-D bad-style` implies `-D non-snake-case` + = 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.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr index 0cf896060a27f..0babd7f6fe47a 100644 --- a/src/test/ui/lint/command-line-lint-group-forbid.stderr +++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr @@ -4,7 +4,7 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-F bad-style` implies `-F non-snake-case` + = 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.stderr b/src/test/ui/lint/command-line-lint-group-warn.stderr index 4ffbff6cdb7ec..998c892c7e349 100644 --- a/src/test/ui/lint/command-line-lint-group-warn.stderr +++ b/src/test/ui/lint/command-line-lint-group-warn.stderr @@ -4,5 +4,5 @@ warning: variable `_InappropriateCamelCasing` should have a snake case name such 14 | let _InappropriateCamelCasing = true; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `-W bad-style` implies `-W non-snake-case` + = note: `-W non-snake-case` implied by `-W bad-style` diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr index 93f6399b22726..9c0f4866af690 100644 --- a/src/test/ui/lint/lint-group-style.stderr +++ b/src/test/ui/lint/lint-group-style.stderr @@ -4,7 +4,7 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 14 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[deny(bad_style)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:11:9 | @@ -17,7 +17,7 @@ error: function `CamelCase` should have a snake case name such as `camel_case` 22 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[forbid(bad_style)] implies #[forbid(non_snake_case)] + = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | @@ -30,7 +30,7 @@ error: static variable `bad` should have an upper case name such as `BAD` 24 | static bad: isize = 1; | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[forbid(bad_style)] implies #[forbid(non_upper_case_globals)] + = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:20:14 | @@ -43,7 +43,7 @@ warning: function `CamelCase` should have a snake case name such as `camel_case` 30 | fn CamelCase() {} | ^^^^^^^^^^^^^^^^^ | - = note: #[warn(bad_style)] implies #[warn(non_snake_case)] + = note: #[warn(non_snake_case)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | @@ -56,7 +56,7 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase` 32 | struct snake_case; | ^^^^^^^^^^^^^^^^^^ | - = note: #[warn(bad_style)] implies #[warn(non_camel_case_types)] + = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)] note: lint level defined here --> $DIR/lint-group-style.rs:28:17 | diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 9888fa64e3826..881b6321d25d6 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -4,7 +4,7 @@ error: unused variable: `theOtherTwo` 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(warnings)] implies #[deny(unused_variables)] + = note: #[deny(unused_variables)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -17,7 +17,7 @@ error: variable `theTwo` should have a snake case name such as `the_two` 19 | let theTwo = 2; | ^^^^^^ | - = note: #[deny(warnings)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] note: lint level defined here --> $DIR/issue-24690.rs:16:9 | @@ -30,7 +30,7 @@ error: variable `theOtherTwo` should have a snake case name such as `the_other_t 20 | let theOtherTwo = 2; | ^^^^^^^^^^^ | - = note: #[deny(warnings)] implies #[deny(non_snake_case)] + = note: #[deny(non_snake_case)] implied by #[deny(warnings)] error: aborting due to 3 previous errors From f7dbec3d2fbb184c7349d7b359428e1bf1597b54 Mon Sep 17 00:00:00 2001 From: Robin Kruppe Date: Sat, 3 Dec 2016 02:10:59 +0100 Subject: [PATCH 34/53] book: use abort() over loop {} for panic Due to #28728 loop {} is very risky and can lead to fun debugging experiences like in #38136. Besides, aborting is probably better behavior than an infinite loop. --- src/doc/book/lang-items.md | 11 ++++------- src/doc/book/no-stdlib.md | 10 ++++++---- 2 files changed, 10 insertions(+), 11 deletions(-) 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() } } ``` From ba1f88425de31616c3cca1ed08b1ef3a30ba9c80 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 14 Dec 2016 16:14:19 +0100 Subject: [PATCH 35/53] Add time module missing docs --- src/libstd/time/mod.rs | 129 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 14 deletions(-) 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 From a160177b86864d8091903e191c573d061799145a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 23 Dec 2016 12:18:40 -0800 Subject: [PATCH 36/53] Clarify behavior of `VecDeque::insert`. Fixes https://github.com/rust-lang/rust/issues/37046. --- src/libcollections/vec_deque.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 67621b860bf39..d650360435aa0 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1228,9 +1228,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 +1238,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) { From 3816222d93ee439bf5c722bbbd080344bbf194f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Dec 2016 12:50:28 -0800 Subject: [PATCH 37/53] Add test for correct span for type Test for #27522. --- src/test/ui/span/issue-27522.rs | 19 +++++++++++++++++++ src/test/ui/span/issue-27522.stderr | 11 +++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/ui/span/issue-27522.rs create mode 100644 src/test/ui/span/issue-27522.stderr 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 + From 6e69380bc4561fd8e5ea2129066c00dcc0af0433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 25 Dec 2016 13:00:06 -0800 Subject: [PATCH 38/53] Test for appropriate span on second custom derive --- src/test/ui/custom-derive/auxiliary/plugin.rs | 28 +++++++++++++++++++ src/test/ui/custom-derive/issue-36935.rs | 23 +++++++++++++++ src/test/ui/custom-derive/issue-36935.stderr | 8 ++++++ 3 files changed, 59 insertions(+) create mode 100644 src/test/ui/custom-derive/auxiliary/plugin.rs create mode 100644 src/test/ui/custom-derive/issue-36935.rs create mode 100644 src/test/ui/custom-derive/issue-36935.stderr 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 + From edcdec26136a15231de74d1a58ff9c2c2a7ce0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2017 18:18:47 -0800 Subject: [PATCH 39/53] Move check-ui to fulldeps so librustc is available As per @alexcrichton's comment in #38607. --- src/bootstrap/step.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index c3e10405eb532..e95731ec164c6 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", From 0b96d0737e5f80b8236c6e73969a37d0093e2f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 7 Jan 2017 23:31:23 -0800 Subject: [PATCH 40/53] trying to figure out why this test failes, might need help --- src/bootstrap/step.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index e95731ec164c6..ac10da10a1c42 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -1407,7 +1407,6 @@ 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("cfail"))); assert!(!plan.iter().any(|s| s.name.contains("cfail-full"))); From 3eb1db7d1ed9bf75d5080cccdf1ae5760572467e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2017 21:10:08 -0800 Subject: [PATCH 41/53] review comment --- src/bootstrap/step.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index ac10da10a1c42..a8a047a29285b 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -1374,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"))); @@ -1407,7 +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("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"))); From 8b359fa0c9a7a9ebccc19f60aa3409b12ffdd087 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 26 Dec 2016 15:19:27 -0800 Subject: [PATCH 42/53] std: Remove unused objects from compiler-builtins We don't actually use trampoline_setup.c and all the `*tf3` business seems related to f80/f128 business. Specifically this'll fix some warnings showing up during builds on OSX. --- src/libcompiler_builtins/build.rs | 6 ------ 1 file changed, 6 deletions(-) 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", From 74cddaf552d8fae7ec049883a33f6574b6943f47 Mon Sep 17 00:00:00 2001 From: York Xiang Date: Tue, 27 Dec 2016 11:25:01 +0800 Subject: [PATCH 43/53] Fix doc for `escape_debug` --- src/libstd_unicode/char.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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"); /// ``` From c7d7df2cd532bd137b0fac0c2bff26a4042f355e Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Wed, 28 Dec 2016 17:47:10 -0500 Subject: [PATCH 44/53] Replace uses of `#[unsafe_destructor_blind_to_params]` with `#[may_dangle]` CC #34761 --- src/liballoc/arc.rs | 3 +-- src/liballoc/lib.rs | 3 ++- src/liballoc/raw_vec.rs | 3 +-- src/liballoc/rc.rs | 3 +-- src/libarena/lib.rs | 7 +++---- src/libcollections/btree/map.rs | 3 +-- src/libcollections/lib.rs | 3 ++- src/libcollections/linked_list.rs | 3 +-- src/libcollections/vec.rs | 6 ++---- src/libcollections/vec_deque.rs | 3 +-- src/libstd/collections/hash/table.rs | 3 +-- src/libstd/lib.rs | 3 ++- src/libstd/sync/mutex.rs | 3 +-- src/libstd/sync/rwlock.rs | 3 +-- 14 files changed, 20 insertions(+), 29 deletions(-) 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 9ca9f93f3d33a..c67106cf57aaf 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -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/libarena/lib.rs b/src/libarena/lib.rs index 82ca989c9efb0..a3cfc15895eb7 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -30,10 +30,10 @@ #![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/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/lib.rs b/src/libcollections/lib.rs index ea2feac49f6ed..561d8860dc880 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -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..36dfc6b3e2940 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1786,8 +1786,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 +2055,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 d650360435aa0..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 { 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/lib.rs b/src/libstd/lib.rs index 87dce860278ca..08a5c0971b75d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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)] 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() } From e27f8d68ca251a6df3c72dbb021837154915da4f Mon Sep 17 00:00:00 2001 From: Christopher Date: Fri, 30 Dec 2016 09:38:53 -0600 Subject: [PATCH 45/53] Update signed formatting for numeric types in docs Sign formatting is no longer controlled by a `Signed` trait. Instead, `pad_integral` is used and implemented for numeric types by default. Fixes #38677 --- src/libcollections/fmt.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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. From a059a769c853d698ac020b184d8a9e2d8c936f48 Mon Sep 17 00:00:00 2001 From: Mina Naguib Date: Tue, 3 Jan 2017 14:52:14 -0500 Subject: [PATCH 46/53] Doc fix --- src/libstd/net/tcp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) => { From 6fbec03a2f49c78a6eb07d9f114b58cac6a7f94a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 3 Jan 2017 22:29:15 -0800 Subject: [PATCH 47/53] Add more docs for CoerceUnsized and Unsize --- src/doc/nomicon/coercions.md | 4 +++- src/libcore/marker.rs | 15 ++++++++++++++- src/libcore/ops.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) 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/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/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 { From dc29b67a04900bf00b6b74f18d200f6ddbee6628 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Thu, 5 Jan 2017 01:16:37 +0000 Subject: [PATCH 48/53] Fix typo in tuple docs --- src/libstd/primitive_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 /// From f63db437b40ea4057b61f6d74730655a673dcbbf Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 4 Jan 2017 22:47:23 -0500 Subject: [PATCH 49/53] Expand {Path,OsStr}::{to_str,to_string_lossy} doc examples. --- src/libstd/ffi/os_str.rs | 23 +++++++++++++++++++++++ src/libstd/path.rs | 13 +++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) 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/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() From 79f819846afa35e3c6925a51a84a73710d18634c Mon Sep 17 00:00:00 2001 From: F001 Date: Thu, 5 Jan 2017 12:25:26 +0800 Subject: [PATCH 50/53] Update usage of rustc Add proc_macro crate type --- src/librustc/session/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 \ From 5561d7b6f3c9047b27a2c8ea1cceee07cac7ef45 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 5 Jan 2017 10:53:29 -0500 Subject: [PATCH 51/53] ICH: Add some more test cases for trait impls. --- src/test/incremental/hashes/trait_impls.rs | 152 +++++++++++++++++++++ 1 file changed, 152 insertions(+) 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 } +} From ddc536c10acca754d78de84ffc9c714a8a2242b5 Mon Sep 17 00:00:00 2001 From: derekdreery Date: Fri, 6 Jan 2017 15:58:35 +0000 Subject: [PATCH 52/53] Update vec.rs Add a warning not to convert char* from c to Vec (I thought you could until I asked on irc) --- src/libcollections/vec.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 36dfc6b3e2940..b4f8fc4f98f9c 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 C pointer to a char array and a `size_t`. /// /// The ownership of `ptr` is effectively transferred to the /// `Vec` which may then deallocate, reallocate or change the From 27de1bb1f88d982ba7bb39408f21661bb4750035 Mon Sep 17 00:00:00 2001 From: derekdreery Date: Fri, 6 Jan 2017 18:17:18 +0000 Subject: [PATCH 53/53] Update vec.rs Changed language to stress char is the C meaning (u8) not unicode. --- src/libcollections/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index b4f8fc4f98f9c..27cf0268c99bb 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -371,7 +371,7 @@ impl Vec { /// /// Violating these may cause problems like corrupting the allocator's /// internal datastructures. For example it is **not** safe - /// to build a `Vec` from a C pointer to a char array and a `size_t`. + /// 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