diff --git a/configure b/configure index 133af075795c..5311bf4b064e 100755 --- a/configure +++ b/configure @@ -856,7 +856,7 @@ probe_need CFG_CMAKE cmake if [ -n "$CFG_ANTLR4" ] then CFG_ANTLR4_JAR="\"$(find /usr/ -name antlr-complete.jar 2>/dev/null | head -n 1)\"" - if [ "x" -eq "x$CFG_ANTLR4_JAR" ] + if [ "x" = "x$CFG_ANTLR4_JAR" ] then CFG_ANTLR4_JAR="\"$(find ~ -name antlr-complete.jar 2>/dev/null | head -n 1)\"" fi diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md index 397263c69733..140e27d19248 100644 --- a/src/doc/book/lifetimes.md +++ b/src/doc/book/lifetimes.md @@ -352,7 +352,7 @@ to it. Rust supports powerful local type inference in the bodies of functions but not in their item signatures. It's forbidden to allow reasoning about types based on the item signature alone. However, for ergonomic reasons, a very restricted secondary inference algorithm called -“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely to infer +“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision acts as a shorthand for writing an item signature, while not hiding away the actual types involved as full local inference would if applied to it. diff --git a/src/doc/reference.md b/src/doc/reference.md index 0596e476d5f6..4fbe51839676 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2474,18 +2474,19 @@ The currently implemented features of the reference compiler are: internally without imposing on callers (i.e. making them behave like function calls in terms of encapsulation). -* - `default_type_parameter_fallback` - Allows type parameter defaults to - influence type inference. -* - `stmt_expr_attributes` - Allows attributes on expressions. +* `default_type_parameter_fallback` - Allows type parameter defaults to + influence type inference. -* - `type_ascription` - Allows type ascription expressions `expr: Type`. +* `stmt_expr_attributes` - Allows attributes on expressions. -* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention - (e.g. `extern "vectorcall" func fn_();`) +* `type_ascription` - Allows type ascription expressions `expr: Type`. -* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention - (e.g. `extern "sysv64" func fn_();`) +* `abi_vectorcall` - Allows the usage of the vectorcall calling convention + (e.g. `extern "vectorcall" func fn_();`) + +* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention + (e.g. `extern "sysv64" func fn_();`) If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled diff --git a/src/etc/char_private.py b/src/etc/char_private.py index 3566d143529b..9d15f98e0670 100644 --- a/src/etc/char_private.py +++ b/src/etc/char_private.py @@ -11,11 +11,16 @@ # except according to those terms. # This script uses the following Unicode tables: -# - Categories.txt +# - UnicodeData.txt + +from collections import namedtuple +import csv import os import subprocess +NUM_CODEPOINTS=0x110000 + def to_ranges(iter): current = None for i in iter: @@ -28,10 +33,10 @@ def to_ranges(iter): if current is not None: yield tuple(current) -def get_escaped(dictionary): - for i in range(0x110000): - if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '): - yield i +def get_escaped(codepoints): + for c in codepoints: + if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '): + yield c.value def get_file(f): try: @@ -40,10 +45,41 @@ def get_file(f): subprocess.run(["curl", "-O", f], check=True) return open(os.path.basename(f)) -def main(): - file = get_file("http://www.unicode.org/notes/tn36/Categories.txt") +Codepoint = namedtuple('Codepoint', 'value class_') - dictionary = {int(line.split()[0], 16): line.split()[1] for line in file} +def get_codepoints(f): + r = csv.reader(f, delimiter=";") + prev_codepoint = 0 + class_first = None + for row in r: + codepoint = int(row[0], 16) + name = row[1] + class_ = row[2] + + if class_first is not None: + if not name.endswith("Last>"): + raise ValueError("Missing Last after First") + + for c in range(prev_codepoint + 1, codepoint): + yield Codepoint(c, class_first) + + class_first = None + if name.endswith("First>"): + class_first = class_ + + yield Codepoint(codepoint, class_) + prev_codepoint = codepoint + + if class_first != None: + raise ValueError("Missing Last after First") + + for c in range(prev_codepoint + 1, NUM_CODEPOINTS): + yield Codepoint(c, None) + +def main(): + file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt") + + codepoints = get_codepoints(file) CUTOFF=0x10000 singletons0 = [] @@ -52,7 +88,7 @@ def main(): normal1 = [] extra = [] - for a, b in to_ranges(get_escaped(dictionary)): + for a, b in to_ranges(get_escaped(codepoints)): if a > 2 * CUTOFF: extra.append((a, b - a)) elif a == b - 1: diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index cc56bbf4890a..14a0819d381b 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -767,6 +767,7 @@ fn test_iterator() { pos += 1; } assert_eq!(pos, v.len()); + assert_eq!(s.chars().count(), v.len()); } #[test] @@ -814,6 +815,14 @@ fn test_iterator_clone() { assert!(it.clone().zip(it).all(|(x,y)| x == y)); } +#[test] +fn test_iterator_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.chars(); + it.next(); + assert_eq!(it.last(), Some('m')); +} + #[test] fn test_bytesator() { let s = "ศไทย中华Việt Nam"; @@ -911,6 +920,14 @@ fn test_char_indices_revator() { assert_eq!(pos, p.len()); } +#[test] +fn test_char_indices_last() { + let s = "ศไทย中华Việt Nam"; + let mut it = s.char_indices(); + it.next(); + assert_eq!(it.last(), Some((27, 'm'))); +} + #[test] fn test_splitn_char_iterator() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; diff --git a/src/libcore/char_private.rs b/src/libcore/char_private.rs index 708e7cc15e7c..ddc473592a26 100644 --- a/src/libcore/char_private.rs +++ b/src/libcore/char_private.rs @@ -11,6 +11,8 @@ // NOTE: The following code was generated by "src/etc/char_private.py", // do not edit directly! +use slice::SliceExt; + fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool { for &s in singletons { if x == s { @@ -42,7 +44,16 @@ pub fn is_printable(x: char) -> bool { } else if x < 0x20000 { check(lower, SINGLETONS1, NORMAL1) } else { - if 0x20000 <= x && x < 0x2f800 { + if 0x2a6d7 <= x && x < 0x2a700 { + return false; + } + if 0x2b735 <= x && x < 0x2b740 { + return false; + } + if 0x2b81e <= x && x < 0x2b820 { + return false; + } + if 0x2cea2 <= x && x < 0x2f800 { return false; } if 0x2fa1e <= x && x < 0xe0100 { @@ -62,10 +73,13 @@ const SINGLETONS0: &'static [u16] = &[ 0x38b, 0x38d, 0x3a2, + 0x530, 0x557, 0x558, 0x560, 0x588, + 0x58b, + 0x58c, 0x590, 0x61c, 0x61d, @@ -79,10 +93,8 @@ const SINGLETONS0: &'static [u16] = &[ 0x83f, 0x85c, 0x85d, - 0x8a1, - 0x8ff, - 0x978, - 0x980, + 0x8b5, + 0x8e2, 0x984, 0x98d, 0x98e, @@ -154,14 +166,11 @@ const SINGLETONS0: &'static [u16] = &[ 0xc0d, 0xc11, 0xc29, - 0xc34, 0xc45, 0xc49, 0xc57, 0xc64, 0xc65, - 0xc80, - 0xc81, 0xc84, 0xc8d, 0xc91, @@ -193,6 +202,8 @@ const SINGLETONS0: &'static [u16] = &[ 0xdbf, 0xdd5, 0xdd7, + 0xdf0, + 0xdf1, 0xe83, 0xe85, 0xe86, @@ -245,6 +256,10 @@ const SINGLETONS0: &'static [u16] = &[ 0x1317, 0x135b, 0x135c, + 0x13f6, + 0x13f7, + 0x13fe, + 0x13ff, 0x1680, 0x170d, 0x176d, @@ -253,6 +268,7 @@ const SINGLETONS0: &'static [u16] = &[ 0x17df, 0x180e, 0x180f, + 0x191f, 0x196e, 0x196f, 0x1a1c, @@ -260,6 +276,9 @@ const SINGLETONS0: &'static [u16] = &[ 0x1a5f, 0x1a7d, 0x1a7e, + 0x1aae, + 0x1aaf, + 0x1cf7, 0x1f16, 0x1f17, 0x1f1e, @@ -285,7 +304,12 @@ const SINGLETONS0: &'static [u16] = &[ 0x2072, 0x2073, 0x208f, - 0x2700, + 0x23ff, + 0x2b74, + 0x2b75, + 0x2b96, + 0x2b97, + 0x2bc9, 0x2c2f, 0x2c5f, 0x2d26, @@ -306,8 +330,11 @@ const SINGLETONS0: &'static [u16] = &[ 0x318f, 0x321f, 0x32ff, - 0xa78f, + 0xa7af, + 0xa8fe, + 0xa8ff, 0xa9ce, + 0xa9ff, 0xaa4e, 0xaa4f, 0xaa5a, @@ -317,6 +344,7 @@ const SINGLETONS0: &'static [u16] = &[ 0xab0f, 0xab10, 0xab27, + 0xab2f, 0xabee, 0xabef, 0xfa6e, @@ -350,7 +378,7 @@ const SINGLETONS1: &'static [u16] = &[ 0x3e, 0x4e, 0x4f, - 0x31f, + 0x18f, 0x39e, 0x49e, 0x49f, @@ -361,6 +389,9 @@ const SINGLETONS1: &'static [u16] = &[ 0x83d, 0x83e, 0x856, + 0x8f3, + 0x9d0, + 0x9d1, 0xa04, 0xa14, 0xa18, @@ -368,6 +399,49 @@ const SINGLETONS1: &'static [u16] = &[ 0xb57, 0x10bd, 0x1135, + 0x11ce, + 0x11cf, + 0x11e0, + 0x1212, + 0x1287, + 0x1289, + 0x128e, + 0x129e, + 0x1304, + 0x130d, + 0x130e, + 0x1311, + 0x1312, + 0x1329, + 0x1331, + 0x1334, + 0x133a, + 0x133b, + 0x1345, + 0x1346, + 0x1349, + 0x134a, + 0x134e, + 0x134f, + 0x1364, + 0x1365, + 0x145a, + 0x145c, + 0x15b6, + 0x15b7, + 0x1c09, + 0x1c37, + 0x1c90, + 0x1c91, + 0x1ca8, + 0x246f, + 0x6a5f, + 0x6aee, + 0x6aef, + 0x6b5a, + 0x6b62, + 0xbc9a, + 0xbc9b, 0xd127, 0xd128, 0xd455, @@ -395,6 +469,14 @@ const SINGLETONS1: &'static [u16] = &[ 0xd6a7, 0xd7cc, 0xd7cd, + 0xdaa0, + 0xe007, + 0xe019, + 0xe01a, + 0xe022, + 0xe025, + 0xe8c5, + 0xe8c6, 0xee04, 0xee20, 0xee23, @@ -429,31 +511,25 @@ const SINGLETONS1: &'static [u16] = &[ 0xeeaa, 0xf0af, 0xf0b0, - 0xf0bf, 0xf0c0, 0xf0d0, 0xf12f, - 0xf336, - 0xf3c5, - 0xf43f, - 0xf441, - 0xf4f8, - 0xf53e, - 0xf53f, + 0xf91f, + 0xf931, + 0xf932, + 0xf93f, ]; const NORMAL0: &'static [u16] = &[ 0x0, 0x20, 0x7f, 0x22, - 0x37f, 0x5, - 0x528, 0x9, - 0x58b, 0x4, + 0x380, 0x4, 0x5c8, 0x8, 0x5eb, 0x5, 0x5f5, 0x11, 0x7b2, 0xe, 0x7fb, 0x5, 0x85f, 0x41, - 0x8ad, 0x37, + 0x8be, 0x16, 0x9b3, 0x3, 0x9cf, 0x8, 0x9d8, 0x4, @@ -465,7 +541,8 @@ const NORMAL0: &'static [u16] = &[ 0xa5f, 0x7, 0xa76, 0xb, 0xad1, 0xf, - 0xaf2, 0xf, + 0xaf2, 0x7, + 0xafa, 0x7, 0xb4e, 0x8, 0xb58, 0x4, 0xb78, 0xa, @@ -478,21 +555,19 @@ const NORMAL0: &'static [u16] = &[ 0xbc3, 0x3, 0xbd1, 0x6, 0xbd8, 0xe, - 0xbfb, 0x6, + 0xbfb, 0x5, 0xc3a, 0x3, 0xc4e, 0x7, - 0xc5a, 0x6, + 0xc5b, 0x5, 0xc70, 0x8, 0xcce, 0x7, 0xcd7, 0x7, - 0xcf3, 0xf, - 0xd4f, 0x8, - 0xd58, 0x8, - 0xd76, 0x3, + 0xcf3, 0xe, + 0xd50, 0x4, 0xd97, 0x3, 0xdc7, 0x3, 0xdcb, 0x4, - 0xde0, 0x12, + 0xde0, 0x6, 0xdf5, 0xc, 0xe3b, 0x4, 0xe5c, 0x25, @@ -503,9 +578,8 @@ const NORMAL0: &'static [u16] = &[ 0x10c8, 0x5, 0x137d, 0x3, 0x139a, 0x6, - 0x13f5, 0xb, 0x169d, 0x3, - 0x16f1, 0xf, + 0x16f9, 0x7, 0x1715, 0xb, 0x1737, 0x9, 0x1754, 0xc, @@ -516,7 +590,6 @@ const NORMAL0: &'static [u16] = &[ 0x1878, 0x8, 0x18ab, 0x5, 0x18f6, 0xa, - 0x191d, 0x3, 0x192c, 0x4, 0x193c, 0x4, 0x1941, 0x3, @@ -526,34 +599,34 @@ const NORMAL0: &'static [u16] = &[ 0x19db, 0x3, 0x1a8a, 0x6, 0x1a9a, 0x6, - 0x1aae, 0x52, + 0x1abf, 0x41, 0x1b4c, 0x4, 0x1b7d, 0x3, 0x1bf4, 0x8, 0x1c38, 0x3, 0x1c4a, 0x3, - 0x1c80, 0x40, + 0x1c89, 0x37, 0x1cc8, 0x8, - 0x1cf7, 0x9, - 0x1de7, 0x15, + 0x1cfa, 0x6, + 0x1df6, 0x5, 0x1fff, 0x11, 0x2028, 0x8, 0x205f, 0x11, 0x209d, 0x3, - 0x20ba, 0x16, + 0x20bf, 0x11, 0x20f1, 0xf, - 0x218a, 0x6, - 0x23f4, 0xc, + 0x218c, 0x4, 0x2427, 0x19, 0x244b, 0x15, - 0x2b4d, 0x3, - 0x2b5a, 0xa6, + 0x2bba, 0x3, + 0x2bd2, 0x1a, + 0x2bf0, 0x10, 0x2cf4, 0x5, 0x2d28, 0x5, 0x2d68, 0x7, 0x2d71, 0xe, 0x2d97, 0x9, - 0x2e3c, 0x44, + 0x2e45, 0x3b, 0x2ef4, 0xc, 0x2fd6, 0x1a, 0x2ffc, 0x5, @@ -561,32 +634,28 @@ const NORMAL0: &'static [u16] = &[ 0x312e, 0x3, 0x31bb, 0x5, 0x31e4, 0xc, - 0x3400, 0x19c0, - 0x4e00, 0x5200, + 0x4db6, 0xa, + 0x9fd6, 0x2a, 0xa48d, 0x3, 0xa4c7, 0x9, 0xa62c, 0x14, - 0xa698, 0x7, 0xa6f8, 0x8, - 0xa794, 0xc, - 0xa7ab, 0x4d, + 0xa7b8, 0x3f, 0xa82c, 0x4, 0xa83a, 0x6, 0xa878, 0x8, - 0xa8c5, 0x9, + 0xa8c6, 0x8, 0xa8da, 0x6, - 0xa8fc, 0x4, 0xa954, 0xb, 0xa97d, 0x3, 0xa9da, 0x4, - 0xa9e0, 0x20, 0xaa37, 0x9, - 0xaa7c, 0x4, 0xaac3, 0x18, 0xaaf7, 0xa, 0xab17, 0x9, - 0xab2f, 0x91, - 0xabfa, 0x2bb6, + 0xab66, 0xa, + 0xabfa, 0x6, + 0xd7a4, 0xc, 0xd7c7, 0x4, 0xd7fc, 0x2104, 0xfada, 0x26, @@ -596,7 +665,6 @@ const NORMAL0: &'static [u16] = &[ 0xfd40, 0x10, 0xfdc8, 0x28, 0xfe1a, 0x6, - 0xfe27, 0x9, 0xfe6c, 0x4, 0xfefd, 0x4, 0xffbf, 0x3, @@ -608,61 +676,123 @@ const NORMAL1: &'static [u16] = &[ 0xfb, 0x5, 0x103, 0x4, 0x134, 0x3, - 0x18b, 0x5, - 0x19c, 0x34, + 0x19c, 0x4, + 0x1a1, 0x2f, 0x1fe, 0x82, 0x29d, 0x3, - 0x2d1, 0x2f, + 0x2d1, 0xf, + 0x2fc, 0x4, 0x324, 0xc, - 0x34b, 0x35, + 0x34b, 0x5, + 0x37b, 0x5, 0x3c4, 0x4, 0x3d6, 0x2a, - 0x4aa, 0x356, + 0x4aa, 0x6, + 0x4d4, 0x4, + 0x4fc, 0x4, + 0x528, 0x8, + 0x564, 0xb, + 0x570, 0x90, + 0x737, 0x9, + 0x756, 0xa, + 0x768, 0x98, 0x839, 0x3, - 0x860, 0xa0, + 0x89f, 0x8, + 0x8b0, 0x30, + 0x8f6, 0x5, 0x91c, 0x3, 0x93a, 0x5, 0x940, 0x40, - 0x9b8, 0x6, - 0x9c0, 0x40, + 0x9b8, 0x4, 0xa07, 0x5, 0xa34, 0x4, 0xa3b, 0x4, 0xa48, 0x8, 0xa59, 0x7, - 0xa80, 0x80, + 0xaa0, 0x20, + 0xae7, 0x4, + 0xaf7, 0x9, 0xb36, 0x3, 0xb73, 0x5, - 0xb80, 0x80, - 0xc49, 0x217, + 0xb92, 0x7, + 0xb9d, 0xc, + 0xbb0, 0x50, + 0xc49, 0x37, + 0xcb3, 0xd, + 0xcf3, 0x7, + 0xd00, 0x160, 0xe7f, 0x181, 0x104e, 0x4, - 0x1070, 0x10, + 0x1070, 0xf, 0x10c2, 0xe, 0x10e9, 0x7, 0x10fa, 0x6, - 0x1144, 0x3c, - 0x11c9, 0x7, - 0x11da, 0x4a6, + 0x1144, 0xc, + 0x1177, 0x9, + 0x11f5, 0xb, + 0x123f, 0x41, + 0x12aa, 0x6, + 0x12eb, 0x5, + 0x12fa, 0x6, + 0x1351, 0x6, + 0x1358, 0x5, + 0x136d, 0x3, + 0x1375, 0x8b, + 0x145e, 0x22, + 0x14c8, 0x8, + 0x14da, 0xa6, + 0x15de, 0x22, + 0x1645, 0xb, + 0x165a, 0x6, + 0x166d, 0x13, 0x16b8, 0x8, - 0x16ca, 0x936, - 0x236f, 0x91, - 0x2463, 0xd, - 0x2474, 0xb8c, - 0x342f, 0x33d1, - 0x6a39, 0x4c7, + 0x16ca, 0x36, + 0x171a, 0x3, + 0x172c, 0x4, + 0x1740, 0x160, + 0x18f3, 0xc, + 0x1900, 0x1c0, + 0x1af9, 0x107, + 0x1c46, 0xa, + 0x1c6d, 0x3, + 0x1cb7, 0x349, + 0x239a, 0x66, + 0x2475, 0xb, + 0x2544, 0xabc, + 0x342f, 0xfd1, + 0x4647, 0x21b9, + 0x6a39, 0x7, + 0x6a6a, 0x4, + 0x6a70, 0x60, + 0x6af6, 0xa, + 0x6b46, 0xa, + 0x6b78, 0x5, + 0x6b90, 0x370, 0x6f45, 0xb, 0x6f7f, 0x10, - 0x6fa0, 0x4060, - 0xb002, 0x1ffe, + 0x6fa0, 0x40, + 0x6fe1, 0x1f, + 0x87ed, 0x13, + 0x8af3, 0x250d, + 0xb002, 0xbfe, + 0xbc6b, 0x5, + 0xbc7d, 0x3, + 0xbc89, 0x7, + 0xbca0, 0x1360, 0xd0f6, 0xa, 0xd173, 0x8, - 0xd1de, 0x22, + 0xd1e9, 0x17, 0xd246, 0xba, 0xd357, 0x9, 0xd372, 0x8e, 0xd547, 0x3, - 0xd800, 0x1600, + 0xda8c, 0xf, + 0xdab0, 0x550, + 0xe02b, 0x7d5, + 0xe8d7, 0x29, + 0xe94b, 0x5, + 0xe95a, 0x4, + 0xe960, 0x4a0, 0xee3c, 0x6, 0xee43, 0x4, 0xee9c, 0x5, @@ -670,24 +800,27 @@ const NORMAL1: &'static [u16] = &[ 0xeef2, 0x10e, 0xf02c, 0x4, 0xf094, 0xc, - 0xf0e0, 0x20, - 0xf10b, 0x5, + 0xf0f6, 0xa, + 0xf10d, 0x3, 0xf16c, 0x4, - 0xf19b, 0x4b, + 0xf1ad, 0x39, 0xf203, 0xd, - 0xf23b, 0x5, + 0xf23c, 0x4, 0xf249, 0x7, 0xf252, 0xae, - 0xf321, 0xf, - 0xf37d, 0x3, - 0xf394, 0xc, - 0xf3cb, 0x15, - 0xf3f1, 0xf, - 0xf4fd, 0x3, - 0xf544, 0xc, - 0xf568, 0x93, - 0xf641, 0x4, - 0xf650, 0x30, - 0xf6c6, 0x3a, - 0xf774, 0x88c, + 0xf6d3, 0xd, + 0xf6ed, 0x3, + 0xf6f7, 0x9, + 0xf774, 0xc, + 0xf7d5, 0x2b, + 0xf80c, 0x4, + 0xf848, 0x8, + 0xf85a, 0x6, + 0xf888, 0x8, + 0xf8ae, 0x62, + 0xf928, 0x8, + 0xf94c, 0x4, + 0xf95f, 0x21, + 0xf992, 0x2e, + 0xf9c1, 0x63f, ]; diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index cd2e0cb11d35..02a2e370547e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1273,54 +1273,68 @@ unsafe impl TrustedLen for Enumerate #[stable(feature = "rust1", since = "1.0.0")] pub struct Peekable { iter: I, - peeked: Option, + /// Remember a peeked value, even if it was None. + peeked: Option>, } +// Peekable must remember if a None has been seen in the `.peek()` method. +// It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the +// underlying iterator at most once. This does not by itself make the iterator +// fused. #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Peekable { type Item = I::Item; #[inline] fn next(&mut self) -> Option { - match self.peeked { - Some(_) => self.peeked.take(), + match self.peeked.take() { + Some(v) => v, None => self.iter.next(), } } #[inline] #[rustc_inherit_overflow_checks] - fn count(self) -> usize { - (if self.peeked.is_some() { 1 } else { 0 }) + self.iter.count() + fn count(mut self) -> usize { + match self.peeked.take() { + Some(None) => 0, + Some(Some(_)) => 1 + self.iter.count(), + None => self.iter.count(), + } } #[inline] fn nth(&mut self, n: usize) -> Option { - match self.peeked { - Some(_) if n == 0 => self.peeked.take(), - Some(_) => { - self.peeked = None; - self.iter.nth(n-1) - }, - None => self.iter.nth(n) + match self.peeked.take() { + // the .take() below is just to avoid "move into pattern guard" + Some(ref mut v) if n == 0 => v.take(), + Some(None) => None, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), } } #[inline] - fn last(self) -> Option { - self.iter.last().or(self.peeked) + fn last(mut self) -> Option { + let peek_opt = match self.peeked.take() { + Some(None) => return None, + Some(v) => v, + None => None, + }; + self.iter.last().or(peek_opt) } #[inline] fn size_hint(&self) -> (usize, Option) { + let peek_len = match self.peeked { + Some(None) => return (0, Some(0)), + Some(Some(_)) => 1, + None => 0, + }; let (lo, hi) = self.iter.size_hint(); - if self.peeked.is_some() { - let lo = lo.saturating_add(1); - let hi = hi.and_then(|x| x.checked_add(1)); - (lo, hi) - } else { - (lo, hi) - } + let lo = lo.saturating_add(peek_len); + let hi = hi.and_then(|x| x.checked_add(peek_len)); + (lo, hi) } } @@ -1372,9 +1386,13 @@ impl Peekable { #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&mut self) -> Option<&I::Item> { if self.peeked.is_none() { - self.peeked = self.iter.next(); + self.peeked = Some(self.iter.next()); + } + match self.peeked { + Some(Some(ref value)) => Some(value), + Some(None) => None, + _ => unreachable!(), } - self.peeked.as_ref() } } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 196750254af3..b4cd52e59f65 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -424,6 +424,17 @@ impl<'a> Iterator for Chars<'a> { }) } + #[inline] + fn count(self) -> usize { + // length in `char` is equal to the number of non-continuation bytes + let bytes_len = self.iter.len(); + let mut cont_bytes = 0; + for &byte in self.iter { + cont_bytes += utf8_is_cont_byte(byte) as usize; + } + bytes_len - cont_bytes + } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.iter.len(); @@ -432,6 +443,12 @@ impl<'a> Iterator for Chars<'a> { // `isize::MAX` (that's well below `usize::MAX`). ((len + 3) / 4, Some(len)) } + + #[inline] + fn last(mut self) -> Option { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -501,10 +518,21 @@ impl<'a> Iterator for CharIndices<'a> { } } + #[inline] + fn count(self) -> usize { + self.iter.count() + } + #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + + #[inline] + fn last(mut self) -> Option<(usize, char)> { + // No need to go through the entire string. + self.next_back() + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs index 7da0b6902f27..b4088ffbf89a 100644 --- a/src/libcoretest/char.rs +++ b/src/libcoretest/char.rs @@ -162,6 +162,8 @@ fn test_escape_debug() { assert_eq!(s, "~"); let s = string('é'); assert_eq!(s, "é"); + let s = string('文'); + assert_eq!(s, "文"); let s = string('\x00'); assert_eq!(s, "\\u{0}"); let s = string('\x1f'); diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 58b6444ef88c..274539dfa669 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -274,6 +274,74 @@ fn test_iterator_peekable_last() { let mut it = ys.iter().peekable(); assert_eq!(it.peek(), Some(&&0)); assert_eq!(it.last(), Some(&0)); + + let mut it = ys.iter().peekable(); + assert_eq!(it.next(), Some(&0)); + assert_eq!(it.peek(), None); + assert_eq!(it.last(), None); +} + +/// This is an iterator that follows the Iterator contract, +/// but it is not fused. After having returned None once, it will start +/// producing elements if .next() is called again. +pub struct CycleIter<'a, T: 'a> { + index: usize, + data: &'a [T], +} + +pub fn cycle(data: &[T]) -> CycleIter { + CycleIter { + index: 0, + data: data, + } +} + +impl<'a, T> Iterator for CycleIter<'a, T> { + type Item = &'a T; + fn next(&mut self) -> Option { + let elt = self.data.get(self.index); + self.index += 1; + self.index %= 1 + self.data.len(); + elt + } +} + +#[test] +fn test_iterator_peekable_remember_peek_none_1() { + // Check that the loop using .peek() terminates + let data = [1, 2, 3]; + let mut iter = cycle(&data).peekable(); + + let mut n = 0; + while let Some(_) = iter.next() { + let is_the_last = iter.peek().is_none(); + assert_eq!(is_the_last, n == data.len() - 1); + n += 1; + if n > data.len() { break; } + } + assert_eq!(n, data.len()); +} + +#[test] +fn test_iterator_peekable_remember_peek_none_2() { + let data = [0]; + let mut iter = cycle(&data).peekable(); + iter.next(); + assert_eq!(iter.peek(), None); + assert_eq!(iter.last(), None); +} + +#[test] +fn test_iterator_peekable_remember_peek_none_3() { + let data = [0]; + let mut iter = cycle(&data).peekable(); + iter.peek(); + assert_eq!(iter.nth(0), Some(&0)); + + let mut iter = cycle(&data).peekable(); + iter.next(); + assert_eq!(iter.peek(), None); + assert_eq!(iter.nth(0), None); } #[test] diff --git a/src/libcoretest/num/flt2dec/strategy/dragon.rs b/src/libcoretest/num/flt2dec/strategy/dragon.rs index 79dcca7671a2..08c2cd0a7326 100644 --- a/src/libcoretest/num/flt2dec/strategy/dragon.rs +++ b/src/libcoretest/num/flt2dec/strategy/dragon.rs @@ -11,7 +11,6 @@ use std::prelude::v1::*; use std::{i16, f64}; use super::super::*; -use core::num::flt2dec::*; use core::num::bignum::Big32x40 as Big; use core::num::flt2dec::strategy::dragon::*; diff --git a/src/libcoretest/num/flt2dec/strategy/grisu.rs b/src/libcoretest/num/flt2dec/strategy/grisu.rs index 2d4afceda191..311bd252353c 100644 --- a/src/libcoretest/num/flt2dec/strategy/grisu.rs +++ b/src/libcoretest/num/flt2dec/strategy/grisu.rs @@ -10,7 +10,6 @@ use std::{i16, f64}; use super::super::*; -use core::num::flt2dec::*; use core::num::flt2dec::strategy::grisu::*; #[test] diff --git a/src/libproc_macro_plugin/qquote.rs b/src/libproc_macro_plugin/qquote.rs index e5a3abc2ea98..1ae906e0aa4e 100644 --- a/src/libproc_macro_plugin/qquote.rs +++ b/src/libproc_macro_plugin/qquote.rs @@ -34,8 +34,9 @@ use syntax::codemap::Span; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::proc_macro_shim::build_block_emitter; -use syntax::parse::token::{self, Token, gensym_ident, str_to_ident}; +use syntax::parse::token::{self, Token}; use syntax::print::pprust; +use syntax::symbol::Symbol; use syntax::tokenstream::{TokenTree, TokenStream}; // ____________________________________________________________________________________________ @@ -124,7 +125,7 @@ fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindi } // produce an error or something first let exp = vec![exp.unwrap().to_owned()]; debug!("RHS: {:?}", exp.clone()); - let new_id = gensym_ident("tmp"); + let new_id = Ident::with_empty_ctxt(Symbol::gensym("tmp")); debug!("RHS TS: {:?}", TokenStream::from_tts(exp.clone())); debug!("RHS TS TT: {:?}", TokenStream::from_tts(exp.clone()).to_vec()); bindings.push((new_id, TokenStream::from_tts(exp))); @@ -179,7 +180,7 @@ fn unravel_concats(tss: Vec) -> TokenStream { }; while let Some(ts) = pushes.pop() { - output = build_fn_call(str_to_ident("concat"), + output = build_fn_call(Ident::from_str("concat"), concat(concat(ts, from_tokens(vec![Token::Comma])), output)); @@ -209,18 +210,19 @@ fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec) -> (Bindings, T // FIXME handle sequence repetition tokens QTT::QDL(qdl) => { debug!(" QDL: {:?} ", qdl.tts); - let new_id = gensym_ident("qdl_tmp"); + let new_id = Ident::with_empty_ctxt(Symbol::gensym("qdl_tmp")); let mut cct_rec = convert_complex_tts(cx, qdl.tts); bindings.append(&mut cct_rec.0); bindings.push((new_id, cct_rec.1)); let sep = build_delim_tok(qdl.delim); - pushes.push(build_mod_call(vec![str_to_ident("proc_macro_tokens"), - str_to_ident("build"), - str_to_ident("build_delimited")], - concat(from_tokens(vec![Token::Ident(new_id)]), - concat(lex(","), sep)))); + pushes.push(build_mod_call( + vec![Ident::from_str("proc_macro_tokens"), + Ident::from_str("build"), + Ident::from_str("build_delimited")], + concat(from_tokens(vec![Token::Ident(new_id)]), concat(lex(","), sep)), + )); } QTT::QIdent(t) => { pushes.push(TokenStream::from_tts(vec![t])); @@ -250,13 +252,13 @@ fn unravel(binds: Bindings) -> TokenStream { /// Checks if the Ident is `unquote`. fn is_unquote(id: Ident) -> bool { - let qq = str_to_ident("unquote"); + let qq = Ident::from_str("unquote"); id.name == qq.name // We disregard context; unquote is _reserved_ } /// Checks if the Ident is `quote`. fn is_qquote(id: Ident) -> bool { - let qq = str_to_ident("qquote"); + let qq = Ident::from_str("qquote"); id.name == qq.name // We disregard context; qquote is _reserved_ } @@ -266,7 +268,8 @@ mod int_build { use syntax::ast::{self, Ident}; use syntax::codemap::{DUMMY_SP}; - use syntax::parse::token::{self, Token, keywords, str_to_ident}; + use syntax::parse::token::{self, Token, Lit}; + use syntax::symbol::keywords; use syntax::tokenstream::{TokenTree, TokenStream}; // ____________________________________________________________________________________________ @@ -277,19 +280,19 @@ mod int_build { build_paren_delimited(build_vec(build_token_tt(t)))) } - pub fn emit_lit(l: token::Lit, n: Option) -> TokenStream { + pub fn emit_lit(l: Lit, n: Option) -> TokenStream { let suf = match n { - Some(n) => format!("Some(ast::Name({}))", n.0), + Some(n) => format!("Some(ast::Name({}))", n.as_u32()), None => "None".to_string(), }; let lit = match l { - token::Lit::Byte(n) => format!("Lit::Byte(token::intern(\"{}\"))", n.to_string()), - token::Lit::Char(n) => format!("Lit::Char(token::intern(\"{}\"))", n.to_string()), - token::Lit::Integer(n) => format!("Lit::Integer(token::intern(\"{}\"))", n.to_string()), - token::Lit::Float(n) => format!("Lit::Float(token::intern(\"{}\"))", n.to_string()), - token::Lit::Str_(n) => format!("Lit::Str_(token::intern(\"{}\"))", n.to_string()), - token::Lit::ByteStr(n) => format!("Lit::ByteStr(token::intern(\"{}\"))", n.to_string()), + Lit::Byte(n) => format!("Lit::Byte(Symbol::intern(\"{}\"))", n.to_string()), + Lit::Char(n) => format!("Lit::Char(Symbol::intern(\"{}\"))", n.to_string()), + Lit::Float(n) => format!("Lit::Float(Symbol::intern(\"{}\"))", n.to_string()), + Lit::Str_(n) => format!("Lit::Str_(Symbol::intern(\"{}\"))", n.to_string()), + Lit::Integer(n) => format!("Lit::Integer(Symbol::intern(\"{}\"))", n.to_string()), + Lit::ByteStr(n) => format!("Lit::ByteStr(Symbol::intern(\"{}\"))", n.to_string()), _ => panic!("Unsupported literal"), }; @@ -388,9 +391,10 @@ mod int_build { Token::Underscore => lex("_"), Token::Literal(lit, sfx) => emit_lit(lit, sfx), // fix ident expansion information... somehow - Token::Ident(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))", ident.name)), - Token::Lifetime(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))", - ident.name)), + Token::Ident(ident) => + lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)), + Token::Lifetime(ident) => + lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)), _ => panic!("Unhandled case!"), } } @@ -408,7 +412,7 @@ mod int_build { /// Takes `input` and returns `vec![input]`. pub fn build_vec(ts: TokenStream) -> TokenStream { - build_mac_call(str_to_ident("vec"), ts) + build_mac_call(Ident::from_str("vec"), ts) // tts.clone().to_owned() } diff --git a/src/libproc_macro_tokens/build.rs b/src/libproc_macro_tokens/build.rs index 7b7590b863b7..d39aba0aa778 100644 --- a/src/libproc_macro_tokens/build.rs +++ b/src/libproc_macro_tokens/build.rs @@ -13,7 +13,8 @@ extern crate syntax_pos; use syntax::ast::Ident; use syntax::codemap::DUMMY_SP; -use syntax::parse::token::{self, Token, keywords, str_to_ident}; +use syntax::parse::token::{self, Token}; +use syntax::symbol::keywords; use syntax::tokenstream::{self, TokenTree, TokenStream}; use std::rc::Rc; @@ -43,13 +44,13 @@ pub fn ident_eq(tident: &TokenTree, id: Ident) -> bool { /// Convert a `&str` into a Token. pub fn str_to_token_ident(s: &str) -> Token { - Token::Ident(str_to_ident(s)) + Token::Ident(Ident::from_str(s)) } /// Converts a keyword (from `syntax::parse::token::keywords`) into a Token that /// corresponds to it. pub fn keyword_to_token_ident(kw: keywords::Keyword) -> Token { - Token::Ident(str_to_ident(&kw.name().as_str()[..])) + Token::Ident(Ident::from_str(&kw.name().as_str()[..])) } // ____________________________________________________________________________________________ diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 22c7d14be29d..c399623462b5 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -223,7 +223,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { expr_exit } - hir::ExprLoop(ref body, _) => { + hir::ExprLoop(ref body, _, _) => { // // [pred] // | @@ -282,9 +282,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_unreachable_node() } - hir::ExprBreak(label) => { + hir::ExprBreak(label, ref opt_expr) => { + let v = self.opt_expr(opt_expr, pred); let loop_scope = self.find_scope(expr, label.map(|l| l.node)); - let b = self.add_ast_node(expr.id, &[pred]); + let b = self.add_ast_node(expr.id, &[v]); self.add_exiting_edge(expr, b, loop_scope, loop_scope.break_index); self.add_unreachable_node() @@ -299,15 +300,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprArray(ref elems) => { - self.straightline(expr, pred, elems.iter().map(|e| &**e)) + self.straightline(expr, pred, elems.iter().map(|e| &*e)) } hir::ExprCall(ref func, ref args) => { - self.call(expr, pred, &func, args.iter().map(|e| &**e)) + self.call(expr, pred, &func, args.iter().map(|e| &*e)) } hir::ExprMethodCall(.., ref args) => { - self.call(expr, pred, &args[0], args[1..].iter().map(|e| &**e)) + self.call(expr, pred, &args[0], args[1..].iter().map(|e| &*e)) } hir::ExprIndex(ref l, ref r) | @@ -320,7 +321,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprTup(ref exprs) => { - self.straightline(expr, pred, exprs.iter().map(|e| &**e)) + self.straightline(expr, pred, exprs.iter().map(|e| &*e)) } hir::ExprStruct(_, ref fields, ref base) => { @@ -353,8 +354,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprInlineAsm(_, ref outputs, ref inputs) => { - let post_outputs = self.exprs(outputs.iter().map(|e| &**e), pred); - let post_inputs = self.exprs(inputs.iter().map(|e| &**e), post_outputs); + let post_outputs = self.exprs(outputs.iter().map(|e| &*e), pred); + let post_inputs = self.exprs(inputs.iter().map(|e| &*e), post_outputs); self.add_ast_node(expr.id, &[post_inputs]) } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 8ba52cdb64f5..abc35634d15f 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -64,7 +64,7 @@ impl<'a> CheckAttrVisitor<'a> { None => continue, }; - let (message, label) = match &*name { + let (message, label) = match &*name.as_str() { "C" => { conflicting_reprs += 1; if target != Target::Struct && @@ -120,7 +120,7 @@ impl<'a> CheckAttrVisitor<'a> { } fn check_attribute(&self, attr: &ast::Attribute, target: Target) { - let name: &str = &attr.name(); + let name: &str = &attr.name().as_str(); match name { "inline" => self.check_inline(attr, target), "repr" => self.check_repr(attr, target), diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 4cfa889ec561..7dd88e36dd1f 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -882,7 +882,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_block(block); walk_opt_sp_name(visitor, opt_sp_name); } - ExprLoop(ref block, ref opt_sp_name) => { + ExprLoop(ref block, ref opt_sp_name, _) => { visitor.visit_block(block); walk_opt_sp_name(visitor, opt_sp_name); } @@ -923,7 +923,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { } visitor.visit_path(path, expression.id) } - ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => { + ExprBreak(ref opt_sp_name, ref opt_expr) => { + walk_opt_sp_name(visitor, opt_sp_name); + walk_list!(visitor, visit_expr, opt_expr); + } + ExprAgain(ref opt_sp_name) => { walk_opt_sp_name(visitor, opt_sp_name); } ExprRet(ref optional_expression) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 05c4ae521803..5af7c18e1a10 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -53,8 +53,8 @@ use syntax::ast::*; use syntax::errors; use syntax::ptr::P; use syntax::codemap::{respan, Spanned}; -use syntax::parse::token; use syntax::std_inject; +use syntax::symbol::{Symbol, keywords}; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -149,7 +149,7 @@ impl<'a> LoweringContext<'a> { } fn str_to_ident(&self, s: &'static str) -> Name { - token::gensym(s) + Symbol::gensym(s) } fn with_parent_def(&mut self, parent_id: NodeId, f: F) -> T @@ -210,8 +210,8 @@ impl<'a> LoweringContext<'a> { hir::Arm { attrs: self.lower_attrs(&arm.attrs), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), - guard: arm.guard.as_ref().map(|ref x| self.lower_expr(x)), - body: self.lower_expr(&arm.body), + guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))), + body: P(self.lower_expr(&arm.body)), } } @@ -262,10 +262,10 @@ impl<'a> LoweringContext<'a> { hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds)) } TyKind::Array(ref ty, ref e) => { - hir::TyArray(self.lower_ty(ty), self.lower_expr(e)) + hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e))) } TyKind::Typeof(ref expr) => { - hir::TyTypeof(self.lower_expr(expr)) + hir::TyTypeof(P(self.lower_expr(expr))) } TyKind::PolyTraitRef(ref bounds) => { hir::TyPolyTraitRef(self.lower_bounds(bounds)) @@ -292,7 +292,7 @@ impl<'a> LoweringContext<'a> { name: v.node.name.name, attrs: self.lower_attrs(&v.node.attrs), data: self.lower_variant_data(&v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_expr(e)), + disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))), }, span: v.span, } @@ -350,7 +350,7 @@ impl<'a> LoweringContext<'a> { id: l.id, ty: l.ty.as_ref().map(|t| self.lower_ty(t)), pat: self.lower_pat(&l.pat), - init: l.init.as_ref().map(|e| self.lower_expr(e)), + init: l.init.as_ref().map(|e| P(self.lower_expr(e))), span: l.span, attrs: l.attrs.clone(), }) @@ -400,8 +400,8 @@ impl<'a> LoweringContext<'a> { // Don't expose `Self` (recovered "keyword used as ident" parse error). // `rustc::ty` expects `Self` to be only used for a trait's `Self`. // Instead, use gensym("Self") to create a distinct name that looks the same. - if name == token::keywords::SelfType.name() { - name = token::gensym("Self"); + if name == keywords::SelfType.name() { + name = Symbol::gensym("Self"); } hir::TyParam { @@ -540,7 +540,7 @@ impl<'a> LoweringContext<'a> { hir::StructField { span: f.span, id: f.id, - name: f.ident.map(|ident| ident.name).unwrap_or(token::intern(&index.to_string())), + name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())), vis: self.lower_visibility(&f.vis), ty: self.lower_ty(&f.ty), attrs: self.lower_attrs(&f.attrs), @@ -550,7 +550,7 @@ impl<'a> LoweringContext<'a> { fn lower_field(&mut self, f: &Field) -> hir::Field { hir::Field { name: respan(f.ident.span, f.ident.node.name), - expr: self.lower_expr(&f.expr), + expr: P(self.lower_expr(&f.expr)), span: f.span, is_shorthand: f.is_shorthand, } @@ -599,10 +599,10 @@ impl<'a> LoweringContext<'a> { ItemKind::Static(ref t, m, ref e) => { hir::ItemStatic(self.lower_ty(t), self.lower_mutability(m), - self.lower_expr(e)) + P(self.lower_expr(e))) } ItemKind::Const(ref t, ref e) => { - hir::ItemConst(self.lower_ty(t), self.lower_expr(e)) + hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e))) } ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { let body = self.lower_block(body); @@ -611,7 +611,7 @@ impl<'a> LoweringContext<'a> { self.lower_constness(constness), abi, self.lower_generics(generics), - self.expr_block(body, ThinVec::new())) + P(self.expr_block(body, ThinVec::new()))) } ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)), @@ -672,13 +672,13 @@ impl<'a> LoweringContext<'a> { node: match i.node { TraitItemKind::Const(ref ty, ref default) => { hir::ConstTraitItem(this.lower_ty(ty), - default.as_ref().map(|x| this.lower_expr(x))) + default.as_ref().map(|x| P(this.lower_expr(x)))) } TraitItemKind::Method(ref sig, ref body) => { hir::MethodTraitItem(this.lower_method_sig(sig), body.as_ref().map(|x| { let body = this.lower_block(x); - this.expr_block(body, ThinVec::new()) + P(this.expr_block(body, ThinVec::new())) })) } TraitItemKind::Type(ref bounds, ref default) => { @@ -702,12 +702,12 @@ impl<'a> LoweringContext<'a> { defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), node: match i.node { ImplItemKind::Const(ref ty, ref expr) => { - hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr)) + hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr))) } ImplItemKind::Method(ref sig, ref body) => { let body = this.lower_block(body); hir::ImplItemKind::Method(this.lower_method_sig(sig), - this.expr_block(body, ThinVec::new())) + P(this.expr_block(body, ThinVec::new()))) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -885,7 +885,7 @@ impl<'a> LoweringContext<'a> { } }) } - PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)), + PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))), PatKind::TupleStruct(ref path, ref pats, ddpos) => { hir::PatKind::TupleStruct(self.lower_path(path), pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos) @@ -920,7 +920,7 @@ impl<'a> LoweringContext<'a> { hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl)) } PatKind::Range(ref e1, ref e2) => { - hir::PatKind::Range(self.lower_expr(e1), self.lower_expr(e2)) + hir::PatKind::Range(P(self.lower_expr(e1)), P(self.lower_expr(e2))) } PatKind::Slice(ref before, ref slice, ref after) => { hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(), @@ -933,8 +933,8 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_expr(&mut self, e: &Expr) -> P { - P(hir::Expr { + fn lower_expr(&mut self, e: &Expr) -> hir::Expr { + hir::Expr { id: e.id, node: match e.node { // Issue #22181: @@ -954,7 +954,7 @@ impl<'a> LoweringContext<'a> { // // But for now there are type-inference issues doing that. ExprKind::Box(ref e) => { - hir::ExprBox(self.lower_expr(e)) + hir::ExprBox(P(self.lower_expr(e))) } // Desugar ExprBox: `in (PLACE) EXPR` @@ -968,8 +968,8 @@ impl<'a> LoweringContext<'a> { // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR )); // InPlace::finalize(place) // }) - let placer_expr = self.lower_expr(placer); - let value_expr = self.lower_expr(value_expr); + let placer_expr = P(self.lower_expr(placer)); + let value_expr = P(self.lower_expr(value_expr)); let placer_ident = self.str_to_ident("placer"); let place_ident = self.str_to_ident("place"); @@ -983,7 +983,7 @@ impl<'a> LoweringContext<'a> { let make_call = |this: &mut LoweringContext, p, args| { let path = this.std_path(e.span, p); let path = this.expr_path(path, ThinVec::new()); - this.expr_call(e.span, path, args) + P(this.expr_call(e.span, path, args)) }; let mk_stmt_let = |this: &mut LoweringContext, bind, expr| { @@ -996,11 +996,11 @@ impl<'a> LoweringContext<'a> { // let placer = ; let (s1, placer_binding) = { - let placer_expr = self.signal_block_expr(hir_vec![], - placer_expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new()); + let placer_expr = P(self.signal_block_expr(hir_vec![], + placer_expr, + e.span, + hir::PopUnstableBlock, + ThinVec::new())); mk_stmt_let(self, placer_ident, placer_expr) }; @@ -1013,7 +1013,7 @@ impl<'a> LoweringContext<'a> { // let p_ptr = Place::pointer(&mut place); let (s3, p_ptr_binding) = { - let agent = self.expr_ident(e.span, place_ident, place_binding); + let agent = P(self.expr_ident(e.span, place_ident, place_binding)); let args = hir_vec![self.expr_mut_addr_of(e.span, agent)]; let call = make_call(self, &place_pointer, args); mk_stmt_let(self, p_ptr_ident, call) @@ -1021,11 +1021,11 @@ impl<'a> LoweringContext<'a> { // pop_unsafe!(EXPR)); let pop_unsafe_expr = { - let value_expr = self.signal_block_expr(hir_vec![], - value_expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new()); + let value_expr = P(self.signal_block_expr(hir_vec![], + value_expr, + e.span, + hir::PopUnstableBlock, + ThinVec::new())); self.signal_block_expr(hir_vec![], value_expr, e.span, @@ -1047,11 +1047,11 @@ impl<'a> LoweringContext<'a> { let place = self.expr_ident(e.span, place_ident, place_binding); let call = make_call(self, &inplace_finalize, hir_vec![place]); - self.signal_block_expr(hir_vec![call_move_val_init], - call, - e.span, - hir::PushUnsafeBlock(hir::CompilerGenerated), - ThinVec::new()) + P(self.signal_block_expr(hir_vec![call_move_val_init], + call, + e.span, + hir::PushUnsafeBlock(hir::CompilerGenerated), + ThinVec::new())) }; return self.signal_block_expr(hir_vec![s1, s2, s3], @@ -1065,15 +1065,15 @@ impl<'a> LoweringContext<'a> { hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::Repeat(ref expr, ref count) => { - let expr = self.lower_expr(expr); - let count = self.lower_expr(count); + let expr = P(self.lower_expr(expr)); + let count = P(self.lower_expr(count)); hir::ExprRepeat(expr, count) } ExprKind::Tup(ref elts) => { hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::Call(ref f, ref args) => { - let f = self.lower_expr(f); + let f = P(self.lower_expr(f)); hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::MethodCall(i, ref tps, ref args) => { @@ -1083,27 +1083,27 @@ impl<'a> LoweringContext<'a> { } ExprKind::Binary(binop, ref lhs, ref rhs) => { let binop = self.lower_binop(binop); - let lhs = self.lower_expr(lhs); - let rhs = self.lower_expr(rhs); + let lhs = P(self.lower_expr(lhs)); + let rhs = P(self.lower_expr(rhs)); hir::ExprBinary(binop, lhs, rhs) } ExprKind::Unary(op, ref ohs) => { let op = self.lower_unop(op); - let ohs = self.lower_expr(ohs); + let ohs = P(self.lower_expr(ohs)); hir::ExprUnary(op, ohs) } ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())), ExprKind::Cast(ref expr, ref ty) => { - let expr = self.lower_expr(expr); + let expr = P(self.lower_expr(expr)); hir::ExprCast(expr, self.lower_ty(ty)) } ExprKind::Type(ref expr, ref ty) => { - let expr = self.lower_expr(expr); + let expr = P(self.lower_expr(expr)); hir::ExprType(expr, self.lower_ty(ty)) } ExprKind::AddrOf(m, ref ohs) => { let m = self.lower_mutability(m); - let ohs = self.lower_expr(ohs); + let ohs = P(self.lower_expr(ohs)); hir::ExprAddrOf(m, ohs) } // More complicated than you might expect because the else branch @@ -1114,7 +1114,7 @@ impl<'a> LoweringContext<'a> { ExprKind::IfLet(..) => { // wrap the if-let expr in a block let span = els.span; - let els = self.lower_expr(els); + let els = P(self.lower_expr(els)); let id = self.next_id(); let blk = P(hir::Block { stmts: hir_vec![], @@ -1123,23 +1123,25 @@ impl<'a> LoweringContext<'a> { rules: hir::DefaultBlock, span: span, }); - self.expr_block(blk, ThinVec::new()) + P(self.expr_block(blk, ThinVec::new())) } - _ => self.lower_expr(els), + _ => P(self.lower_expr(els)), } }); - hir::ExprIf(self.lower_expr(cond), self.lower_block(blk), else_opt) + hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt) } ExprKind::While(ref cond, ref body, opt_ident) => { - hir::ExprWhile(self.lower_expr(cond), self.lower_block(body), + hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body), self.lower_opt_sp_ident(opt_ident)) } ExprKind::Loop(ref body, opt_ident) => { - hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident)) + hir::ExprLoop(self.lower_block(body), + self.lower_opt_sp_ident(opt_ident), + hir::LoopSource::Loop) } ExprKind::Match(ref expr, ref arms) => { - hir::ExprMatch(self.lower_expr(expr), + hir::ExprMatch(P(self.lower_expr(expr)), arms.iter().map(|x| self.lower_arm(x)).collect(), hir::MatchSource::Normal) } @@ -1147,33 +1149,33 @@ impl<'a> LoweringContext<'a> { self.with_parent_def(e.id, |this| { hir::ExprClosure(this.lower_capture_clause(capture_clause), this.lower_fn_decl(decl), - this.lower_expr(body), + P(this.lower_expr(body)), fn_decl_span) }) } ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk)), ExprKind::Assign(ref el, ref er) => { - hir::ExprAssign(self.lower_expr(el), self.lower_expr(er)) + hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er))) } ExprKind::AssignOp(op, ref el, ref er) => { hir::ExprAssignOp(self.lower_binop(op), - self.lower_expr(el), - self.lower_expr(er)) + P(self.lower_expr(el)), + P(self.lower_expr(er))) } ExprKind::Field(ref el, ident) => { - hir::ExprField(self.lower_expr(el), respan(ident.span, ident.node.name)) + hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name)) } ExprKind::TupField(ref el, ident) => { - hir::ExprTupField(self.lower_expr(el), ident) + hir::ExprTupField(P(self.lower_expr(el)), ident) } ExprKind::Index(ref el, ref er) => { - hir::ExprIndex(self.lower_expr(el), self.lower_expr(er)) + hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er))) } ExprKind::Range(ref e1, ref e2, lims) => { fn make_struct(this: &mut LoweringContext, ast_expr: &Expr, path: &[&str], - fields: &[(&str, &P)]) -> P { + fields: &[(&str, &P)]) -> hir::Expr { let struct_path = this.std_path(ast_expr.span, &iter::once(&"ops").chain(path) .map(|s| *s) @@ -1183,13 +1185,13 @@ impl<'a> LoweringContext<'a> { this.expr_path(struct_path, ast_expr.attrs.clone()) } else { let fields = fields.into_iter().map(|&(s, e)| { - let expr = this.lower_expr(&e); - let signal_block = this.signal_block_expr(hir_vec![], - expr, - e.span, - hir::PopUnstableBlock, - ThinVec::new()); - this.field(token::intern(s), signal_block, ast_expr.span) + let expr = P(this.lower_expr(&e)); + let signal_block = P(this.signal_block_expr(hir_vec![], + expr, + e.span, + hir::PopUnstableBlock, + ThinVec::new())); + this.field(Symbol::intern(s), signal_block, ast_expr.span) }).collect(); let attrs = ast_expr.attrs.clone(); @@ -1242,9 +1244,12 @@ impl<'a> LoweringContext<'a> { }); hir::ExprPath(hir_qself, self.lower_path(path)) } - ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)), + ExprKind::Break(opt_ident, ref opt_expr) => { + hir::ExprBreak(self.lower_opt_sp_ident(opt_ident), + opt_expr.as_ref().map(|x| P(self.lower_expr(x)))) + } ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), - ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))), + ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))), ExprKind::InlineAsm(ref asm) => { let hir_asm = hir::InlineAsm { inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(), @@ -1272,20 +1277,19 @@ impl<'a> LoweringContext<'a> { ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { hir::ExprStruct(P(self.lower_path(path)), fields.iter().map(|x| self.lower_field(x)).collect(), - maybe_expr.as_ref().map(|x| self.lower_expr(x))) + maybe_expr.as_ref().map(|x| P(self.lower_expr(x)))) } ExprKind::Paren(ref ex) => { - return self.lower_expr(ex).map(|mut ex| { - // include parens in span, but only if it is a super-span. - if e.span.contains(ex.span) { - ex.span = e.span; - } - // merge attributes into the inner expression. - let mut attrs = e.attrs.clone(); - attrs.extend::>(ex.attrs.into()); - ex.attrs = attrs; - ex - }); + let mut ex = self.lower_expr(ex); + // include parens in span, but only if it is a super-span. + if e.span.contains(ex.span) { + ex.span = e.span; + } + // merge attributes into the inner expression. + let mut attrs = e.attrs.clone(); + attrs.extend::>(ex.attrs.into()); + ex.attrs = attrs; + return ex; } // Desugar ExprIfLet @@ -1302,13 +1306,13 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { let body = self.lower_block(body); - let body_expr = self.expr_block(body, ThinVec::new()); + let body_expr = P(self.expr_block(body, ThinVec::new())); let pat = self.lower_pat(pat); self.arm(hir_vec![pat], body_expr) }; // `[_ if => ,]` - let mut else_opt = else_opt.as_ref().map(|e| self.lower_expr(e)); + let mut else_opt = else_opt.as_ref().map(|e| P(self.lower_expr(e))); let else_if_arms = { let mut arms = vec![]; loop { @@ -1322,7 +1326,7 @@ impl<'a> LoweringContext<'a> { attrs: hir_vec![], pats: hir_vec![pat_under], guard: Some(cond), - body: self.expr_block(then, ThinVec::new()), + body: P(self.expr_block(then, ThinVec::new())), }); else_opt.map(|else_opt| (else_opt, true)) } @@ -1362,7 +1366,7 @@ impl<'a> LoweringContext<'a> { arms.extend(else_if_arms); arms.push(else_arm); - let sub_expr = self.lower_expr(sub_expr); + let sub_expr = P(self.lower_expr(sub_expr)); // add attributes to the outer returned expr node return self.expr(e.span, hir::ExprMatch(sub_expr, @@ -1388,7 +1392,7 @@ impl<'a> LoweringContext<'a> { // ` => ` let pat_arm = { let body = self.lower_block(body); - let body_expr = self.expr_block(body, ThinVec::new()); + let body_expr = P(self.expr_block(body, ThinVec::new())); let pat = self.lower_pat(pat); self.arm(hir_vec![pat], body_expr) }; @@ -1402,7 +1406,7 @@ impl<'a> LoweringContext<'a> { // `match { ... }` let arms = hir_vec![pat_arm, break_arm]; - let sub_expr = self.lower_expr(sub_expr); + let sub_expr = P(self.lower_expr(sub_expr)); let match_expr = self.expr(e.span, hir::ExprMatch(sub_expr, arms, @@ -1410,11 +1414,12 @@ impl<'a> LoweringContext<'a> { ThinVec::new()); // `[opt_ident]: loop { ... }` - let loop_block = self.block_expr(match_expr); - let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident)); + let loop_block = P(self.block_expr(P(match_expr))); + let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident), + hir::LoopSource::WhileLet); // add attributes to the outer returned expr node let attrs = e.attrs.clone(); - return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs }); + return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs }; } // Desugar ExprForLoop @@ -1471,20 +1476,23 @@ impl<'a> LoweringContext<'a> { // `match ::std::iter::Iterator::next(&mut iter) { ... }` let match_expr = { let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]); - let iter = self.expr_ident(e.span, iter, iter_pat.id); + let iter = P(self.expr_ident(e.span, iter, iter_pat.id)); let ref_mut_iter = self.expr_mut_addr_of(e.span, iter); let next_path = self.expr_path(next_path, ThinVec::new()); - let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]); + let next_expr = P(self.expr_call(e.span, next_path, + hir_vec![ref_mut_iter])); let arms = hir_vec![pat_arm, break_arm]; - self.expr(e.span, - hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar), - ThinVec::new()) + P(self.expr(e.span, + hir::ExprMatch(next_expr, arms, + hir::MatchSource::ForLoopDesugar), + ThinVec::new())) }; // `[opt_ident]: loop { ... }` - let loop_block = self.block_expr(match_expr); - let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident)); + let loop_block = P(self.block_expr(match_expr)); + let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident), + hir::LoopSource::ForLoop); let loop_expr = P(hir::Expr { id: e.id, node: loop_expr, @@ -1501,13 +1509,13 @@ impl<'a> LoweringContext<'a> { &["iter", "IntoIterator", "into_iter"]); let into_iter = self.expr_path(into_iter_path, ThinVec::new()); - self.expr_call(e.span, into_iter, hir_vec![head]) + P(self.expr_call(e.span, into_iter, hir_vec![head])) }; - let match_expr = self.expr_match(e.span, - into_iter_expr, - hir_vec![iter_arm], - hir::MatchSource::ForLoopDesugar); + let match_expr = P(self.expr_match(e.span, + into_iter_expr, + hir_vec![iter_arm], + hir::MatchSource::ForLoopDesugar)); // `{ let _result = ...; _result }` // underscore prevents an unused_variables lint if the head diverges @@ -1515,8 +1523,8 @@ impl<'a> LoweringContext<'a> { let (let_stmt, let_stmt_binding) = self.stmt_let(e.span, false, result_ident, match_expr); - let result = self.expr_ident(e.span, result_ident, let_stmt_binding); - let block = self.block_all(e.span, hir_vec![let_stmt], Some(result)); + let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding)); + let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result))); // add the attributes to the outer returned expr node return self.expr_block(block, e.attrs.clone()); } @@ -1536,7 +1544,7 @@ impl<'a> LoweringContext<'a> { // { Carrier::translate( { } ) } let discr = { // expand - let sub_expr = self.lower_expr(sub_expr); + let sub_expr = P(self.lower_expr(sub_expr)); let sub_expr = self.signal_block_expr(hir_vec![], sub_expr, e.span, @@ -1545,20 +1553,20 @@ impl<'a> LoweringContext<'a> { let path = self.std_path(e.span, &["ops", "Carrier", "translate"]); let path = self.expr_path(path, ThinVec::new()); - let call = self.expr_call(e.span, path, hir_vec![sub_expr]); + let call = P(self.expr_call(e.span, path, hir_vec![sub_expr])); - self.signal_block_expr(hir_vec![], - call, - e.span, - hir::PushUnstableBlock, - ThinVec::new()) + P(self.signal_block_expr(hir_vec![], + call, + e.span, + hir::PushUnstableBlock, + ThinVec::new())) }; // Ok(val) => val let ok_arm = { let val_ident = self.str_to_ident("val"); let val_pat = self.pat_ident(e.span, val_ident); - let val_expr = self.expr_ident(e.span, val_ident, val_pat.id); + let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id)); let ok_pat = self.pat_ok(e.span, val_pat); self.arm(hir_vec![ok_pat], val_expr) @@ -1578,15 +1586,16 @@ impl<'a> LoweringContext<'a> { let from_err_expr = { let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]); let from_err = self.expr_path(path, ThinVec::new()); - self.expr_call(e.span, from_err, hir_vec![from_expr]) + P(self.expr_call(e.span, from_err, hir_vec![from_expr])) }; - let ret_expr = self.expr(e.span, - hir::Expr_::ExprRet(Some(from_err_expr)), - ThinVec::new()); + let ret_expr = P(self.expr(e.span, + hir::Expr_::ExprRet(Some(from_err_expr)), + ThinVec::new())); let ret_stmt = self.stmt_expr(ret_expr); - let block = self.signal_block_stmt(ret_stmt, e.span, - hir::PushUnstableBlock, ThinVec::new()); + let block = P(self.signal_block_stmt(ret_stmt, e.span, + hir::PushUnstableBlock, + ThinVec::new())); let err_pat = self.pat_err(e.span, err_local); self.arm(hir_vec![err_pat], block) @@ -1600,7 +1609,7 @@ impl<'a> LoweringContext<'a> { }, span: e.span, attrs: e.attrs.clone(), - }) + } } fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt { @@ -1621,13 +1630,13 @@ impl<'a> LoweringContext<'a> { }, StmtKind::Expr(ref e) => { Spanned { - node: hir::StmtExpr(self.lower_expr(e), s.id), + node: hir::StmtExpr(P(self.lower_expr(e)), s.id), span: s.span, } } StmtKind::Semi(ref e) => { Spanned { - node: hir::StmtSemi(self.lower_expr(e), s.id), + node: hir::StmtSemi(P(self.lower_expr(e)), s.id), span: s.span, } } @@ -1721,15 +1730,15 @@ impl<'a> LoweringContext<'a> { } fn expr_break(&mut self, span: Span, attrs: ThinVec) -> P { - self.expr(span, hir::ExprBreak(None), attrs) + P(self.expr(span, hir::ExprBreak(None, None), attrs)) } - fn expr_call(&mut self, span: Span, e: P, args: hir::HirVec>) - -> P { + fn expr_call(&mut self, span: Span, e: P, args: hir::HirVec) + -> hir::Expr { self.expr(span, hir::ExprCall(e, args), ThinVec::new()) } - fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P { + fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr { let expr_path = hir::ExprPath(None, self.path_ident(span, id)); let expr = self.expr(span, expr_path, ThinVec::new()); @@ -1742,13 +1751,13 @@ impl<'a> LoweringContext<'a> { expr } - fn expr_mut_addr_of(&mut self, span: Span, e: P) -> P { + fn expr_mut_addr_of(&mut self, span: Span, e: P) -> hir::Expr { self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new()) } fn expr_path(&mut self, path: hir::Path, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, true); - let expr = self.expr(path.span, hir::ExprPath(None, path), attrs); + let expr = P(self.expr(path.span, hir::ExprPath(None, path), attrs)); self.resolver.record_resolution(expr.id, def); expr } @@ -1758,16 +1767,16 @@ impl<'a> LoweringContext<'a> { arg: P, arms: hir::HirVec, source: hir::MatchSource) - -> P { + -> hir::Expr { self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new()) } - fn expr_block(&mut self, b: P, attrs: ThinVec) -> P { + fn expr_block(&mut self, b: P, attrs: ThinVec) -> hir::Expr { self.expr(b.span, hir::ExprBlock(b), attrs) } - fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec>) -> P { - self.expr(sp, hir::ExprTup(exprs), ThinVec::new()) + fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec) -> P { + P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new())) } fn expr_struct(&mut self, @@ -1777,18 +1786,18 @@ impl<'a> LoweringContext<'a> { e: Option>, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, false); - let expr = self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs); + let expr = P(self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs)); self.resolver.record_resolution(expr.id, def); expr } - fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec) -> P { - P(hir::Expr { + fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec) -> hir::Expr { + hir::Expr { id: self.next_id(), node: node, span: span, attrs: attrs, - }) + } } fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P) @@ -1820,19 +1829,19 @@ impl<'a> LoweringContext<'a> { } } - fn block_expr(&mut self, expr: P) -> P { + fn block_expr(&mut self, expr: P) -> hir::Block { self.block_all(expr.span, hir::HirVec::new(), Some(expr)) } fn block_all(&mut self, span: Span, stmts: hir::HirVec, expr: Option>) - -> P { - P(hir::Block { + -> hir::Block { + hir::Block { stmts: stmts, expr: expr, id: self.next_id(), rules: hir::DefaultBlock, span: span, - }) + } } fn pat_ok(&mut self, span: Span, pat: P) -> P { @@ -1953,9 +1962,9 @@ impl<'a> LoweringContext<'a> { fn std_path_components(&mut self, components: &[&str]) -> Vec { let mut v = Vec::new(); if let Some(s) = self.crate_root { - v.push(token::intern(s)); + v.push(Symbol::intern(s)); } - v.extend(components.iter().map(|s| token::intern(s))); + v.extend(components.iter().map(|s| Symbol::intern(s))); return v; } @@ -1972,7 +1981,7 @@ impl<'a> LoweringContext<'a> { span: Span, rule: hir::BlockCheckMode, attrs: ThinVec) - -> P { + -> hir::Expr { let id = self.next_id(); let block = P(hir::Block { rules: rule, @@ -1989,7 +1998,7 @@ impl<'a> LoweringContext<'a> { span: Span, rule: hir::BlockCheckMode, attrs: ThinVec) - -> P { + -> hir::Expr { let id = self.next_id(); let block = P(hir::Block { rules: rule, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 51a378a08336..89217e83ca22 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -9,9 +9,7 @@ // except according to those terms. use super::*; -use super::MapEntry::*; -use hir::*; use hir::intravisit::Visitor; use hir::def_id::DefId; use middle::cstore::InlinedItem; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 421843a7f11d..7486d954c480 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::*; +use hir::map::definitions::*; use hir; use hir::intravisit; @@ -19,7 +19,7 @@ use middle::cstore::InlinedItem; use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; -use syntax::parse::token::{self, keywords}; +use syntax::symbol::{Symbol, keywords}; /// Creates def ids for nodes in the HIR. pub struct DefCollector<'a> { @@ -169,7 +169,7 @@ impl<'a> visit::Visitor for DefCollector<'a> { this.with_parent(variant_def_index, |this| { for (index, field) in v.node.data.fields().iter().enumerate() { let name = field.ident.map(|ident| ident.name) - .unwrap_or_else(|| token::intern(&index.to_string())); + .unwrap_or_else(|| Symbol::intern(&index.to_string())); this.create_def(field.id, DefPathData::Field(name.as_str())); } @@ -188,7 +188,7 @@ impl<'a> visit::Visitor for DefCollector<'a> { for (index, field) in struct_def.fields().iter().enumerate() { let name = field.ident.map(|ident| ident.name.as_str()) - .unwrap_or(token::intern(&index.to_string()).as_str()); + .unwrap_or(Symbol::intern(&index.to_string()).as_str()); this.create_def(field.id, DefPathData::Field(name)); } } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 38157c7e5656..83d3627d8e61 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -14,7 +14,7 @@ use std::fmt::Write; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; use syntax::ast; -use syntax::parse::token::{self, InternedString}; +use syntax::symbol::{Symbol, InternedString}; use ty::TyCtxt; use util::nodemap::NodeMap; @@ -115,9 +115,9 @@ impl DefPath { pub fn to_string(&self, tcx: TyCtxt) -> String { let mut s = String::with_capacity(self.data.len() * 16); - s.push_str(&tcx.original_crate_name(self.krate)); + s.push_str(&tcx.original_crate_name(self.krate).as_str()); s.push_str("/"); - s.push_str(&tcx.crate_disambiguator(self.krate)); + s.push_str(&tcx.crate_disambiguator(self.krate).as_str()); for component in &self.data { write!(s, @@ -137,8 +137,8 @@ impl DefPath { } pub fn deterministic_hash_to(&self, tcx: TyCtxt, state: &mut H) { - tcx.original_crate_name(self.krate).hash(state); - tcx.crate_disambiguator(self.krate).hash(state); + tcx.original_crate_name(self.krate).as_str().hash(state); + tcx.crate_disambiguator(self.krate).as_str().hash(state); self.data.hash(state); } } @@ -328,7 +328,7 @@ impl DefPathData { LifetimeDef(ref name) | EnumVariant(ref name) | Binding(ref name) | - Field(ref name) => Some(token::intern(name)), + Field(ref name) => Some(Symbol::intern(name)), Impl | CrateRoot | @@ -343,7 +343,7 @@ impl DefPathData { pub fn as_interned_str(&self) -> InternedString { use self::DefPathData::*; - match *self { + let s = match *self { TypeNs(ref name) | ValueNs(ref name) | Module(ref name) | @@ -353,43 +353,24 @@ impl DefPathData { EnumVariant(ref name) | Binding(ref name) | Field(ref name) => { - name.clone() - } - - Impl => { - InternedString::new("{{impl}}") + return name.clone(); } // note that this does not show up in user printouts - CrateRoot => { - InternedString::new("{{root}}") - } + CrateRoot => "{{root}}", // note that this does not show up in user printouts - InlinedRoot(_) => { - InternedString::new("{{inlined-root}}") - } + InlinedRoot(_) => "{{inlined-root}}", - Misc => { - InternedString::new("{{?}}") - } + Impl => "{{impl}}", + Misc => "{{?}}", + ClosureExpr => "{{closure}}", + StructCtor => "{{constructor}}", + Initializer => "{{initializer}}", + ImplTrait => "{{impl-Trait}}", + }; - ClosureExpr => { - InternedString::new("{{closure}}") - } - - StructCtor => { - InternedString::new("{{constructor}}") - } - - Initializer => { - InternedString::new("{{initializer}}") - } - - ImplTrait => { - InternedString::new("{{impl-Trait}}") - } - } + Symbol::intern(s).as_str() } pub fn to_string(&self) -> String { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 06cfc8aee8c9..a90577b34261 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -765,7 +765,7 @@ impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { None => return false, Some((node_id, name)) => (node_id, name), }; - if &part[..] != mod_name.as_str() { + if mod_name != &**part { return false; } cursor = self.map.get_parent(mod_id); @@ -803,8 +803,7 @@ impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { - name.as_str() == &self.item_name[..] && - self.suffix_matches(parent_of_n) + name == &**self.item_name && self.suffix_matches(parent_of_n) } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9f5ff6914b0c..316487652242 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -40,8 +40,8 @@ use syntax::codemap::{self, respan, Spanned}; use syntax::abi::Abi; use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect}; use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem}; -use syntax::parse::token::{keywords, InternedString}; use syntax::ptr::P; +use syntax::symbol::{Symbol, keywords}; use syntax::tokenstream::TokenTree; use syntax::util::ThinVec; @@ -867,12 +867,12 @@ pub enum Expr_ { /// A `box x` expression. ExprBox(P), /// An array (`[a, b, c, d]`) - ExprArray(HirVec>), + ExprArray(HirVec), /// A function call /// /// The first field resolves to the function itself (usually an `ExprPath`), /// and the second field is the list of arguments - ExprCall(P, HirVec>), + ExprCall(P, HirVec), /// A method call (`x.foo::(a, b, c, d)`) /// /// The `Spanned` is the identifier for the method name. @@ -885,9 +885,9 @@ pub enum Expr_ { /// /// Thus, `x.foo::(a, b, c, d)` is represented as /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`. - ExprMethodCall(Spanned, HirVec>, HirVec>), + ExprMethodCall(Spanned, HirVec>, HirVec), /// A tuple (`(a, b, c ,d)`) - ExprTup(HirVec>), + ExprTup(HirVec), /// A binary operation (For example: `a + b`, `a * b`) ExprBinary(BinOp, P, P), /// A unary operation (For example: `!x`, `*x`) @@ -908,7 +908,7 @@ pub enum Expr_ { /// Conditionless loop (can be exited with break, continue, or return) /// /// `'label: loop { block }` - ExprLoop(P, Option>), + ExprLoop(P, Option>, LoopSource), /// A `match` block, with a source that indicates whether or not it is /// the result of a desugaring, and if so, which kind. ExprMatch(P, HirVec, MatchSource), @@ -944,14 +944,14 @@ pub enum Expr_ { /// A referencing operation (`&a` or `&mut a`) ExprAddrOf(Mutability, P), /// A `break`, with an optional label to break - ExprBreak(Option>), + ExprBreak(Option>, Option>), /// A `continue`, with an optional label ExprAgain(Option>), /// A `return`, with an optional value to be returned ExprRet(Option>), /// Inline assembly (from `asm!`), with its outputs and inputs. - ExprInlineAsm(P, HirVec>, HirVec>), + ExprInlineAsm(P, HirVec, HirVec), /// A struct or struct-like variant literal expression. /// @@ -1002,6 +1002,18 @@ pub enum MatchSource { TryDesugar, } +/// The loop type that yielded an ExprLoop +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +pub enum LoopSource { + /// A `loop { .. }` loop + Loop, + /// A `while let _ = _ { .. }` loop + WhileLet, + /// A `for _ in _ { .. }` loop + ForLoop, +} + + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum CaptureClause { CaptureByValue, @@ -1163,18 +1175,18 @@ pub enum Ty_ { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct InlineAsmOutput { - pub constraint: InternedString, + pub constraint: Symbol, pub is_rw: bool, pub is_indirect: bool, } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct InlineAsm { - pub asm: InternedString, + pub asm: Symbol, pub asm_str_style: StrStyle, pub outputs: HirVec, - pub inputs: HirVec, - pub clobbers: HirVec, + pub inputs: HirVec, + pub clobbers: HirVec, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 807bbec3b588..c109e84bf618 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -13,13 +13,14 @@ pub use self::AnnNode::*; use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{CodeMap, Spanned}; -use syntax::parse::token::{self, keywords, BinOpToken}; +use syntax::parse::token::{self, BinOpToken}; use syntax::parse::lexer::comments; use syntax::print::pp::{self, break_offset, word, space, hardbreak}; use syntax::print::pp::{Breaks, eof}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; use syntax::print::pprust::{self as ast_pp, PrintState}; use syntax::ptr::P; +use syntax::symbol::keywords; use syntax_pos::{self, BytePos}; use errors; @@ -451,7 +452,7 @@ impl<'a> State<'a> { self.end() } - pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P]) -> io::Result<()> { + pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr]) -> io::Result<()> { self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&e), |e| e.span) } @@ -1199,7 +1200,7 @@ impl<'a> State<'a> { } - fn print_call_post(&mut self, args: &[P]) -> io::Result<()> { + fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> { self.popen()?; self.commasep_exprs(Inconsistent, args)?; self.pclose() @@ -1217,10 +1218,10 @@ impl<'a> State<'a> { Ok(()) } - fn print_expr_vec(&mut self, exprs: &[P]) -> io::Result<()> { + fn print_expr_vec(&mut self, exprs: &[hir::Expr]) -> io::Result<()> { self.ibox(indent_unit)?; word(&mut self.s, "[")?; - self.commasep_exprs(Inconsistent, &exprs[..])?; + self.commasep_exprs(Inconsistent, exprs)?; word(&mut self.s, "]")?; self.end() } @@ -1273,16 +1274,16 @@ impl<'a> State<'a> { Ok(()) } - fn print_expr_tup(&mut self, exprs: &[P]) -> io::Result<()> { + fn print_expr_tup(&mut self, exprs: &[hir::Expr]) -> io::Result<()> { self.popen()?; - self.commasep_exprs(Inconsistent, &exprs[..])?; + self.commasep_exprs(Inconsistent, exprs)?; if exprs.len() == 1 { word(&mut self.s, ",")?; } self.pclose() } - fn print_expr_call(&mut self, func: &hir::Expr, args: &[P]) -> io::Result<()> { + fn print_expr_call(&mut self, func: &hir::Expr, args: &[hir::Expr]) -> io::Result<()> { self.print_expr_maybe_paren(func)?; self.print_call_post(args) } @@ -1290,7 +1291,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, name: Spanned, tys: &[P], - args: &[P]) + args: &[hir::Expr]) -> io::Result<()> { let base_args = &args[1..]; self.print_expr(&args[0])?; @@ -1339,7 +1340,7 @@ impl<'a> State<'a> { self.print_expr(expr)?; } hir::ExprArray(ref exprs) => { - self.print_expr_vec(&exprs[..])?; + self.print_expr_vec(exprs)?; } hir::ExprRepeat(ref element, ref count) => { self.print_expr_repeat(&element, &count)?; @@ -1348,13 +1349,13 @@ impl<'a> State<'a> { self.print_expr_struct(path, &fields[..], wth)?; } hir::ExprTup(ref exprs) => { - self.print_expr_tup(&exprs[..])?; + self.print_expr_tup(exprs)?; } hir::ExprCall(ref func, ref args) => { - self.print_expr_call(&func, &args[..])?; + self.print_expr_call(&func, args)?; } hir::ExprMethodCall(name, ref tys, ref args) => { - self.print_expr_method_call(name, &tys[..], &args[..])?; + self.print_expr_method_call(name, &tys[..], args)?; } hir::ExprBinary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, &lhs, &rhs)?; @@ -1392,7 +1393,7 @@ impl<'a> State<'a> { space(&mut self.s)?; self.print_block(&blk)?; } - hir::ExprLoop(ref blk, opt_sp_name) => { + hir::ExprLoop(ref blk, opt_sp_name, _) => { if let Some(sp_name) = opt_sp_name { self.print_name(sp_name.node)?; self.word_space(":")?; @@ -1470,13 +1471,17 @@ impl<'a> State<'a> { hir::ExprPath(Some(ref qself), ref path) => { self.print_qpath(path, qself, true)? } - hir::ExprBreak(opt_name) => { + hir::ExprBreak(opt_name, ref opt_expr) => { word(&mut self.s, "break")?; space(&mut self.s)?; if let Some(name) = opt_name { self.print_name(name.node)?; space(&mut self.s)?; } + if let Some(ref expr) = *opt_expr { + self.print_expr(expr)?; + space(&mut self.s)?; + } } hir::ExprAgain(opt_name) => { word(&mut self.s, "continue")?; @@ -1499,19 +1504,19 @@ impl<'a> State<'a> { hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => { word(&mut self.s, "asm!")?; self.popen()?; - self.print_string(&a.asm, a.asm_str_style)?; + self.print_string(&a.asm.as_str(), a.asm_str_style)?; self.word_space(":")?; let mut out_idx = 0; self.commasep(Inconsistent, &a.outputs, |s, out| { - let mut ch = out.constraint.chars(); + let constraint = out.constraint.as_str(); + let mut ch = constraint.chars(); match ch.next() { Some('=') if out.is_rw => { s.print_string(&format!("+{}", ch.as_str()), ast::StrStyle::Cooked)? } - _ => s.print_string(&out.constraint, - ast::StrStyle::Cooked)?, + _ => s.print_string(&constraint, ast::StrStyle::Cooked)?, } s.popen()?; s.print_expr(&outputs[out_idx])?; @@ -1524,7 +1529,7 @@ impl<'a> State<'a> { let mut in_idx = 0; self.commasep(Inconsistent, &a.inputs, |s, co| { - s.print_string(&co, ast::StrStyle::Cooked)?; + s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; s.popen()?; s.print_expr(&inputs[in_idx])?; s.pclose()?; @@ -1535,7 +1540,7 @@ impl<'a> State<'a> { self.word_space(":")?; self.commasep(Inconsistent, &a.clobbers, |s, co| { - s.print_string(&co, ast::StrStyle::Cooked)?; + s.print_string(&co.as_str(), ast::StrStyle::Cooked)?; Ok(()) })?; diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index 58caac4034e3..8db09d0b73d3 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -91,8 +91,8 @@ use std::cell::{Cell, RefCell}; use std::char::from_u32; use std::fmt; use syntax::ast; -use syntax::parse::token; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::{self, Pos, Span}; use errors::DiagnosticBuilder; @@ -1219,7 +1219,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> { names.push(lt_name); } names.sort(); - let name = token::intern(&names[0]); + let name = Symbol::intern(&names[0]); return (name_to_dummy_lifetime(name), Kept); } return (self.life_giver.give_lifetime(), Fresh); @@ -1931,7 +1931,7 @@ impl LifeGiver { let mut s = String::from("'"); s.push_str(&num_to_string(self.counter.get())); if !self.taken.contains(&s) { - lifetime = name_to_dummy_lifetime(token::intern(&s[..])); + lifetime = name_to_dummy_lifetime(Symbol::intern(&s)); self.generated.borrow_mut().push(lifetime); break; } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 8c0d70c6d602..0942ce79a6b4 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -33,6 +33,7 @@ #![feature(core_intrinsics)] #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))] #![feature(enumset)] +#![cfg_attr(stage0, feature(item_like_imports))] #![feature(libc)] #![feature(nonzero)] #![feature(quote)] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 82a46f76401d..96aee04b6b7a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -157,7 +157,7 @@ declare_lint! { declare_lint! { pub HR_LIFETIME_IN_ASSOC_TYPE, - Warn, + Deny, "binding for associated type references higher-ranked lifetime \ that does not appear in the trait input types" } @@ -204,6 +204,13 @@ declare_lint! { "detects extra requirements in impls that were erroneously allowed" } +declare_lint! { + pub LEGACY_DIRECTORY_OWNERSHIP, + Warn, + "non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files \ + not named `mod.rs`" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -242,7 +249,8 @@ impl LintPass for HardwiredLints { LIFETIME_UNDERSCORE, SAFE_EXTERN_STATICS, PATTERNS_IN_FNS_WITHOUT_BODY, - EXTRA_REQUIREMENT_IN_IMPL + EXTRA_REQUIREMENT_IN_IMPL, + LEGACY_DIRECTORY_OWNERSHIP ) } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index a490b58964a7..4a082944010b 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -40,7 +40,6 @@ use std::default::Default as StdDefault; use std::mem; use std::fmt; use syntax::attr; -use syntax::parse::token::InternedString; use syntax::ast; use syntax_pos::{MultiSpan, Span}; use errors::{self, Diagnostic, DiagnosticBuilder}; @@ -384,8 +383,7 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({ /// Parse the lint attributes into a vector, with `Err`s for malformed lint /// attributes. Writing this as an iterator is an enormous mess. // See also the hir version just below. -pub fn gather_attrs(attrs: &[ast::Attribute]) - -> Vec> { +pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec> { let mut out = vec![]; for attr in attrs { let r = gather_attr(attr); @@ -394,18 +392,17 @@ pub fn gather_attrs(attrs: &[ast::Attribute]) out } -pub fn gather_attr(attr: &ast::Attribute) - -> Vec> { +pub fn gather_attr(attr: &ast::Attribute) -> Vec> { let mut out = vec![]; - let level = match Level::from_str(&attr.name()) { + let level = match Level::from_str(&attr.name().as_str()) { None => return out, Some(lvl) => lvl, }; attr::mark_used(attr); - let meta = &attr.node.value; + let meta = &attr.value; let metas = if let Some(metas) = meta.meta_item_list() { metas } else { @@ -414,9 +411,7 @@ pub fn gather_attr(attr: &ast::Attribute) }; for li in metas { - out.push(li.word().map_or(Err(li.span), |word| { - Ok((word.name().clone(), level, word.span)) - })); + out.push(li.word().map_or(Err(li.span), |word| Ok((word.name(), level, word.span)))); } out @@ -629,10 +624,10 @@ pub trait LintContext: Sized { continue; } Ok((lint_name, level, span)) => { - match self.lints().find_lint(&lint_name, &self.sess(), Some(span)) { + match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) { Ok(lint_id) => vec![(lint_id, level, span)], Err(FindLintError::NotFound) => { - match self.lints().lint_groups.get(&lint_name[..]) { + match self.lints().lint_groups.get(&*lint_name.as_str()) { Some(&(ref v, _)) => v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) @@ -1193,8 +1188,7 @@ fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) { continue; } Ok((lint_name, _, span)) => { - match check_lint_name(&cx.lints, - &lint_name[..]) { + match check_lint_name(&cx.lints, &lint_name.as_str()) { CheckLintNameResult::Ok => (), CheckLintNameResult::Warning(ref msg) => { cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS, diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 3482971cd199..9677082a43a3 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::parse::token::InternedString; +use syntax::symbol::InternedString; use syntax::ast; use std::rc::Rc; use hir::def_id::DefId; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index f61978271e7f..a7f28dd6d58c 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -39,7 +39,7 @@ use syntax::ast; use syntax::attr; use syntax::ext::base::SyntaxExtension; use syntax::ptr::P; -use syntax::parse::token::InternedString; +use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_back::target::Target; use hir; @@ -52,16 +52,17 @@ pub use self::NativeLibraryKind::{NativeStatic, NativeFramework, NativeUnknown}; #[derive(Clone, Debug)] pub struct LinkMeta { - pub crate_name: String, + pub crate_name: Symbol, pub crate_hash: Svh, } -// Where a crate came from on the local filesystem. One of these two options +// Where a crate came from on the local filesystem. One of these three options // must be non-None. #[derive(PartialEq, Clone, Debug)] pub struct CrateSource { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, + pub rmeta: Option<(PathBuf, PathKind)>, } #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] @@ -76,6 +77,30 @@ pub enum DepKind { Explicit, } +#[derive(PartialEq, Clone, Debug)] +pub enum LibSource { + Some(PathBuf), + MetadataOnly, + None, +} + +impl LibSource { + pub fn is_some(&self) -> bool { + if let LibSource::Some(_) = *self { + true + } else { + false + } + } + + pub fn option(&self) -> Option { + match *self { + LibSource::Some(ref p) => Some(p.clone()), + LibSource::MetadataOnly | LibSource::None => None, + } + } +} + #[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)] pub enum LinkagePreference { RequireDynamic, @@ -92,8 +117,8 @@ pub enum NativeLibraryKind { #[derive(Clone, Hash, RustcEncodable, RustcDecodable)] pub struct NativeLibrary { pub kind: NativeLibraryKind, - pub name: String, - pub cfg: Option>, + pub name: Symbol, + pub cfg: Option, } /// The data we save and restore about an inlined item or method. This is not @@ -205,11 +230,11 @@ pub trait CrateStore<'tcx> { fn extern_crate(&self, cnum: CrateNum) -> Option; /// The name of the crate as it is referred to in source code of the current /// crate. - fn crate_name(&self, cnum: CrateNum) -> InternedString; + fn crate_name(&self, cnum: CrateNum) -> Symbol; /// The name of the crate as it is stored in the crate's metadata. - fn original_crate_name(&self, cnum: CrateNum) -> InternedString; + fn original_crate_name(&self, cnum: CrateNum) -> Symbol; fn crate_hash(&self, cnum: CrateNum) -> Svh; - fn crate_disambiguator(&self, cnum: CrateNum) -> InternedString; + fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol; fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option; fn native_libraries(&self, cnum: CrateNum) -> Vec; fn reachable_ids(&self, cnum: CrateNum) -> Vec; @@ -244,7 +269,7 @@ pub trait CrateStore<'tcx> { // utility functions fn metadata_filename(&self) -> &str; fn metadata_section_name(&self, target: &Target) -> &str; - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)>; + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>; fn used_crate_source(&self, cnum: CrateNum) -> CrateSource; fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option; fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -375,13 +400,13 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { bug!("panic_strategy") } fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } - fn crate_name(&self, cnum: CrateNum) -> InternedString { bug!("crate_name") } - fn original_crate_name(&self, cnum: CrateNum) -> InternedString { + fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") } + fn original_crate_name(&self, cnum: CrateNum) -> Symbol { bug!("original_crate_name") } fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") } fn crate_disambiguator(&self, cnum: CrateNum) - -> InternedString { bug!("crate_disambiguator") } + -> Symbol { bug!("crate_disambiguator") } fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option { bug!("plugin_registrar_fn") } fn native_libraries(&self, cnum: CrateNum) -> Vec @@ -427,7 +452,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // utility functions fn metadata_filename(&self) -> &str { bug!("metadata_filename") } fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") } - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { vec![] } fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") } fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { None } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 991398813752..f47eab013c2b 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -309,8 +309,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { let dead_code = lint::builtin::DEAD_CODE.name_lower(); for attr in lint::gather_attrs(attrs) { match attr { - Ok((ref name, lint::Allow, _)) - if &name[..] == dead_code => return true, + Ok((name, lint::Allow, _)) if name == &*dead_code => return true, _ => (), } } @@ -499,8 +498,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { span: syntax_pos::Span, name: ast::Name, node_type: &str) { - let name = name.as_str(); - if !name.starts_with("_") { + if !name.as_str().starts_with("_") { self.tcx .sess .add_lint(lint::builtin::DEAD_CODE, diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 92d1ab85c5a0..ee7f13f9e6e2 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -114,7 +114,7 @@ fn calculate_type(sess: &session::Session, // No linkage happens with rlibs, we just needed the metadata (which we // got long ago), so don't bother with anything. - config::CrateTypeRlib => return Vec::new(), + config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(), // Staticlibs and cdylibs must have all static dependencies. If any fail // to be found, we generate some nice pretty errors. @@ -192,7 +192,7 @@ fn calculate_type(sess: &session::Session, if src.dylib.is_none() && !formats.contains_key(&cnum) && sess.cstore.dep_kind(cnum) == DepKind::Explicit { - assert!(src.rlib.is_some()); + assert!(src.rlib.is_some() || src.rmeta.is_some()); info!("adding staticlib: {}", sess.cstore.crate_name(cnum)); add_library(sess, cnum, RequireStatic, &mut formats); ret[cnum.as_usize() - 1] = Linkage::Static; diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 9dd54457a349..65aedae347a8 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -92,7 +92,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, "main") { EntryPointType::MainAttr - } else if item.name.as_str() == "main" { + } else if item.name == "main" { if at_root { // This is a top-level function so can be 'main' EntryPointType::MainNamed diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 231da576f2b9..594ed408d8cd 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -327,7 +327,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.delegate.consume(consume_id, consume_span, cmt, mode); } - fn consume_exprs(&mut self, exprs: &[P]) { + fn consume_exprs(&mut self, exprs: &[hir::Expr]) { for expr in exprs { self.consume_expr(&expr); } @@ -472,11 +472,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.consume_exprs(inputs); } - hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(..) => {} - hir::ExprLoop(ref blk, _) => { + hir::ExprLoop(ref blk, _, _) => { self.walk_block(&blk); } @@ -514,7 +513,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.walk_block(&blk); } - hir::ExprRet(ref opt_expr) => { + hir::ExprBreak(_, ref opt_expr) | hir::ExprRet(ref opt_expr) => { if let Some(ref expr) = *opt_expr { self.consume_expr(&expr); } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index cf08b59312d5..80cf64865abe 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { ty::TyFnDef(.., ref bfty) => bfty.abi == RustIntrinsic, _ => return false }; - intrinsic && self.infcx.tcx.item_name(def_id).as_str() == "transmute" + intrinsic && self.infcx.tcx.item_name(def_id) == "transmute" } fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>, id: ast::NodeId) { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 9b4b1396669a..5af9a2f02742 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -30,7 +30,7 @@ use middle::weak_lang_items; use util::nodemap::FxHashMap; use syntax::ast; -use syntax::parse::token::InternedString; +use syntax::symbol::Symbol; use hir::itemlikevisit::ItemLikeVisitor; use hir; @@ -152,7 +152,7 @@ struct LanguageItemCollector<'a, 'tcx: 'a> { impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { fn visit_item(&mut self, item: &hir::Item) { if let Some(value) = extract(&item.attrs) { - let item_index = self.item_refs.get(&value[..]).cloned(); + let item_index = self.item_refs.get(&*value.as_str()).cloned(); if let Some(item_index) = item_index { self.collect_item(item_index, self.ast_map.local_def_id(item.id)) @@ -160,7 +160,7 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> { let span = self.ast_map.span(item.id); span_err!(self.session, span, E0522, "definition of an unknown language item: `{}`.", - &value[..]); + value); } } } @@ -243,12 +243,10 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> { } } -pub fn extract(attrs: &[ast::Attribute]) -> Option { +pub fn extract(attrs: &[ast::Attribute]) -> Option { for attribute in attrs { match attribute.value_str() { - Some(ref value) if attribute.check_name("lang") => { - return Some(value.clone()); - } + Some(value) if attribute.check_name("lang") => return Some(value), _ => {} } } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d381188d56b5..4b1787ba593c 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -123,8 +123,7 @@ use std::io::prelude::*; use std::io; use std::rc::Rc; use syntax::ast::{self, NodeId}; -use syntax::parse::token::keywords; -use syntax::ptr::P; +use syntax::symbol::keywords; use syntax_pos::Span; use hir::Expr; @@ -491,7 +490,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) | hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) | hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) | - hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(_) | + hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) | hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) | hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) | @@ -902,7 +901,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.define_bindings_in_pat(&local.pat, succ) } - fn propagate_through_exprs(&mut self, exprs: &[P], succ: LiveNode) + fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode) -> LiveNode { exprs.iter().rev().fold(succ, |succ, expr| { self.propagate_through_expr(&expr, succ) @@ -991,7 +990,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Note that labels have been resolved, so we don't need to look // at the label ident - hir::ExprLoop(ref blk, _) => { + hir::ExprLoop(ref blk, _, _) => { self.propagate_through_loop(expr, LoopLoop, &blk, succ) } @@ -1036,7 +1035,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln) } - hir::ExprBreak(opt_label) => { + hir::ExprBreak(opt_label, ref opt_expr) => { // Find which label this break jumps to let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span); @@ -1044,7 +1043,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // look it up in the break loop nodes table match self.break_ln.get(&sc) { - Some(&b) => b, + Some(&b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b), None => span_bug!(expr.span, "break to unknown label") } } @@ -1058,7 +1057,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match self.cont_ln.get(&sc) { Some(&b) => b, - None => span_bug!(expr.span, "loop to unknown label") + None => span_bug!(expr.span, "continue to unknown label") } } @@ -1087,7 +1086,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Uninteresting cases: just propagate in rev exec order hir::ExprArray(ref exprs) => { - self.propagate_through_exprs(&exprs[..], succ) + self.propagate_through_exprs(exprs, succ) } hir::ExprRepeat(ref element, ref count) => { @@ -1111,7 +1110,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } else { succ }; - let succ = self.propagate_through_exprs(&args[..], succ); + let succ = self.propagate_through_exprs(args, succ); self.propagate_through_expr(&f, succ) } @@ -1124,11 +1123,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } else { succ }; - self.propagate_through_exprs(&args[..], succ) + self.propagate_through_exprs(args, succ) } hir::ExprTup(ref exprs) => { - self.propagate_through_exprs(&exprs[..], succ) + self.propagate_through_exprs(exprs, succ) } hir::ExprBinary(op, ref l, ref r) if op.node.is_lazy() => { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index ac614494355a..35e0e494771b 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { 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 + *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata }); ReachableContext { tcx: tcx, diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs index 0764e817f430..7f89461a3f4b 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/recursion_limit.rs @@ -25,7 +25,7 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) { } if let Some(s) = attr.value_str() { - if let Some(n) = s.parse().ok() { + if let Some(n) = s.as_str().parse().ok() { sess.recursion_limit.set(n); return; } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 5f9a6b283c6a..0dbde2d21caf 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -805,7 +805,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &hir::Expr) { terminating(then.id); } - hir::ExprLoop(ref body, _) => { + hir::ExprLoop(ref body, _, _) => { terminating(body.id); } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f682dfbf1be9..41da5562e23f 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -27,7 +27,7 @@ use middle::region; use ty; use std::mem::replace; use syntax::ast; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use syntax_pos::Span; use util::nodemap::NodeMap; @@ -462,7 +462,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) { fn expression_label(ex: &hir::Expr) -> Option<(ast::Name, Span)> { match ex.node { hir::ExprWhile(.., Some(label)) | - hir::ExprLoop(_, Some(label)) => Some((label.node, label.span)), + hir::ExprLoop(_, Some(label), _) => Some((label.node, label.span)), _ => None, } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7e4efc7ddca0..86a89eff3a47 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -21,7 +21,7 @@ use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE}; use ty::{self, TyCtxt, AdtKind}; use middle::privacy::AccessLevels; -use syntax::parse::token::InternedString; +use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; use syntax::ast; use syntax::ast::{NodeId, Attribute}; @@ -36,7 +36,6 @@ use hir::pat_util::EnumerateAndAdjustIterator; use std::mem::replace; use std::cmp::Ordering; -use std::ops::Deref; #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)] pub enum StabilityLevel { @@ -151,10 +150,11 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { // Check if deprecated_since < stable_since. If it is, // this is *almost surely* an accident. - if let (&Some(attr::RustcDeprecation {since: ref dep_since, ..}), - &attr::Stable {since: ref stab_since}) = (&stab.rustc_depr, &stab.level) { + if let (&Some(attr::RustcDeprecation {since: dep_since, ..}), + &attr::Stable {since: stab_since}) = (&stab.rustc_depr, &stab.level) { // Explicit version of iter::order::lt to handle parse errors properly - for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) { + for (dep_v, stab_v) in + dep_since.as_str().split(".").zip(stab_since.as_str().split(".")) { if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), stab_v.parse()) { match dep_v.cmp(&stab_v) { Ordering::Less => { @@ -356,7 +356,7 @@ impl<'a, 'tcx> Index<'tcx> { /// features and possibly prints errors. Returns a list of all /// features used. pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> FxHashMap { + -> FxHashMap { let _task = tcx.dep_graph.in_task(DepNode::StabilityCheck); let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features; @@ -376,8 +376,8 @@ pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) struct Checker<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - active_features: FxHashSet, - used_features: FxHashMap, + active_features: FxHashSet, + used_features: FxHashMap, // Within a block where feature gate checking can be skipped. in_skip_block: u32, } @@ -407,10 +407,10 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { if !self.active_features.contains(feature) { let msg = match *reason { Some(ref r) => format!("use of unstable library feature '{}': {}", - &feature, &r), + &feature.as_str(), &r), None => format!("use of unstable library feature '{}'", &feature) }; - emit_feature_err(&self.tcx.sess.parse_sess, &feature, span, + emit_feature_err(&self.tcx.sess.parse_sess, &feature.as_str(), span, GateIssue::Library(Some(issue)), &msg); } } @@ -455,7 +455,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // When compiling with --test we don't enforce stability on the // compiler-generated test module, demarcated with `DUMMY_SP` plus the // name `__test` - if item.span == DUMMY_SP && item.name.as_str() == "__test" { return } + if item.span == DUMMY_SP && item.name == "__test" { return } check_item(self.tcx, item, true, &mut |id, sp, stab, depr| self.check(id, sp, stab, depr)); @@ -735,10 +735,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features(sess: &Session, - lib_features_used: &FxHashMap) { let ref declared_lib_features = sess.features.borrow().declared_lib_features; - let mut remaining_lib_features: FxHashMap + let mut remaining_lib_features: FxHashMap = declared_lib_features.clone().into_iter().collect(); fn format_stable_since_msg(version: &str) -> String { @@ -746,7 +746,7 @@ pub fn check_unused_or_stable_features(sess: &Session, } for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { - let version = find_lang_feature_accepted_version(stable_lang_feature.deref()) + let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) .expect("unexpectedly couldn't find version feature was stabilized"); sess.add_lint(lint::builtin::STABLE_FEATURES, ast::CRATE_NODE_ID, @@ -761,7 +761,7 @@ pub fn check_unused_or_stable_features(sess: &Session, sess.add_lint(lint::builtin::STABLE_FEATURES, ast::CRATE_NODE_ID, span, - format_stable_since_msg(version.deref())); + format_stable_since_msg(&version.as_str())); } } None => ( /* used but undeclared, handled during the previous ast visit */ ) diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 12d32bf31b13..30690c099194 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -16,7 +16,7 @@ use middle::lang_items; use rustc_back::PanicStrategy; use syntax::ast; -use syntax::parse::token::InternedString; +use syntax::symbol::Symbol; use syntax_pos::Span; use hir::intravisit::Visitor; use hir::intravisit; @@ -55,10 +55,10 @@ pub fn check_crate(krate: &hir::Crate, verify(sess, items); } -pub fn link_name(attrs: &[ast::Attribute]) -> Option { +pub fn link_name(attrs: &[ast::Attribute]) -> Option { lang_items::extract(attrs).and_then(|name| { - $(if &name[..] == stringify!($name) { - Some(InternedString::new(stringify!($sym))) + $(if name == stringify!($name) { + Some(Symbol::intern(stringify!($sym))) } else)* { None } @@ -75,7 +75,8 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { config::CrateTypeCdylib | config::CrateTypeExecutable | config::CrateTypeStaticlib => true, - config::CrateTypeRlib => false, + config::CrateTypeRlib | + config::CrateTypeMetadata => false, } }); if !needs_check { @@ -126,7 +127,7 @@ impl<'a> Context<'a> { impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_foreign_item(&mut self, i: &hir::ForeignItem) { if let Some(lang_item) = lang_items::extract(&i.attrs) { - self.register(&lang_item, i.span); + self.register(&lang_item.as_str(), i.span); } intravisit::walk_foreign_item(self, i) } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 16522a73f56a..f3677b808195 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -25,9 +25,8 @@ use lint; use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; -use syntax::attr; use syntax::parse; -use syntax::parse::token::InternedString; +use syntax::symbol::Symbol; use syntax::feature_gate::UnstableFeatures; use errors::{ColorConfig, FatalError, Handler}; @@ -41,6 +40,7 @@ use std::collections::btree_map::Values as BTreeMapValuesIter; use std::fmt; use std::hash::Hasher; use std::collections::hash_map::DefaultHasher; +use std::collections::HashSet; use std::iter::FromIterator; use std::path::PathBuf; @@ -78,18 +78,6 @@ pub enum OutputType { DepInfo, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum ErrorOutputType { - HumanReadable(ColorConfig), - Json, -} - -impl Default for ErrorOutputType { - fn default() -> ErrorOutputType { - ErrorOutputType::HumanReadable(ColorConfig::Auto) - } -} - impl OutputType { fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { match *self { @@ -125,6 +113,18 @@ impl OutputType { } } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ErrorOutputType { + HumanReadable(ColorConfig), + Json, +} + +impl Default for ErrorOutputType { + fn default() -> ErrorOutputType { + ErrorOutputType::HumanReadable(ColorConfig::Auto) + } +} + // Use tree-based collections to cheaply get a deterministic Hash implementation. // DO NOT switch BTreeMap out for an unsorted container type! That would break // dependency tracking for commandline arguments. @@ -483,6 +483,7 @@ pub enum CrateType { CrateTypeStaticlib, CrateTypeCdylib, CrateTypeProcMacro, + CrateTypeMetadata, } #[derive(Clone, Hash)] @@ -927,8 +928,6 @@ pub fn default_lib_output() -> CrateType { } pub fn default_configuration(sess: &Session) -> ast::CrateConfig { - use syntax::parse::token::intern_and_get_ident as intern; - let end = &sess.target.target.target_endian; let arch = &sess.target.target.arch; let wordsz = &sess.target.target.target_pointer_width; @@ -938,55 +937,46 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let max_atomic_width = sess.target.target.max_atomic_width(); let fam = if let Some(ref fam) = sess.target.target.options.target_family { - intern(fam) + Symbol::intern(fam) } else if sess.target.target.options.is_like_windows { - InternedString::new("windows") + Symbol::intern("windows") } else { - InternedString::new("unix") + Symbol::intern("unix") }; - let mk = attr::mk_name_value_item_str; - let mut ret = vec![ // Target bindings. - mk(InternedString::new("target_os"), intern(os)), - mk(InternedString::new("target_family"), fam.clone()), - mk(InternedString::new("target_arch"), intern(arch)), - mk(InternedString::new("target_endian"), intern(end)), - mk(InternedString::new("target_pointer_width"), intern(wordsz)), - mk(InternedString::new("target_env"), intern(env)), - mk(InternedString::new("target_vendor"), intern(vendor)), - ]; - match &fam[..] { - "windows" | "unix" => ret.push(attr::mk_word_item(fam)), - _ => (), + let mut ret = HashSet::new(); + // Target bindings. + ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os)))); + ret.insert((Symbol::intern("target_family"), Some(fam))); + ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch)))); + ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end)))); + ret.insert((Symbol::intern("target_pointer_width"), Some(Symbol::intern(wordsz)))); + ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env)))); + ret.insert((Symbol::intern("target_vendor"), Some(Symbol::intern(vendor)))); + if fam == "windows" || fam == "unix" { + ret.insert((fam, None)); } if sess.target.target.options.has_elf_tls { - ret.push(attr::mk_word_item(InternedString::new("target_thread_local"))); + ret.insert((Symbol::intern("target_thread_local"), None)); } for &i in &[8, 16, 32, 64, 128] { if i <= max_atomic_width { let s = i.to_string(); - ret.push(mk(InternedString::new("target_has_atomic"), intern(&s))); + ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s)))); if &s == wordsz { - ret.push(mk(InternedString::new("target_has_atomic"), intern("ptr"))); + ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern("ptr")))); } } } if sess.opts.debug_assertions { - ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); + ret.insert((Symbol::intern("debug_assertions"), None)); } if sess.opts.crate_types.contains(&CrateTypeProcMacro) { - ret.push(attr::mk_word_item(InternedString::new("proc_macro"))); + ret.insert((Symbol::intern("proc_macro"), None)); } return ret; } -pub fn append_configuration(cfg: &mut ast::CrateConfig, - name: InternedString) { - if !cfg.iter().any(|mi| mi.name() == name) { - cfg.push(attr::mk_word_item(name)) - } -} - pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig { @@ -995,11 +985,10 @@ pub fn build_configuration(sess: &Session, let default_cfg = default_configuration(sess); // If the user wants a test runner, then add the test cfg if sess.opts.test { - append_configuration(&mut user_cfg, InternedString::new("test")) + user_cfg.insert((Symbol::intern("test"), None)); } - let mut v = user_cfg.into_iter().collect::>(); - v.extend_from_slice(&default_cfg[..]); - v + user_cfg.extend(default_cfg.iter().cloned()); + user_cfg } pub fn build_target_config(opts: &Options, sp: &Handler) -> Config { @@ -1159,7 +1148,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|metadata]"), 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 \ @@ -1245,11 +1234,14 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { let meta_item = panictry!(parser.parse_meta_item()); if !parser.reader.is_eof() { - early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", - s)) + early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", s)) + } else if meta_item.is_meta_item_list() { + let msg = + format!("invalid predicate in --cfg command line argument: `{}`", meta_item.name()); + early_error(ErrorOutputType::default(), &msg) } - meta_item + (meta_item.name(), meta_item.value_str()) }).collect::() } @@ -1548,6 +1540,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateTypeCdylib, "bin" => CrateTypeExecutable, "proc-macro" => CrateTypeProcMacro, + "metadata" => CrateTypeMetadata, _ => { return Err(format!("unknown crate type: `{}`", part)); @@ -1632,6 +1625,7 @@ impl fmt::Display for CrateType { CrateTypeStaticlib => "staticlib".fmt(f), CrateTypeCdylib => "cdylib".fmt(f), CrateTypeProcMacro => "proc-macro".fmt(f), + CrateTypeMetadata => "metadata".fmt(f), } } } @@ -1773,9 +1767,7 @@ mod tests { use std::rc::Rc; use super::{OutputType, OutputTypes, Externs}; use rustc_back::PanicStrategy; - use syntax::{ast, attr}; - use syntax::parse::token::InternedString; - use syntax::codemap::dummy_spanned; + use syntax::symbol::Symbol; fn optgroups() -> Vec { super::rustc_optgroups().into_iter() @@ -1804,9 +1796,7 @@ mod tests { let (sessopts, cfg) = build_session_options_and_crate_config(matches); let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore)); let cfg = build_configuration(&sess, cfg); - assert!(attr::contains(&cfg, &dummy_spanned(ast::MetaItemKind::Word({ - InternedString::new("test") - })))); + assert!(cfg.contains(&(Symbol::intern("test"), None))); } // When the user supplies --test and --cfg test, don't implicitly add @@ -1827,7 +1817,7 @@ mod tests { let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore)); let cfg = build_configuration(&sess, cfg); - let mut test_items = cfg.iter().filter(|m| m.name() == "test"); + let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test"); assert!(test_items.next().is_some()); assert!(test_items.next().is_none()); } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 9becbd99eb33..9577a25b3f83 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -28,7 +28,7 @@ use syntax::json::JsonEmitter; use syntax::feature_gate; use syntax::parse; use syntax::parse::ParseSess; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; use syntax_pos::{Span, MultiSpan}; @@ -89,7 +89,7 @@ pub struct Session { // forms a unique global identifier for the crate. It is used to allow // multiple crates with the same name to coexist. See the // trans::back::symbol_names module for more information. - pub crate_disambiguator: RefCell, + pub crate_disambiguator: RefCell, pub features: RefCell, /// The maximum recursion limit for potentially infinitely recursive @@ -129,8 +129,8 @@ pub struct PerfStats { } impl Session { - pub fn local_crate_disambiguator(&self) -> token::InternedString { - self.crate_disambiguator.borrow().clone() + pub fn local_crate_disambiguator(&self) -> Symbol { + *self.crate_disambiguator.borrow() } pub fn struct_span_warn<'a, S: Into>(&'a self, sp: S, @@ -610,7 +610,7 @@ pub fn build_session_(sopts: config::Options, plugin_attributes: RefCell::new(Vec::new()), crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FxHashMap()), - crate_disambiguator: RefCell::new(token::intern("").as_str()), + crate_disambiguator: RefCell::new(Symbol::intern("")), features: RefCell::new(feature_gate::Features::new()), recursion_limit: Cell::new(64), next_node_id: Cell::new(NodeId::new(1)), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e0a397ad28fb..21009711cb18 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -246,12 +246,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let err_sp = item.meta().span.substitute_dummy(span); let def = self.tcx.lookup_trait_def(trait_ref.def_id); let trait_str = def.trait_ref.to_string(); - if let Some(ref istring) = item.value_str() { + if let Some(istring) = item.value_str() { + let istring = &*istring.as_str(); let generic_map = def.generics.types.iter().map(|param| { (param.name.as_str().to_string(), trait_ref.substs.type_for_def(param).to_string()) }).collect::>(); - let parser = Parser::new(&istring); + let parser = Parser::new(istring); let mut errored = false; let err: String = parser.filter_map(|p| { match p { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a2d45fa27149..76bead99343a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -26,8 +26,8 @@ use super::util; use hir::def_id::DefId; use infer::InferOk; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; -use syntax::parse::token; use syntax::ast; +use syntax::symbol::Symbol; use ty::subst::Subst; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder}; @@ -1245,7 +1245,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here projection_ty: ty::ProjectionTy { trait_ref: trait_ref, - item_name: token::intern(FN_OUTPUT_NAME), + item_name: Symbol::intern(FN_OUTPUT_NAME), }, ty: ret_type }); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 45450456e8a6..20855c46b680 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -49,7 +49,7 @@ use std::rc::Rc; use std::iter; use syntax::ast::{self, Name, NodeId}; use syntax::attr; -use syntax::parse::token::{self, keywords}; +use syntax::symbol::{Symbol, keywords}; use hir; @@ -561,7 +561,7 @@ pub struct GlobalCtxt<'tcx> { /// The definite name of the current crate after taking into account /// attributes, commandline parameters, etc. - pub crate_name: token::InternedString, + pub crate_name: Symbol, /// Data layout specification for the current target. pub data_layout: TargetDataLayout, @@ -574,7 +574,7 @@ pub struct GlobalCtxt<'tcx> { /// Map from function to the `#[derive]` mode that it's defining. Only used /// by `proc-macro` crates. - pub derive_macros: RefCell>, + pub derive_macros: RefCell>, } impl<'tcx> GlobalCtxt<'tcx> { @@ -588,15 +588,15 @@ impl<'tcx> GlobalCtxt<'tcx> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn crate_name(self, cnum: CrateNum) -> token::InternedString { + pub fn crate_name(self, cnum: CrateNum) -> Symbol { if cnum == LOCAL_CRATE { - self.crate_name.clone() + self.crate_name } else { self.sess.cstore.crate_name(cnum) } } - pub fn original_crate_name(self, cnum: CrateNum) -> token::InternedString { + pub fn original_crate_name(self, cnum: CrateNum) -> Symbol { if cnum == LOCAL_CRATE { self.crate_name.clone() } else { @@ -604,7 +604,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn crate_disambiguator(self, cnum: CrateNum) -> token::InternedString { + pub fn crate_disambiguator(self, cnum: CrateNum) -> Symbol { if cnum == LOCAL_CRATE { self.sess.local_crate_disambiguator() } else { @@ -835,7 +835,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), cast_kinds: RefCell::new(NodeMap()), fragment_infos: RefCell::new(DefIdMap()), - crate_name: token::intern_and_get_ident(crate_name), + crate_name: Symbol::intern(crate_name), data_layout: data_layout, layout_cache: RefCell::new(FxHashMap()), layout_depth: Cell::new(0), diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 8222583d9a7d..b93a8698f603 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -12,7 +12,7 @@ use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; use syntax::ast; -use syntax::parse::token; +use syntax::symbol::Symbol; use std::cell::Cell; @@ -94,14 +94,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(extern_crate_def_id) = opt_extern_crate { self.push_item_path(buffer, extern_crate_def_id); } else { - buffer.push(&self.crate_name(cnum)); + buffer.push(&self.crate_name(cnum).as_str()); } } } RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. - buffer.push(&self.original_crate_name(cnum)); + buffer.push(&self.original_crate_name(cnum).as_str()); } } } @@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { return true; } None => { - buffer.push(&self.crate_name(cur_def.krate)); + buffer.push(&self.crate_name(cur_def.krate).as_str()); cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count(); return true; } @@ -136,7 +136,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { cur_path.push(self.sess.cstore.def_key(cur_def) .disambiguated_data.data.get_opt_name().unwrap_or_else(|| - token::intern(""))); + Symbol::intern(""))); match visible_parent_map.get(&cur_def) { Some(&def) => cur_def = def, None => return false, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f5c23401a4e6..e94e93158c47 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -44,7 +44,7 @@ use std::vec::IntoIter; use std::mem; use syntax::ast::{self, Name, NodeId}; use syntax::attr; -use syntax::parse::token::{self, InternedString}; +use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_const_math::ConstInt; @@ -2344,7 +2344,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(id) = self.map.as_local_node_id(id) { self.map.name(id) } else if id.index == CRATE_DEF_INDEX { - token::intern(&self.sess.cstore.original_crate_name(id.krate)) + self.sess.cstore.original_crate_name(id.krate) } else { let def_key = self.sess.cstore.def_key(id); // The name of a StructCtor is that of its struct parent. @@ -2747,7 +2747,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. - pub fn span_of_impl(self, impl_did: DefId) -> Result { + pub fn span_of_impl(self, impl_did: DefId) -> Result { if impl_did.is_local() { let node_id = self.map.as_local_node_id(impl_did).unwrap(); Ok(self.map.span(node_id)) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 56466d596829..81896ecfb534 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -23,7 +23,7 @@ use std::fmt; use std::ops; use syntax::abi; use syntax::ast::{self, Name}; -use syntax::parse::token::{keywords, InternedString}; +use syntax::symbol::{keywords, InternedString}; use serialize; diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 7cd5fd78df52..e01856b2a476 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -19,10 +19,6 @@ use std::iter::repeat; use std::path::Path; use std::time::{Duration, Instant}; -use hir; -use hir::intravisit; -use hir::intravisit::Visitor; - // The name of the associated type for `Fn` return types pub const FN_OUTPUT_NAME: &'static str = "Output"; @@ -186,57 +182,6 @@ pub fn indenter() -> Indenter { Indenter { _cannot_construct_outside_of_this_module: () } } -struct LoopQueryVisitor

where P: FnMut(&hir::Expr_) -> bool { - p: P, - flag: bool, -} - -impl<'v, P> Visitor<'v> for LoopQueryVisitor

where P: FnMut(&hir::Expr_) -> bool { - fn visit_expr(&mut self, e: &hir::Expr) { - self.flag |= (self.p)(&e.node); - match e.node { - // Skip inner loops, since a break in the inner loop isn't a - // break inside the outer loop - hir::ExprLoop(..) | hir::ExprWhile(..) => {} - _ => intravisit::walk_expr(self, e) - } - } -} - -// Takes a predicate p, returns true iff p is true for any subexpressions -// of b -- skipping any inner loops (loop, while, loop_body) -pub fn loop_query

(b: &hir::Block, p: P) -> bool where P: FnMut(&hir::Expr_) -> bool { - let mut v = LoopQueryVisitor { - p: p, - flag: false, - }; - intravisit::walk_block(&mut v, b); - return v.flag; -} - -struct BlockQueryVisitor

where P: FnMut(&hir::Expr) -> bool { - p: P, - flag: bool, -} - -impl<'v, P> Visitor<'v> for BlockQueryVisitor

where P: FnMut(&hir::Expr) -> bool { - fn visit_expr(&mut self, e: &hir::Expr) { - self.flag |= (self.p)(e); - intravisit::walk_expr(self, e) - } -} - -// Takes a predicate p, returns true iff p is true for any subexpressions -// of b -- skipping any inner loops (loop, while, loop_body) -pub fn block_query

(b: &hir::Block, p: P) -> bool where P: FnMut(&hir::Expr) -> bool { - let mut v = BlockQueryVisitor { - p: p, - flag: false, - }; - intravisit::walk_block(&mut v, &b); - return v.flag; -} - pub trait MemoizationMap { type Key: Clone; type Value: Clone; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a63c7ba6a25c..d04825d56044 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -25,8 +25,8 @@ use std::fmt; use std::usize; use syntax::abi::Abi; -use syntax::parse::token; use syntax::ast::CRATE_NODE_ID; +use syntax::symbol::Symbol; use hir; pub fn verbose() -> bool { @@ -284,7 +284,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, ty::BrAnon(_) | ty::BrFresh(_) | ty::BrEnv => { - let name = token::intern("'r"); + let name = Symbol::intern("'r"); let _ = write!(f, "{}", name); ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID), name, diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs index b8c26a0512ff..916d17dcc91d 100644 --- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs +++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs @@ -169,7 +169,7 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { - if name.as_str() == "rustc_peek" { + if name == "rustc_peek" { return Some((args, source_info.span)); } } diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs index 836832de5b9c..9035c2ab3c23 100644 --- a/src/librustc_borrowck/borrowck/mir/mod.rs +++ b/src/librustc_borrowck/borrowck/mir/mod.rs @@ -11,7 +11,6 @@ use borrowck::BorrowckCtxt; use syntax::ast::{self, MetaItem}; -use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir; @@ -35,7 +34,7 @@ use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; use self::dataflow::{DefinitelyInitializedLvals}; use self::gather_moves::{MoveData, MovePathIndex, LookupResult}; -fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option> { +fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option { for attr in attrs { if attr.check_name("rustc_mir") { let items = attr.meta_item_list(); diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 5f0c94744a11..b594fe9853a4 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -297,7 +297,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => bug!() }; let pats = args.iter() - .map(|expr| const_expr_to_pat(tcx, &**expr, pat_id, span)) + .map(|expr| const_expr_to_pat(tcx, &*expr, pat_id, span)) .collect::>()?; PatKind::TupleStruct(path, pats, None) } @@ -1221,7 +1221,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind, use syntax::ast::*; use syntax::ast::LitIntType::*; match *lit { - LitKind::Str(ref s, _) => Ok(Str((*s).clone())), + LitKind::Str(ref s, _) => Ok(Str(s.as_str())), LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())), LitKind::Byte(n) => Ok(Integral(U8(n))), LitKind::Int(n, Signed(ity)) => { @@ -1249,15 +1249,15 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind, infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral) }, - LitKind::Float(ref n, fty) => { - parse_float(n, Some(fty)).map(Float) + LitKind::Float(n, fty) => { + parse_float(&n.as_str(), Some(fty)).map(Float) } - LitKind::FloatUnsuffixed(ref n) => { + LitKind::FloatUnsuffixed(n) => { let fty_hint = match ty_hint.map(|t| &t.sty) { Some(&ty::TyFloat(fty)) => Some(fty), _ => None }; - parse_float(n, fty_hint).map(Float) + parse_float(&n.as_str(), fty_hint).map(Float) } LitKind::Bool(b) => Ok(Bool(b)), LitKind::Char(c) => Ok(Char(c)), diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index 1f4d09a92247..e2d3a4f45374 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -344,7 +344,7 @@ impl<'tcx, K, V> UnificationTable } pub fn probe(&mut self, a_id: K) -> Option { - self.get(a_id).value.clone() + self.get(a_id).value } pub fn unsolved_variables(&mut self) -> Vec { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6a3a1bbb55ca..5cbb8f93fc9d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -53,7 +53,8 @@ use std::path::{Path, PathBuf}; use syntax::{ast, diagnostics, visit}; use syntax::attr; use syntax::ext::base::ExtCtxt; -use syntax::parse::{self, PResult, token}; +use syntax::parse::{self, PResult}; +use syntax::symbol::Symbol; use syntax::util::node_count::NodeCounter; use syntax; use syntax_ext; @@ -210,9 +211,6 @@ pub fn compile_input(sess: &Session, tcx.print_debug_stats(); } - // Discard interned strings as they are no longer required. - token::clear_ident_interner(); - Ok((outputs, trans)) })?? }; @@ -563,8 +561,7 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, *sess.features.borrow_mut() = features; *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); - *sess.crate_disambiguator.borrow_mut() = - token::intern(&compute_crate_disambiguator(sess)).as_str(); + *sess.crate_disambiguator.borrow_mut() = Symbol::intern(&compute_crate_disambiguator(sess)); time(time_passes, "recursion limit", || { middle::recursion_limit::update_recursion_limit(sess, &krate); @@ -858,7 +855,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, time(time_passes, "loop checking", - || loops::check_crate(sess, &hir_map)); + || loops::check_crate(sess, &resolutions.def_map, &hir_map)); time(time_passes, "static item recursion checking", @@ -1107,7 +1104,7 @@ pub fn phase_6_link_output(sess: &Session, outputs: &OutputFilenames) { time(sess.time_passes(), "linking", - || link::link_binary(sess, trans, outputs, &trans.link.crate_name)); + || link::link_binary(sess, trans, outputs, &trans.link.crate_name.as_str())); } fn escape_dep_filename(filename: &str) -> String { @@ -1185,6 +1182,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { Some(config::CrateTypeRlib) } + Some(ref n) if *n == "metadata" => { + Some(config::CrateTypeMetadata) + } Some(ref n) if *n == "dylib" => { Some(config::CrateTypeDylib) } @@ -1358,11 +1358,3 @@ pub fn build_output_filenames(input: &Input, } } } - -// For use by the `rusti` project (https://github.com/murarth/rusti). -pub fn reset_thread_local_state() { - // These may be left in an incoherent state after a previous compile. - syntax::ext::hygiene::reset_hygiene_data(); - // `clear_ident_interner` can be used to free memory, but it does not restore the initial state. - token::reset_ident_interner(); -} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 7e60c40220f8..a0863e0d2942 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -95,12 +95,11 @@ use std::str; use std::sync::{Arc, Mutex}; use std::thread; -use syntax::{ast, json}; +use syntax::ast; use syntax::codemap::{CodeMap, FileLoader, RealFileLoader}; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; -use syntax_pos::MultiSpan; -use errors::emitter::Emitter; +use syntax_pos::{DUMMY_SP, MultiSpan}; #[cfg(test)] pub mod test; @@ -374,37 +373,11 @@ fn handle_explain(code: &str, } } -fn check_cfg(cfg: &ast::CrateConfig, - output: ErrorOutputType) { - let emitter: Box = match output { - config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(errors::emitter::EmitterWriter::stderr(color_config, None)) - } - config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()), - }; - let handler = errors::Handler::with_emitter(true, false, emitter); - - let mut saw_invalid_predicate = false; - for item in cfg.iter() { - if item.is_meta_item_list() { - saw_invalid_predicate = true; - handler.emit(&MultiSpan::new(), - &format!("invalid predicate in --cfg command line argument: `{}`", - item.name()), - errors::Level::Fatal); - } - } - - if saw_invalid_predicate { - panic!(errors::FatalError); - } -} - impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, _: &config::Options, - cfg: &ast::CrateConfig, + _: &ast::CrateConfig, descriptions: &errors::registry::Registry, output: ErrorOutputType) -> Compilation { @@ -413,7 +386,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { return Compilation::Stop; } - check_cfg(cfg, output); Compilation::Continue } @@ -640,24 +612,27 @@ impl RustcDefaultCalls { let allow_unstable_cfg = UnstableFeatures::from_environment() .is_nightly_build(); - for cfg in &sess.parse_sess.config { - if !allow_unstable_cfg && GatedCfg::gate(cfg).is_some() { + let mut cfgs = Vec::new(); + for &(name, ref value) in sess.parse_sess.config.iter() { + let gated_cfg = GatedCfg::gate(&ast::MetaItem { + name: name, + node: ast::MetaItemKind::Word, + span: DUMMY_SP, + }); + if !allow_unstable_cfg && gated_cfg.is_some() { continue; } - if cfg.is_word() { - println!("{}", cfg.name()); - } else if let Some(s) = cfg.value_str() { - println!("{}=\"{}\"", cfg.name(), s); - } else if cfg.is_meta_item_list() { - // Right now there are not and should not be any - // MetaItemKind::List items in the configuration returned by - // `build_configuration`. - panic!("Found an unexpected list in cfg attribute '{}'!", cfg.name()) + cfgs.push(if let &Some(ref value) = value { + format!("{}=\"{}\"", name, value) } else { - // There also shouldn't be literals. - panic!("Found an unexpected literal in cfg attribute '{}'!", cfg.name()) - } + format!("{}", name) + }); + } + + cfgs.sort(); + for cfg in cfgs { + println!("{}", cfg); } } PrintRequest::TargetCPUs => { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index ecbf28c1082f..6c99c9d71b81 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -450,15 +450,15 @@ impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> { impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { match node { - pprust::NodeIdent(&ast::Ident { name: ast::Name(nm), ctxt }) => { + pprust::NodeIdent(&ast::Ident { name, ctxt }) => { pp::space(&mut s.s)?; // FIXME #16420: this doesn't display the connections // between syntax contexts - s.synth_comment(format!("{}{:?}", nm, ctxt)) + s.synth_comment(format!("{}{:?}", name.as_u32(), ctxt)) } - pprust::NodeName(&ast::Name(nm)) => { + pprust::NodeName(&name) => { pp::space(&mut s.s)?; - s.synth_comment(nm.to_string()) + s.synth_comment(name.as_u32().to_string()) } _ => Ok(()), } diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index 57a9edc5c586..876323d599e8 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -8,13 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::{ast, attr}; +use syntax::ast; use llvm::LLVMRustHasFeature; use rustc::session::Session; use rustc_trans::back::write::create_target_machine; use syntax::feature_gate::UnstableFeatures; -use syntax::parse::token::InternedString; -use syntax::parse::token::intern_and_get_ident as intern; +use syntax::symbol::Symbol; use libc::c_char; // WARNING: the features must be known to LLVM or the feature @@ -41,11 +40,11 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { _ => &[], }; - let tf = InternedString::new("target_feature"); + let tf = Symbol::intern("target_feature"); for feat in whitelist { assert_eq!(feat.chars().last(), Some('\0')); if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } { - cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(&feat[..feat.len() - 1]))) + cfg.insert((tf, Some(Symbol::intern(&feat[..feat.len() - 1])))); } } @@ -74,6 +73,6 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { } if crt_static { - cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static"))); + cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 782c74c8c78c..a4f0e2903847 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -34,8 +34,8 @@ use syntax::codemap::CodeMap; use errors; use errors::emitter::Emitter; use errors::{Level, DiagnosticBuilder}; -use syntax::parse::token; use syntax::feature_gate::UnstableFeatures; +use syntax::symbol::Symbol; use rustc::hir; @@ -288,11 +288,11 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn t_param(&self, index: u32) -> Ty<'tcx> { let name = format!("T{}", index); - self.infcx.tcx.mk_param(index, token::intern(&name[..])) + self.infcx.tcx.mk_param(index, Symbol::intern(&name[..])) } pub fn re_early_bound(&self, index: u32, name: &'static str) -> &'tcx ty::Region { - let name = token::intern(name); + let name = Symbol::intern(name); self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { index: index, name: name, diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 998cbae2cce1..87e6b2befdc3 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -57,7 +57,6 @@ use std::env; use std::fs::File; use std::io::Write; use syntax::ast; -use syntax::parse::token::InternedString; use syntax_pos::Span; use {ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED}; @@ -97,7 +96,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { } type Sources = Vec<(Span, DefId, DepNode)>; -type Targets = Vec<(Span, InternedString, ast::NodeId, DepNode)>; +type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode)>; struct IfThisChanged<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -106,7 +105,7 @@ struct IfThisChanged<'a, 'tcx:'a> { } impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { - fn argument(&self, attr: &ast::Attribute) -> Option { + fn argument(&self, attr: &ast::Attribute) -> Option { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { match list_item.word() { @@ -127,8 +126,8 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { None => DepNode::Hir(def_id), - Some(ref n) => { - match DepNode::from_label_string(&n[..], def_id) { + Some(n) => { + match DepNode::from_label_string(&n.as_str(), def_id) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -142,8 +141,8 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { } else if attr.check_name(ATTR_THEN_THIS_WOULD_NEED) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - Some(ref n) => { - match DepNode::from_label_string(&n[..], def_id) { + Some(n) => { + match DepNode::from_label_string(&n.as_str(), def_id) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -159,7 +158,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { } }; self.then_this_would_need.push((attr.span, - dep_node_interned.clone().unwrap(), + dep_node_interned.unwrap(), node_id, dep_node)); } diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index f98e698a1c9d..250ef061e510 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -172,8 +172,8 @@ impl<'a, 'tcx> HashItemsVisitor<'a, 'tcx> { let crate_disambiguator = self.tcx.sess.local_crate_disambiguator(); "crate_disambiguator".hash(&mut crate_state); - crate_disambiguator.len().hash(&mut crate_state); - crate_disambiguator.hash(&mut crate_state); + crate_disambiguator.as_str().len().hash(&mut crate_state); + crate_disambiguator.as_str().hash(&mut crate_state); // add each item (in some deterministic order) to the overall // crate hash. diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index a1ece48462b1..fd0856393fc1 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -18,6 +18,7 @@ use syntax::abi::Abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::parse::token; +use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; use syntax::tokenstream; use rustc::hir; @@ -169,8 +170,8 @@ enum SawAbiComponent<'a> { // FIXME (#14132): should we include (some function of) // ident.ctxt as well? - SawIdent(token::InternedString), - SawStructDef(token::InternedString), + SawIdent(InternedString), + SawStructDef(InternedString), SawLifetime, SawLifetimeDef(usize), @@ -232,11 +233,11 @@ enum SawAbiComponent<'a> { #[derive(Hash)] enum SawExprComponent<'a> { - SawExprLoop(Option), - SawExprField(token::InternedString), + SawExprLoop(Option), + SawExprField(InternedString), SawExprTupField(usize), - SawExprBreak(Option), - SawExprAgain(Option), + SawExprBreak(Option), + SawExprAgain(Option), SawExprBox, SawExprArray, @@ -246,6 +247,8 @@ enum SawExprComponent<'a> { SawExprBinary(hir::BinOp_), SawExprUnary(hir::UnOp), SawExprLit(ast::LitKind), + SawExprLitStr(InternedString, ast::StrStyle), + SawExprLitFloat(InternedString, Option), SawExprCast, SawExprType, SawExprIf, @@ -314,12 +317,12 @@ fn saw_expr<'a>(node: &'a Expr_, ExprUnary(op, _) => { (SawExprUnary(op), unop_can_panic_at_runtime(op)) } - ExprLit(ref lit) => (SawExprLit(lit.node.clone()), false), + ExprLit(ref lit) => (saw_lit(lit), false), ExprCast(..) => (SawExprCast, false), ExprType(..) => (SawExprType, false), ExprIf(..) => (SawExprIf, false), ExprWhile(..) => (SawExprWhile, false), - ExprLoop(_, id) => (SawExprLoop(id.map(|id| id.node.as_str())), false), + ExprLoop(_, id, _) => (SawExprLoop(id.map(|id| id.node.as_str())), false), ExprMatch(..) => (SawExprMatch, false), ExprClosure(cc, _, _, _) => (SawExprClosure(cc), false), ExprBlock(..) => (SawExprBlock, false), @@ -332,7 +335,7 @@ fn saw_expr<'a>(node: &'a Expr_, ExprIndex(..) => (SawExprIndex, true), ExprPath(ref qself, _) => (SawExprPath(qself.as_ref().map(|q| q.position)), false), ExprAddrOf(m, _) => (SawExprAddrOf(m), false), - ExprBreak(id) => (SawExprBreak(id.map(|id| id.node.as_str())), false), + ExprBreak(id, _) => (SawExprBreak(id.map(|id| id.node.as_str())), false), ExprAgain(id) => (SawExprAgain(id.map(|id| id.node.as_str())), false), ExprRet(..) => (SawExprRet, false), ExprInlineAsm(ref a,..) => (SawExprInlineAsm(a), false), @@ -341,6 +344,15 @@ fn saw_expr<'a>(node: &'a Expr_, } } +fn saw_lit(lit: &ast::Lit) -> SawExprComponent<'static> { + match lit.node { + ast::LitKind::Str(s, style) => SawExprLitStr(s.as_str(), style), + ast::LitKind::Float(s, ty) => SawExprLitFloat(s.as_str(), Some(ty)), + ast::LitKind::FloatUnsuffixed(s) => SawExprLitFloat(s.as_str(), None), + ref node @ _ => SawExprLit(node.clone()), + } +} + #[derive(Hash)] enum SawItemComponent { SawItemExternCrate, @@ -874,22 +886,16 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { // ignoring span information, it doesn't matter here self.hash_discriminant(&meta_item.node); + meta_item.name.as_str().len().hash(self.st); + meta_item.name.as_str().hash(self.st); + match meta_item.node { - ast::MetaItemKind::Word(ref s) => { - s.len().hash(self.st); - s.hash(self.st); - } - ast::MetaItemKind::NameValue(ref s, ref lit) => { - s.len().hash(self.st); - s.hash(self.st); - lit.node.hash(self.st); - } - ast::MetaItemKind::List(ref s, ref items) => { - s.len().hash(self.st); - s.hash(self.st); + ast::MetaItemKind::Word => {} + ast::MetaItemKind::NameValue(ref lit) => saw_lit(lit).hash(self.st), + ast::MetaItemKind::List(ref items) => { // Sort subitems so the hash does not depend on their order let indices = self.indices_sorted_by(&items, |p| { - (p.name(), fnv::hash(&p.literal().map(|i| &i.node))) + (p.name().map(Symbol::as_str), fnv::hash(&p.literal().map(saw_lit))) }); items.len().hash(self.st); for (index, &item_index) in indices.iter().enumerate() { @@ -901,7 +907,7 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { self.hash_meta_item(meta_item); } ast::NestedMetaItemKind::Literal(ref lit) => { - lit.node.hash(self.st); + saw_lit(lit).hash(self.st); } } } @@ -914,11 +920,11 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { let indices = self.indices_sorted_by(attributes, |attr| attr.name()); for i in indices { - let attr = &attributes[i].node; + let attr = &attributes[i]; if !attr.is_sugared_doc && - !IGNORED_ATTRIBUTES.contains(&&*attr.value.name()) { + !IGNORED_ATTRIBUTES.contains(&&*attr.value.name().as_str()) { SawAttribute(attr.style).hash(self.st); - self.hash_meta_item(&*attr.value); + self.hash_meta_item(&attr.value); } } } diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs index d238121872be..546feb212243 100644 --- a/src/librustc_incremental/persist/directory.rs +++ b/src/librustc_incremental/persist/directory.rs @@ -84,8 +84,8 @@ impl DefIdDirectory { assert_eq!(old_info.krate, krate); let old_name: &str = &old_info.name; let old_disambiguator: &str = &old_info.disambiguator; - let new_name: &str = &tcx.crate_name(krate); - let new_disambiguator: &str = &tcx.crate_disambiguator(krate); + let new_name: &str = &tcx.crate_name(krate).as_str(); + let new_disambiguator: &str = &tcx.crate_disambiguator(krate).as_str(); old_name == new_name && old_disambiguator == new_disambiguator } } @@ -99,8 +99,8 @@ impl DefIdDirectory { let new_krates: HashMap<_, _> = once(LOCAL_CRATE) .chain(tcx.sess.cstore.crates()) - .map(|krate| (make_key(&tcx.crate_name(krate), - &tcx.crate_disambiguator(krate)), krate)) + .map(|krate| (make_key(&tcx.crate_name(krate).as_str(), + &tcx.crate_disambiguator(krate).as_str()), krate)) .collect(); let ids = self.paths.iter() diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 0cd1c88fb877..85c35bf79ce8 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -48,7 +48,6 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use syntax::ast::{self, Attribute, NestedMetaItem}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use syntax::parse::token::InternedString; use syntax_pos::Span; use rustc::ty::TyCtxt; use ich::Fingerprint; @@ -88,12 +87,11 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> { } impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { - fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode { for item in attr.meta_item_list().unwrap_or(&[]) { if item.check_name(LABEL) { let value = expect_associated_value(self.tcx, item); - match DepNode::from_label_string(&value[..], def_id) { + match DepNode::from_label_string(&value.as_str(), def_id) { Ok(def_id) => return def_id, Err(()) => { self.tcx.sess.span_fatal( @@ -276,13 +274,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool { if item.check_name(CFG) { let value = expect_associated_value(tcx, item); debug!("check_config: searching for cfg {:?}", value); - for cfg in &config[..] { - if cfg.check_name(&value[..]) { - debug!("check_config: matched {:?}", cfg); - return true; - } - } - return false; + return config.contains(&(value, None)); } } @@ -291,7 +283,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool { &format!("no cfg attribute")); } -fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> InternedString { +fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name { if let Some(value) = item.value_str() { value } else { diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 2572a9c1d78f..26181dbaf50f 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -604,7 +604,7 @@ fn string_to_timestamp(s: &str) -> Result { } fn crate_path_tcx(tcx: TyCtxt, cnum: CrateNum) -> PathBuf { - crate_path(tcx.sess, &tcx.crate_name(cnum), &tcx.crate_disambiguator(cnum)) + crate_path(tcx.sess, &tcx.crate_name(cnum).as_str(), &tcx.crate_disambiguator(cnum).as_str()) } /// Finds the session directory containing the correct metadata hashes file for diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index 6320a923d690..4440cb41dc5f 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -81,19 +81,12 @@ impl NonCamelCaseTypes { .concat() } - let s = name.as_str(); - if !is_camel_case(name) { - let c = to_camel_case(&s); + let c = to_camel_case(&name.as_str()); let m = if c.is_empty() { - format!("{} `{}` should have a camel case name such as `CamelCase`", - sort, - s) + format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name) } else { - format!("{} `{}` should have a camel case name such as `{}`", - sort, - s, - c) + format!("{} `{}` should have a camel case name such as `{}`", sort, name, c) }; cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]); } @@ -241,8 +234,8 @@ impl LateLintPass for NonSnakeCase { .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { self.check_snake_case(cx, "crate", name, None); - } else if let Some((attr, ref name)) = attr_crate_name { - self.check_snake_case(cx, "crate", name, Some(attr.span)); + } else if let Some((attr, name)) = attr_crate_name { + self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span)); } } @@ -326,21 +319,19 @@ pub struct NonUpperCaseGlobals; impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) { - let s = name.as_str(); - - if s.chars().any(|c| c.is_lowercase()) { - let uc = NonSnakeCase::to_snake_case(&s).to_uppercase(); - if uc != &s[..] { + if name.as_str().chars().any(|c| c.is_lowercase()) { + let uc = NonSnakeCase::to_snake_case(&name.as_str()).to_uppercase(); + if name != &*uc { cx.span_lint(NON_UPPER_CASE_GLOBALS, span, &format!("{} `{}` should have an upper case name such as `{}`", sort, - s, + name, uc)); } else { cx.span_lint(NON_UPPER_CASE_GLOBALS, span, - &format!("{} `{}` should have an upper case name", sort, s)); + &format!("{} `{}` should have an upper case name", sort, name)); } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 51ffb1ebc8e9..0b2ae5885230 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -45,6 +45,7 @@ use std::collections::HashSet; use syntax::ast; use syntax::attr; use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes}; +use syntax::symbol::Symbol; use syntax_pos::Span; use rustc::hir::{self, PatKind}; @@ -633,9 +634,9 @@ impl Deprecated { stability: &Option<&attr::Stability>, deprecation: &Option) { // Deprecated attributes apply in-crate and cross-crate. - if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{ref reason, ..}), ..}) + if let Some(&attr::Stability{rustc_depr: Some(attr::RustcDeprecation{reason, ..}), ..}) = *stability { - output(cx, DEPRECATED, span, Some(&reason)) + output(cx, DEPRECATED, span, Some(reason)) } else if let Some(ref depr_entry) = *deprecation { if let Some(parent_depr) = cx.tcx.lookup_deprecation_entry(self.parent_def(cx)) { if parent_depr.same_origin(depr_entry) { @@ -643,10 +644,10 @@ impl Deprecated { } } - output(cx, DEPRECATED, span, depr_entry.attr.note.as_ref().map(|x| &**x)) + output(cx, DEPRECATED, span, depr_entry.attr.note) } - fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option<&str>) { + fn output(cx: &LateContext, lint: &'static Lint, span: Span, note: Option) { let msg = if let Some(note) = note { format!("use of deprecated item: {}", note) } else { @@ -772,9 +773,9 @@ impl LintPass for DeprecatedAttr { impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { - let name = &*attr.name(); + let name = attr.name(); for &&(n, _, ref g) in &self.depr_attrs { - if n == name { + if name == n { if let &AttributeGate::Gated(Stability::Deprecated(link), ref name, ref reason, @@ -1228,7 +1229,7 @@ impl LateLintPass for MutableTransmutes { ty::TyFnDef(.., ref bfty) if bfty.abi == RustIntrinsic => (), _ => return false, } - cx.tcx.item_name(def_id).as_str() == "transmute" + cx.tcx.item_name(def_id) == "transmute" } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 114c0ea556ef..1a3ea5db871e 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -232,6 +232,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { id: LintId::of(EXTRA_REQUIREMENT_IN_IMPL), reference: "issue #37166 ", }, + FutureIncompatibleInfo { + id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP), + reference: "issue #37872 ", + }, ]); // Register renamed and removed lints diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4155d3e67a26..8aa5e9e0a946 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -219,9 +219,9 @@ impl LateLintPass for TypeLimits { ty::TyFloat(t) => { let (min, max) = float_ty_range(t); let lit_val: f64 = match lit.node { - ast::LitKind::Float(ref v, _) | - ast::LitKind::FloatUnsuffixed(ref v) => { - match v.parse() { + ast::LitKind::Float(v, _) | + ast::LitKind::FloatUnsuffixed(v) => { + match v.as_str().parse() { Ok(f) => f, Err(_) => return, } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 0668d362037d..fa452017f0cf 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -20,7 +20,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::ast; use syntax::attr; use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType}; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use syntax::ptr::P; use syntax_pos::Span; @@ -48,7 +48,7 @@ impl UnusedMut { let name = path1.node; if let hir::BindByValue(hir::MutMutable) = mode { if !name.as_str().starts_with("_") { - match mutables.entry(name.0 as usize) { + match mutables.entry(name) { Vacant(entry) => { entry.insert(vec![id]); } @@ -162,7 +162,7 @@ impl LateLintPass for UnusedResults { // check for #[must_use="..."] if let Some(s) = attr.value_str() { msg.push_str(": "); - msg.push_str(&s); + msg.push_str(&s.as_str()); } cx.span_lint(UNUSED_MUST_USE, sp, &msg); return true; @@ -274,10 +274,10 @@ impl LateLintPass for UnusedAttributes { // Has a plugin registered this attribute as one which must be used at // the crate level? let plugin_crate = plugin_attributes.iter() - .find(|&&(ref x, t)| &*attr.name() == x && AttributeType::CrateLevel == t) + .find(|&&(ref x, t)| attr.name() == &**x && AttributeType::CrateLevel == t) .is_some(); if known_crate || plugin_crate { - let msg = match attr.node.style { + let msg = match attr.style { ast::AttrStyle::Outer => { "crate-level attribute should be an inner attribute: add an exclamation \ mark: #![foo]" diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index ebd75be7bba0..470e8d1fd457 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -395,9 +395,6 @@ pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque; #[allow(missing_copy_implementations)] pub enum OperandBundleDef_opaque {} pub type OperandBundleDefRef = *mut OperandBundleDef_opaque; -#[allow(missing_copy_implementations)] -pub enum Attribute_opaque {} -pub type AttributeRef = *mut Attribute_opaque; pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); @@ -770,8 +767,6 @@ extern "C" { Name: *const c_char) -> ValueRef; - pub fn LLVMRustCreateAttribute(C: ContextRef, kind: Attribute, val: u64) -> AttributeRef; - // Operations on functions pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; @@ -790,12 +785,12 @@ extern "C" { pub fn LLVMGetGC(Fn: ValueRef) -> *const c_char; pub fn LLVMSetGC(Fn: ValueRef, Name: *const c_char); pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: AttributeRef); + pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: Attribute); pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, index: c_uint, Name: *const c_char, Value: *const c_char); - pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: AttributeRef); + pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute); // Operations on parameters pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; @@ -806,8 +801,6 @@ extern "C" { pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef; pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef; pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef; - pub fn LLVMAddAttribute(Arg: ValueRef, attr: AttributeRef); - pub fn LLVMRemoveAttribute(Arg: ValueRef, attr: AttributeRef); pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint); // Operations on basic blocks @@ -851,7 +844,7 @@ extern "C" { pub fn LLVMAddInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); pub fn LLVMRemoveInstrAttribute(Instr: ValueRef, index: c_uint, IA: c_uint); pub fn LLVMSetInstrParamAlignment(Instr: ValueRef, index: c_uint, align: c_uint); - pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: AttributeRef); + pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: Attribute); pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64); // Operations on call instructions (only) diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index c81d3b48aa96..c4ec418f224b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -176,20 +176,16 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { } impl Attribute { - fn as_object(&self, value: ValueRef) -> AttributeRef { - unsafe { LLVMRustCreateAttribute(LLVMRustGetValueContext(value), *self, 0) } - } - pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), self.as_object(llfn)) } + unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } } pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { - unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), self.as_object(callsite)) } + unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } } pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), self.as_object(llfn)) } + unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } } pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5384535024e5..27c00481bfd3 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -37,13 +37,14 @@ use syntax::abi::Abi; use syntax::attr; use syntax::ext::base::SyntaxExtension; use syntax::feature_gate::{self, GateIssue}; -use syntax::parse::token::{InternedString, intern}; +use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; use log; pub struct Library { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, + pub rmeta: Option<(PathBuf, PathKind)>, pub metadata: MetadataBlob, } @@ -52,7 +53,7 @@ pub struct CrateLoader<'a> { cstore: &'a CStore, next_crate_num: CrateNum, foreign_item_map: FxHashMap>, - local_crate_name: String, + local_crate_name: Symbol, } fn dump_crates(cstore: &CStore) { @@ -62,16 +63,17 @@ fn dump_crates(cstore: &CStore) { info!(" cnum: {}", data.cnum); info!(" hash: {}", data.hash()); info!(" reqd: {:?}", data.dep_kind.get()); - let CrateSource { dylib, rlib } = data.source.clone(); + let CrateSource { dylib, rlib, rmeta } = data.source.clone(); dylib.map(|dl| info!(" dylib: {}", dl.0.display())); rlib.map(|rl| info!(" rlib: {}", rl.0.display())); - }) + rmeta.map(|rl| info!(" rmeta: {}", rl.0.display())); + }); } #[derive(Debug)] struct ExternCrateInfo { - ident: String, - name: String, + ident: Symbol, + name: Symbol, id: ast::NodeId, dep_kind: DepKind, } @@ -80,7 +82,7 @@ fn register_native_lib(sess: &Session, cstore: &CStore, span: Option, lib: NativeLibrary) { - if lib.name.is_empty() { + if lib.name.as_str().is_empty() { match span { Some(span) => { struct_span_err!(sess, span, E0454, @@ -147,7 +149,7 @@ impl<'a> CrateLoader<'a> { cstore: cstore, next_crate_num: cstore.next_crate_num(), foreign_item_map: FxHashMap(), - local_crate_name: local_crate_name.to_owned(), + local_crate_name: Symbol::intern(local_crate_name), } } @@ -160,12 +162,12 @@ impl<'a> CrateLoader<'a> { Some(name) => { validate_crate_name(Some(self.sess), &name.as_str(), Some(i.span)); - name.to_string() + name } - None => i.ident.to_string(), + None => i.ident.name, }; Some(ExternCrateInfo { - ident: i.ident.to_string(), + ident: i.ident.name, name: name, id: i.id, dep_kind: if attr::contains_name(&i.attrs, "no_link") { @@ -179,7 +181,7 @@ impl<'a> CrateLoader<'a> { } } - fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind) + fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind) -> Option { let mut ret = None; self.cstore.iter_crate_data(|cnum, data| { @@ -201,7 +203,7 @@ impl<'a> CrateLoader<'a> { // `source` stores paths which are normalized which may be different // from the strings on the command line. let source = self.cstore.used_crate_source(cnum); - if let Some(locs) = self.sess.opts.externs.get(name) { + if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { let found = locs.iter().any(|l| { let l = fs::canonicalize(l).ok(); source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || @@ -233,7 +235,7 @@ impl<'a> CrateLoader<'a> { root: &CrateRoot) { // Check for (potential) conflicts with the local crate if self.local_crate_name == root.name && - self.sess.local_crate_disambiguator() == &root.disambiguator[..] { + self.sess.local_crate_disambiguator() == root.disambiguator { span_fatal!(self.sess, span, E0519, "the current crate is indistinguishable from one of its \ dependencies: it has the same crate-name `{}` and was \ @@ -258,8 +260,8 @@ impl<'a> CrateLoader<'a> { fn register_crate(&mut self, root: &Option, - ident: &str, - name: &str, + ident: Symbol, + name: Symbol, span: Span, lib: Library, dep_kind: DepKind) @@ -278,6 +280,7 @@ impl<'a> CrateLoader<'a> { ident: ident.to_string(), dylib: lib.dylib.clone().map(|p| p.0), rlib: lib.rlib.clone().map(|p| p.0), + rmeta: lib.rmeta.clone().map(|p| p.0), }) } else { None @@ -285,12 +288,12 @@ impl<'a> CrateLoader<'a> { // Maintain a reference to the top most crate. let root = if root.is_some() { root } else { &crate_paths }; - let Library { dylib, rlib, metadata } = lib; + let Library { dylib, rlib, rmeta, metadata } = lib; let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); let cmeta = Rc::new(cstore::CrateMetadata { - name: name.to_string(), + name: name, extern_crate: Cell::new(None), key_map: metadata.load_key_map(crate_root.index), proc_macros: crate_root.macro_derive_registrar.map(|_| { @@ -305,6 +308,7 @@ impl<'a> CrateLoader<'a> { source: cstore::CrateSource { dylib: dylib, rlib: rlib, + rmeta: rmeta, }, }); @@ -314,8 +318,8 @@ impl<'a> CrateLoader<'a> { fn resolve_crate(&mut self, root: &Option, - ident: &str, - name: &str, + ident: Symbol, + name: Symbol, hash: Option<&Svh>, span: Span, path_kind: PathKind, @@ -366,6 +370,9 @@ impl<'a> CrateLoader<'a> { match result { LoadResult::Previous(cnum) => { let data = self.cstore.get_crate_data(cnum); + if data.root.macro_derive_registrar.is_some() { + dep_kind = DepKind::MacrosOnly; + } data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind)); (cnum, data) } @@ -456,13 +463,12 @@ impl<'a> CrateLoader<'a> { let deps = crate_root.crate_deps.decode(metadata); let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); - let dep_name = &dep.name.as_str(); let dep_kind = match dep_kind { DepKind::MacrosOnly => DepKind::MacrosOnly, _ => dep.kind, }; let (local_cnum, ..) = self.resolve_crate( - root, dep_name, dep_name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, + root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind, ); (CrateNum::new(crate_num + 1), local_cnum) }).collect(); @@ -482,13 +488,11 @@ impl<'a> CrateLoader<'a> { let target_triple = &self.sess.opts.target_triple[..]; let is_cross = target_triple != config::host_triple(); let mut target_only = false; - let ident = info.ident.clone(); - let name = info.name.clone(); let mut locate_ctxt = locator::Context { sess: self.sess, span: span, - ident: &ident[..], - crate_name: &name[..], + ident: info.ident, + crate_name: info.name, hash: None, filesearch: self.sess.host_filesearch(PathKind::Crate), target: &self.sess.host, @@ -582,11 +586,11 @@ impl<'a> CrateLoader<'a> { trait_name: &str, expand: fn(TokenStream) -> TokenStream, attributes: &[&'static str]) { - let attrs = attributes.iter().map(|s| InternedString::new(s)).collect(); + let attrs = attributes.iter().cloned().map(Symbol::intern).collect(); let derive = SyntaxExtension::CustomDerive( Box::new(CustomDerive::new(expand, attrs)) ); - self.0.push((intern(trait_name), Rc::new(derive))); + self.0.push((Symbol::intern(trait_name), Rc::new(derive))); } } @@ -604,8 +608,8 @@ impl<'a> CrateLoader<'a> { pub fn find_plugin_registrar(&mut self, span: Span, name: &str) -> Option<(PathBuf, Svh, DefIndex)> { let ekrate = self.read_extension_crate(span, &ExternCrateInfo { - name: name.to_string(), - ident: name.to_string(), + name: Symbol::intern(name), + ident: Symbol::intern(name), id: ast::DUMMY_NODE_ID, dep_kind: DepKind::MacrosOnly, }); @@ -642,7 +646,7 @@ impl<'a> CrateLoader<'a> { let libs = self.cstore.get_used_libraries(); for (foreign_lib, list) in self.foreign_item_map.iter() { let is_static = libs.borrow().iter().any(|lib| { - *foreign_lib == lib.name && lib.kind == cstore::NativeStatic + lib.name == &**foreign_lib && lib.kind == cstore::NativeStatic }); if is_static { for id in list { @@ -705,8 +709,8 @@ impl<'a> CrateLoader<'a> { // in terms of everyone has a compatible panic runtime format, that's // performed later as part of the `dependency_format` module. let name = match desired_strategy { - PanicStrategy::Unwind => "panic_unwind", - PanicStrategy::Abort => "panic_abort", + PanicStrategy::Unwind => Symbol::intern("panic_unwind"), + PanicStrategy::Abort => Symbol::intern("panic_abort"), }; info!("panic runtime not found -- loading {}", name); @@ -767,7 +771,8 @@ impl<'a> CrateLoader<'a> { config::CrateTypeProcMacro | config::CrateTypeCdylib | config::CrateTypeStaticlib => need_lib_alloc = true, - config::CrateTypeRlib => {} + config::CrateTypeRlib | + config::CrateTypeMetadata => {} } } if !need_lib_alloc && !need_exe_alloc { return } @@ -788,9 +793,9 @@ impl<'a> CrateLoader<'a> { // * Staticlibs and Rust dylibs use system malloc // * Rust dylibs used as dependencies to rust use jemalloc let name = if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic { - &self.sess.target.target.options.lib_allocation_crate + Symbol::intern(&self.sess.target.target.options.lib_allocation_crate) } else { - &self.sess.target.target.options.exe_allocation_crate + Symbol::intern(&self.sess.target.target.options.exe_allocation_crate) }; let dep_kind = DepKind::Implicit; let (cnum, data) = @@ -852,8 +857,8 @@ impl<'a> CrateLoader<'a> { impl<'a> CrateLoader<'a> { pub fn preprocess(&mut self, krate: &ast::Crate) { for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") { - if let Some(ref linkarg) = attr.value_str() { - self.cstore.add_used_link_args(&linkarg); + if let Some(linkarg) = attr.value_str() { + self.cstore.add_used_link_args(&linkarg.as_str()); } } } @@ -866,7 +871,7 @@ impl<'a> CrateLoader<'a> { // First, add all of the custom #[link_args] attributes for m in i.attrs.iter().filter(|a| a.check_name("link_args")) { if let Some(linkarg) = m.value_str() { - self.cstore.add_used_link_args(&linkarg); + self.cstore.add_used_link_args(&linkarg.as_str()); } } @@ -878,7 +883,7 @@ impl<'a> CrateLoader<'a> { }; let kind = items.iter().find(|k| { k.check_name("kind") - }).and_then(|a| a.value_str()); + }).and_then(|a| a.value_str()).map(Symbol::as_str); let kind = match kind.as_ref().map(|s| &s[..]) { Some("static") => cstore::NativeStatic, Some("dylib") => cstore::NativeUnknown, @@ -900,7 +905,7 @@ impl<'a> CrateLoader<'a> { struct_span_err!(self.sess, m.span, E0459, "#[link(...)] specified without `name = \"foo\"`") .span_label(m.span, &format!("missing `name` argument")).emit(); - InternedString::new("foo") + Symbol::intern("foo") } }; let cfg = items.iter().find(|k| { @@ -910,7 +915,7 @@ impl<'a> CrateLoader<'a> { list[0].meta_item().unwrap().clone() }); let lib = NativeLibrary { - name: n.to_string(), + name: n, kind: kind, cfg: cfg, }; @@ -941,7 +946,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { for &(ref name, kind) in &self.sess.opts.libs { let lib = NativeLibrary { - name: name.clone(), + name: Symbol::intern(name), kind: kind, cfg: None, }; @@ -959,7 +964,7 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> { let info = self.extract_crate_info(item).unwrap(); let (cnum, ..) = self.resolve_crate( - &None, &info.ident, &info.name, None, item.span, PathKind::Crate, info.dep_kind, + &None, info.ident, info.name, None, item.span, PathKind::Crate, info.dep_kind, ); let def_id = definitions.opt_local_def_id(item.id).unwrap(); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 37853b7473a6..7c1834c1576a 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -25,15 +25,15 @@ use rustc::util::nodemap::{FxHashMap, NodeMap, NodeSet, DefIdMap}; use std::cell::{RefCell, Cell}; use std::rc::Rc; -use std::path::PathBuf; use flate::Bytes; use syntax::{ast, attr}; use syntax::ext::base::SyntaxExtension; +use syntax::symbol::Symbol; use syntax_pos; pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference}; pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown}; -pub use rustc::middle::cstore::{CrateSource, LinkMeta}; +pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; // A map from external crate numbers (as decoded from some crate file) to // local crate numbers (as generated during this session). Each external @@ -44,6 +44,7 @@ pub type CrateNumMap = IndexVec; pub enum MetadataBlob { Inflated(Bytes), Archive(locator::ArchiveMetadata), + Raw(Vec), } /// Holds information about a syntax_pos::FileMap imported from another crate. @@ -58,7 +59,7 @@ pub struct ImportedFileMap { } pub struct CrateMetadata { - pub name: String, + pub name: Symbol, /// Information about the extern crate that caused this crate to /// be loaded. If this is `None`, then the crate was injected @@ -185,7 +186,7 @@ impl CStore { // positions. pub fn do_get_used_crates(&self, prefer: LinkagePreference) - -> Vec<(CrateNum, Option)> { + -> Vec<(CrateNum, LibSource)> { let mut ordering = Vec::new(); for (&num, _) in self.metas.borrow().iter() { self.push_dependencies_in_postorder(&mut ordering, num); @@ -201,6 +202,16 @@ impl CStore { LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0), LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0), }; + let path = match path { + Some(p) => LibSource::Some(p), + None => { + if data.source.rmeta.is_some() { + LibSource::MetadataOnly + } else { + LibSource::None + } + } + }; Some((cnum, path)) }) .collect::>(); @@ -213,7 +224,7 @@ impl CStore { } pub fn add_used_library(&self, lib: NativeLibrary) { - assert!(!lib.name.is_empty()); + assert!(!lib.name.as_str().is_empty()); self.used_libraries.borrow_mut().push(lib); } @@ -249,14 +260,14 @@ impl CStore { } impl CrateMetadata { - pub fn name(&self) -> &str { - &self.root.name + pub fn name(&self) -> Symbol { + self.root.name } pub fn hash(&self) -> Svh { self.root.hash } - pub fn disambiguator(&self) -> &str { - &self.root.disambiguator + pub fn disambiguator(&self) -> Symbol { + self.root.disambiguator } pub fn is_staged_api(&self) -> bool { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2018d829597d..ead933384b96 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -13,7 +13,7 @@ use encoder; use locator; use schema; -use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, DepKind, ExternCrate}; +use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, LibSource, DepKind, ExternCrate}; use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro}; use rustc::hir::def::{self, Def}; use rustc::middle::lang_items; @@ -28,10 +28,10 @@ use rustc::mir::Mir; use rustc::util::nodemap::{NodeSet, DefIdMap}; use rustc_back::PanicStrategy; -use std::path::PathBuf; use syntax::ast; use syntax::attr; -use syntax::parse::{token, new_parser_from_source_str}; +use syntax::parse::new_parser_from_source_str; +use syntax::symbol::Symbol; use syntax_pos::mk_sp; use rustc::hir::svh::Svh; use rustc_back::target::Target; @@ -262,14 +262,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).panic_strategy() } - fn crate_name(&self, cnum: CrateNum) -> token::InternedString + fn crate_name(&self, cnum: CrateNum) -> Symbol { - token::intern_and_get_ident(&self.get_crate_data(cnum).name[..]) + self.get_crate_data(cnum).name } - fn original_crate_name(&self, cnum: CrateNum) -> token::InternedString + fn original_crate_name(&self, cnum: CrateNum) -> Symbol { - token::intern_and_get_ident(&self.get_crate_data(cnum).name()) + self.get_crate_data(cnum).name() } fn extern_crate(&self, cnum: CrateNum) -> Option @@ -282,9 +282,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_hash(cnum) } - fn crate_disambiguator(&self, cnum: CrateNum) -> token::InternedString + fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol { - token::intern_and_get_ident(&self.get_crate_data(cnum).disambiguator()) + self.get_crate_data(cnum).disambiguator() } fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option @@ -544,7 +544,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { locator::meta_section_name(target) } - fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option)> + fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { self.do_get_used_crates(prefer) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 3af9d291ae55..8a187bb97969 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -88,8 +88,9 @@ pub trait Metadata<'a, 'tcx>: Copy { impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { fn raw_bytes(self) -> &'a [u8] { match *self { - MetadataBlob::Inflated(ref vec) => &vec[..], + MetadataBlob::Inflated(ref vec) => vec, MetadataBlob::Archive(ref ar) => ar.as_slice(), + MetadataBlob::Raw(ref vec) => vec, } } } @@ -934,7 +935,7 @@ impl<'a, 'tcx> CrateMetadata { .decode(self) .map(|mut attr| { // Need new unique IDs: old thread-local IDs won't map to new threads. - attr.node.id = attr::mk_attr_id(); + attr.id = attr::mk_attr_id(); attr }) .collect() diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3ab542442a1f..2f4b0d5c87b0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -34,7 +34,7 @@ use std::rc::Rc; use std::u32; use syntax::ast::{self, CRATE_NODE_ID}; use syntax::attr; -use syntax; +use syntax::symbol::Symbol; use syntax_pos; use rustc::hir::{self, PatKind}; @@ -600,7 +600,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let PatKind::Binding(_, ref path1, _) = arg.pat.node { path1.node } else { - syntax::parse::token::intern("") + Symbol::intern("") } })) } @@ -1119,7 +1119,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let deps = get_ordered_deps(self.cstore); self.lazy_seq(deps.iter().map(|&(_, ref dep)| { CrateDep { - name: syntax::parse::token::intern(dep.name()), + name: dep.name(), hash: dep.hash(), kind: dep.dep_kind.get(), } @@ -1279,10 +1279,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro); let root = self.lazy(&CrateRoot { rustc_version: rustc_version(), - name: link_meta.crate_name.clone(), + name: link_meta.crate_name, triple: tcx.sess.opts.target_triple.clone(), hash: link_meta.crate_hash, - disambiguator: tcx.sess.local_crate_disambiguator().to_string(), + disambiguator: tcx.sess.local_crate_disambiguator(), panic_strategy: tcx.sess.panic_strategy(), plugin_registrar_fn: tcx.sess .plugin_registrar_fn diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index b677a63edc06..be9284baa74c 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -53,6 +53,13 @@ //! is a platform-defined dynamic library. Each library has a metadata somewhere //! inside of it. //! +//! A third kind of dependency is an rmeta file. These are metadata files and do +//! not contain any code, etc. To a first approximation, these are treated in the +//! same way as rlibs. Where there is both an rlib and an rmeta file, the rlib +//! gets priority (even if the rmeta file is newer). An rmeta file is only +//! useful for checking a downstream crate, attempting to link one will cause an +//! error. +//! //! When translating a crate name to a crate on the filesystem, we all of a //! sudden need to take into account both rlibs and dylibs! Linkage later on may //! use either one of these files, as each has their pros/cons. The job of crate @@ -227,13 +234,14 @@ use rustc_llvm as llvm; use rustc_llvm::{False, ObjectFile, mk_section_iter}; use rustc_llvm::archive_ro::ArchiveRO; use errors::DiagnosticBuilder; +use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_back::target::Target; use std::cmp; use std::fmt; -use std::fs; -use std::io; +use std::fs::{self, File}; +use std::io::{self, Read}; use std::path::{Path, PathBuf}; use std::ptr; use std::slice; @@ -249,8 +257,8 @@ pub struct CrateMismatch { pub struct Context<'a> { pub sess: &'a Session, pub span: Span, - pub ident: &'a str, - pub crate_name: &'a str, + pub ident: Symbol, + pub crate_name: Symbol, pub hash: Option<&'a Svh>, // points to either self.sess.target.target or self.sess.host, must match triple pub target: &'a Target, @@ -275,6 +283,7 @@ pub struct CratePaths { pub ident: String, pub dylib: Option, pub rlib: Option, + pub rmeta: Option, } pub const METADATA_FILENAME: &'static str = "rust.metadata.bin"; @@ -282,6 +291,7 @@ pub const METADATA_FILENAME: &'static str = "rust.metadata.bin"; #[derive(Copy, Clone, PartialEq)] enum CrateFlavor { Rlib, + Rmeta, Dylib, } @@ -289,6 +299,7 @@ impl fmt::Display for CrateFlavor { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(match *self { CrateFlavor::Rlib => "rlib", + CrateFlavor::Rmeta => "rmeta", CrateFlavor::Dylib => "dylib", }) } @@ -296,12 +307,7 @@ impl fmt::Display for CrateFlavor { impl CratePaths { fn paths(&self) -> Vec { - match (&self.dylib, &self.rlib) { - (&None, &None) => vec![], - (&Some(ref p), &None) | - (&None, &Some(ref p)) => vec![p.clone()], - (&Some(ref p1), &Some(ref p2)) => vec![p1.clone(), p2.clone()], - } + self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).cloned().collect() } } @@ -422,7 +428,7 @@ impl<'a> Context<'a> { // must be loaded via -L plus some filtering. if self.hash.is_none() { self.should_match_name = false; - if let Some(s) = self.sess.opts.externs.get(self.crate_name) { + if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { return self.find_commandline_library(s.iter()); } self.should_match_name = true; @@ -457,32 +463,35 @@ impl<'a> Context<'a> { None => return FileDoesntMatch, Some(file) => file, }; - let (hash, rlib) = if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") { - (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], true) - } else if file.starts_with(&dylib_prefix) && - file.ends_with(&dypair.1) { - (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], false) - } else { - if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) { - staticlibs.push(CrateMismatch { - path: path.to_path_buf(), - got: "static".to_string(), - }); - } - return FileDoesntMatch; - }; + let (hash, found_kind) = + if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") { + (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib) + } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") { + (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta) + } else if file.starts_with(&dylib_prefix) && + file.ends_with(&dypair.1) { + (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib) + } else { + if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) { + staticlibs.push(CrateMismatch { + path: path.to_path_buf(), + got: "static".to_string(), + }); + } + return FileDoesntMatch; + }; info!("lib candidate: {}", path.display()); let hash_str = hash.to_string(); let slot = candidates.entry(hash_str) - .or_insert_with(|| (FxHashMap(), FxHashMap())); - let (ref mut rlibs, ref mut dylibs) = *slot; + .or_insert_with(|| (FxHashMap(), FxHashMap(), FxHashMap())); + let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot; fs::canonicalize(path) .map(|p| { - if rlib { - rlibs.insert(p, kind); - } else { - dylibs.insert(p, kind); + match found_kind { + CrateFlavor::Rlib => { rlibs.insert(p, kind); } + CrateFlavor::Rmeta => { rmetas.insert(p, kind); } + CrateFlavor::Dylib => { dylibs.insert(p, kind); } } FileMatches }) @@ -499,15 +508,17 @@ impl<'a> Context<'a> { // libraries corresponds to the crate id and hash criteria that this // search is being performed for. let mut libraries = FxHashMap(); - for (_hash, (rlibs, dylibs)) in candidates { + for (_hash, (rlibs, rmetas, dylibs)) in candidates { let mut slot = None; let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); + let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); if let Some((h, m)) = slot { libraries.insert(h, Library { dylib: dylib, rlib: rlib, + rmeta: rmeta, metadata: m, }); } @@ -533,7 +544,7 @@ impl<'a> Context<'a> { if let Some((ref p, _)) = lib.rlib { err.note(&format!("path: {}", p.display())); } - note_crate_name(&mut err, &lib.metadata.get_root().name); + note_crate_name(&mut err, &lib.metadata.get_root().name.as_str()); } err.emit(); None @@ -703,6 +714,7 @@ impl<'a> Context<'a> { let sess = self.sess; let dylibname = self.dylibname(); let mut rlibs = FxHashMap(); + let mut rmetas = FxHashMap(); let mut dylibs = FxHashMap(); { let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| { @@ -721,7 +733,8 @@ impl<'a> Context<'a> { return false; } }; - if file.starts_with("lib") && file.ends_with(".rlib") { + if file.starts_with("lib") && + (file.ends_with(".rlib") || file.ends_with(".rmeta")) { return true; } else { let (ref prefix, ref suffix) = dylibname; @@ -744,6 +757,8 @@ impl<'a> Context<'a> { for loc in locs { if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") { rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); + } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") { + rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } else { dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag); } @@ -753,9 +768,10 @@ impl<'a> Context<'a> { // Extract the rlib/dylib pair. let mut slot = None; let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); + let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); - if rlib.is_none() && dylib.is_none() { + if rlib.is_none() && rmeta.is_none() && dylib.is_none() { return None; } match slot { @@ -763,6 +779,7 @@ impl<'a> Context<'a> { Some(Library { dylib: dylib, rlib: rlib, + rmeta: rmeta, metadata: metadata, }) } @@ -850,6 +867,15 @@ fn get_metadata_section_imp(target: &Target, Ok(blob) } }; + } else if flavor == CrateFlavor::Rmeta { + let mut file = File::open(filename).map_err(|_| + format!("could not open file: '{}'", filename.display()))?; + let mut buf = vec![]; + file.read_to_end(&mut buf).map_err(|_| + format!("failed to read rlib metadata: '{}'", filename.display()))?; + let blob = MetadataBlob::Raw(buf); + verify_decompressed_encoding_version(&blob, filename)?; + return Ok(blob); } unsafe { let buf = common::path2cstr(filename); @@ -933,6 +959,8 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) -> let filename = path.file_name().unwrap().to_str().unwrap(); let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib + } else if filename.ends_with(".rmeta") { + CrateFlavor::Rmeta } else { CrateFlavor::Dylib }; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 32c8c5e2ee87..e11719dc40f2 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -22,6 +22,7 @@ use rustc_back::PanicStrategy; use rustc_serialize as serialize; use syntax::{ast, attr}; +use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; @@ -163,10 +164,10 @@ pub enum LazyState { #[derive(RustcEncodable, RustcDecodable)] pub struct CrateRoot { pub rustc_version: String, - pub name: String, + pub name: Symbol, pub triple: String, pub hash: hir::svh::Svh, - pub disambiguator: String, + pub disambiguator: Symbol, pub panic_strategy: PanicStrategy, pub plugin_registrar_fn: Option, pub macro_derive_registrar: Option, diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 5fa084422210..5a77de080702 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -169,41 +169,39 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.terminate(block, source_info, TerminatorKind::Goto { target: loop_block }); - let might_break = this.in_loop_scope(loop_block, exit_block, move |this| { - // conduct the test, if necessary - let body_block; - if let Some(cond_expr) = opt_cond_expr { - // This loop has a condition, ergo its exit_block is reachable. - this.find_loop_scope(expr_span, None).might_break = true; + this.in_loop_scope( + loop_block, exit_block, destination.clone(), + move |this| { + // conduct the test, if necessary + let body_block; + if let Some(cond_expr) = opt_cond_expr { + let loop_block_end; + let cond = unpack!( + loop_block_end = this.as_operand(loop_block, cond_expr)); + body_block = this.cfg.start_new_block(); + this.cfg.terminate(loop_block_end, source_info, + TerminatorKind::If { + cond: cond, + targets: (body_block, exit_block) + }); - let loop_block_end; - let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr)); - body_block = this.cfg.start_new_block(); - this.cfg.terminate(loop_block_end, source_info, - TerminatorKind::If { - cond: cond, - targets: (body_block, exit_block) - }); - } else { - body_block = loop_block; + // if the test is false, there's no `break` to assign `destination`, so + // we have to do it; this overwrites any `break`-assigned value but it's + // always `()` anyway + this.cfg.push_assign_unit(exit_block, source_info, destination); + } else { + body_block = loop_block; + } + + // The “return” value of the loop body must always be an unit. We therefore + // introduce a unit temporary as the destination for the loop body. + let tmp = this.get_unit_temp(); + // Execute the body, branching back to the test. + let body_block_end = unpack!(this.into(&tmp, body_block, body)); + this.cfg.terminate(body_block_end, source_info, + TerminatorKind::Goto { target: loop_block }); } - - // The “return” value of the loop body must always be an unit, but we cannot - // reuse that as a “return” value of the whole loop expressions, because some - // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as - // the destination for the loop body and assign the loop’s own “return” value - // immediately after the iteration is finished. - let tmp = this.get_unit_temp(); - // Execute the body, branching back to the test. - let body_block_end = unpack!(this.into(&tmp, body_block, body)); - this.cfg.terminate(body_block_end, source_info, - TerminatorKind::Goto { target: loop_block }); - }); - // If the loop may reach its exit_block, we assign an empty tuple to the - // destination to keep the MIR well-formed. - if might_break { - this.cfg.push_assign_unit(exit_block, source_info, destination); - } + ); exit_block.unit() } ExprKind::Call { ty, fun, args } => { diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 4a1926e7c57d..f04d630379a3 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -11,9 +11,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::scope::LoopScope; use hair::*; -use rustc::middle::region::CodeExtent; use rustc::mir::*; -use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { @@ -79,14 +77,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block.unit() } ExprKind::Continue { label } => { - this.break_or_continue(expr_span, label, block, - |loop_scope| loop_scope.continue_block) + let LoopScope { continue_block, extent, .. } = + *this.find_loop_scope(expr_span, label); + this.exit_scope(expr_span, extent, block, continue_block); + this.cfg.start_new_block().unit() } - ExprKind::Break { label } => { - this.break_or_continue(expr_span, label, block, |loop_scope| { - loop_scope.might_break = true; - loop_scope.break_block - }) + ExprKind::Break { label, value } => { + let (break_block, extent, destination) = { + let LoopScope { + break_block, + extent, + ref break_destination, + .. + } = *this.find_loop_scope(expr_span, label); + (break_block, extent, break_destination.clone()) + }; + if let Some(value) = value { + unpack!(block = this.into(&destination, block, value)) + } else { + this.cfg.push_assign_unit(block, source_info, &destination) + } + this.exit_scope(expr_span, extent, block, break_block); + this.cfg.start_new_block().unit() } ExprKind::Return { value } => { block = match value { @@ -115,20 +127,4 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - fn break_or_continue(&mut self, - span: Span, - label: Option, - block: BasicBlock, - exit_selector: F) - -> BlockAnd<()> - where F: FnOnce(&mut LoopScope) -> BasicBlock - { - let (exit_block, extent) = { - let loop_scope = self.find_loop_scope(span, label); - (exit_selector(loop_scope), loop_scope.extent) - }; - self.exit_scope(span, extent, block, exit_block); - self.cfg.start_new_block().unit() - } - } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 458a952543e4..5713ee45b9d8 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -18,7 +18,7 @@ use rustc::util::nodemap::NodeMap; use rustc::hir; use syntax::abi::Abi; use syntax::ast; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use syntax_pos::Span; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -38,7 +38,7 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// the current set of loops; see the `scope` module for more /// details - loop_scopes: Vec, + loop_scopes: Vec>, /// the vector of all scopes that we have created thus far; /// we track this for debuginfo later diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 4d9b6c0e05a4..e5fac94a8a49 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -177,7 +177,7 @@ struct FreeData<'tcx> { } #[derive(Clone, Debug)] -pub struct LoopScope { +pub struct LoopScope<'tcx> { /// Extent of the loop pub extent: CodeExtent, /// Where the body of the loop begins @@ -185,8 +185,9 @@ pub struct LoopScope { /// Block to branch into when the loop terminates (either by being `break`-en out from, or by /// having its condition to become false) pub break_block: BasicBlock, - /// Indicates the reachability of the break_block for this loop - pub might_break: bool + /// The destination of the loop expression itself (i.e. where to put the result of a `break` + /// expression) + pub break_destination: Lvalue<'tcx>, } impl<'tcx> Scope<'tcx> { @@ -246,10 +247,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// /// Returns the might_break attribute of the LoopScope used. pub fn in_loop_scope(&mut self, - loop_block: BasicBlock, - break_block: BasicBlock, - f: F) - -> bool + loop_block: BasicBlock, + break_block: BasicBlock, + break_destination: Lvalue<'tcx>, + f: F) where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) { let extent = self.extent_of_innermost_scope(); @@ -257,13 +258,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { extent: extent.clone(), continue_block: loop_block, break_block: break_block, - might_break: false + break_destination: break_destination, }; self.loop_scopes.push(loop_scope); f(self); let loop_scope = self.loop_scopes.pop().unwrap(); assert!(loop_scope.extent == extent); - loop_scope.might_break } /// Convenience wrapper that pushes a scope and then executes `f` @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn find_loop_scope(&mut self, span: Span, label: Option) - -> &mut LoopScope { + -> &mut LoopScope<'tcx> { let loop_scopes = &mut self.loop_scopes; match label { None => { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 24c1ca574a01..6fa267259358 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -21,7 +21,6 @@ use rustc_const_eval as const_eval; use rustc::middle::region::CodeExtent; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; -use rustc::mir::*; use rustc::hir; use syntax::ptr::P; @@ -559,8 +558,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }, hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, - hir::ExprBreak(label) => - ExprKind::Break { label: label.map(|_| loop_label(cx, expr)) }, + hir::ExprBreak(label, ref value) => + ExprKind::Break { label: label.map(|_| loop_label(cx, expr)), + value: value.to_ref() }, hir::ExprAgain(label) => ExprKind::Continue { label: label.map(|_| loop_label(cx, expr)) }, hir::ExprMatch(ref discr, ref arms, _) => @@ -573,7 +573,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprWhile(ref cond, ref body, _) => ExprKind::Loop { condition: Some(cond.to_ref()), body: block::to_expr_ref(cx, body) }, - hir::ExprLoop(ref body, _) => + hir::ExprLoop(ref body, _, _) => ExprKind::Loop { condition: None, body: block::to_expr_ref(cx, body) }, hir::ExprField(ref source, name) => { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 038300068fce..cfeac606f03d 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -16,7 +16,6 @@ */ use hair::*; -use rustc::mir::*; use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; @@ -29,7 +28,7 @@ use rustc::hir::map::blocks::FnLikeNode; use rustc::infer::InferCtxt; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; -use syntax::parse::token; +use syntax::symbol::{Symbol, InternedString}; use rustc::hir; use rustc_const_math::{ConstInt, ConstUsize}; @@ -121,7 +120,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx.mk_nil() } - pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> { + pub fn str_literal(&mut self, value: InternedString) -> Literal<'tcx> { Literal::Value { value: ConstVal::Str(value) } } @@ -145,7 +144,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self_ty: Ty<'tcx>, params: &[Ty<'tcx>]) -> (Ty<'tcx>, Literal<'tcx>) { - let method_name = token::intern(method_name); + let method_name = Symbol::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssociatedKind::Method && item.name == method_name { diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index e211334e5473..50eee7723964 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -202,6 +202,7 @@ pub enum ExprKind<'tcx> { }, Break { label: Option, + value: Option>, }, Continue { label: Option, diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index aa56daf88894..62e405564dbb 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -23,6 +23,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(associated_consts)] #![feature(box_patterns)] #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))] +#![cfg_attr(stage0, feature(item_like_imports))] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] #![feature(staged_api)] diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 828efbf37313..a3916e7eca35 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -21,7 +21,8 @@ use rustc::session::Session; use syntax::ast::*; use syntax::attr; use syntax::codemap::Spanned; -use syntax::parse::token::{self, keywords}; +use syntax::parse::token; +use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax_pos::Span; use errors; @@ -39,7 +40,7 @@ impl<'a> AstValidator<'a> { if label.name == keywords::StaticLifetime.name() { self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name)); } - if label.name.as_str() == "'_" { + if label.name == "'_" { self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE, id, span, @@ -89,7 +90,7 @@ impl<'a> AstValidator<'a> { impl<'a> Visitor for AstValidator<'a> { fn visit_lifetime(&mut self, lt: &Lifetime) { - if lt.name.as_str() == "'_" { + if lt.name == "'_" { self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE, lt.id, lt.span, @@ -105,7 +106,7 @@ impl<'a> Visitor for AstValidator<'a> { ExprKind::Loop(_, Some(ident)) | ExprKind::WhileLet(.., Some(ident)) | ExprKind::ForLoop(.., Some(ident)) | - ExprKind::Break(Some(ident)) | + ExprKind::Break(Some(ident), _) | ExprKind::Continue(Some(ident)) => { self.check_label(ident.node, ident.span, expr.id); } @@ -206,6 +207,13 @@ impl<'a> Visitor for AstValidator<'a> { ItemKind::Mod(_) => { // Ensure that `path` attributes on modules are recorded as used (c.f. #35584). attr::first_attr_value_str_by_name(&item.attrs, "path"); + if let Some(attr) = + item.attrs.iter().find(|attr| attr.name() == "warn_directory_ownership") { + let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP; + let msg = "cannot declare a new module at this location"; + self.session.add_lint(lint, item.id, item.span, msg.to_string()); + attr::mark_used(attr); + } } ItemKind::Union(ref vdata, _) => { if !vdata.is_struct() { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 5df8accd8cef..4d8520ed0440 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -610,7 +610,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node hir::ExprLoop(..) | // More control flow (also not very meaningful). - hir::ExprBreak(_) | + hir::ExprBreak(..) | hir::ExprAgain(_) | hir::ExprRet(_) | diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 89b8aa81411b..b2ef1abd2a4e 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -228,4 +228,5 @@ pub impl Foo for Bar { register_diagnostics! { E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types + E0571, // `break` with a value in a non-`loop`-loop } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 3bdaf276b40c..dafb7bc6e609 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -240,7 +240,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_assoc_type_binding(self, type_binding) } fn visit_attribute(&mut self, attr: &'v ast::Attribute) { - self.record("Attribute", Id::Attr(attr.node.id), attr); + self.record("Attribute", Id::Attr(attr.id), attr); } fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) { self.record("MacroDef", Id::Node(macro_def.id), macro_def); diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 724100e02237..c909e75afc1f 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -12,34 +12,56 @@ use self::Context::*; use rustc::session::Session; use rustc::dep_graph::DepNode; +use rustc::hir::def::{Def, DefMap}; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor}; use rustc::hir; use syntax_pos::Span; +#[derive(Clone, Copy, PartialEq)] +enum LoopKind { + Loop(hir::LoopSource), + WhileLoop, +} + +impl LoopKind { + fn name(self) -> &'static str { + match self { + LoopKind::Loop(hir::LoopSource::Loop) => "loop", + LoopKind::Loop(hir::LoopSource::WhileLet) => "while let", + LoopKind::Loop(hir::LoopSource::ForLoop) => "for", + LoopKind::WhileLoop => "while", + } + } +} + #[derive(Clone, Copy, PartialEq)] enum Context { Normal, - Loop, + Loop(LoopKind), Closure, } #[derive(Copy, Clone)] -struct CheckLoopVisitor<'a> { +struct CheckLoopVisitor<'a, 'ast: 'a> { sess: &'a Session, + def_map: &'a DefMap, + hir_map: &'a Map<'ast>, cx: Context, } -pub fn check_crate(sess: &Session, map: &Map) { +pub fn check_crate(sess: &Session, def_map: &DefMap, map: &Map) { let _task = map.dep_graph.in_task(DepNode::CheckLoops); let krate = map.krate(); krate.visit_all_item_likes(&mut CheckLoopVisitor { sess: sess, + def_map: def_map, + hir_map: map, cx: Normal, }.as_deep_visitor()); } -impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { +impl<'a, 'ast, 'v> Visitor<'v> for CheckLoopVisitor<'a, 'ast> { fn visit_item(&mut self, i: &hir::Item) { self.with_context(Normal, |v| intravisit::walk_item(v, i)); } @@ -51,25 +73,62 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { fn visit_expr(&mut self, e: &hir::Expr) { match e.node { hir::ExprWhile(ref e, ref b, _) => { - self.visit_expr(&e); - self.with_context(Loop, |v| v.visit_block(&b)); + self.with_context(Loop(LoopKind::WhileLoop), |v| { + v.visit_expr(&e); + v.visit_block(&b); + }); } - hir::ExprLoop(ref b, _) => { - self.with_context(Loop, |v| v.visit_block(&b)); + hir::ExprLoop(ref b, _, source) => { + self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b)); } hir::ExprClosure(.., ref b, _) => { self.with_context(Closure, |v| v.visit_expr(&b)); } - hir::ExprBreak(_) => self.require_loop("break", e.span), + hir::ExprBreak(ref opt_label, ref opt_expr) => { + if opt_expr.is_some() { + let loop_kind = if opt_label.is_some() { + let loop_def = self.def_map.get(&e.id).unwrap().full_def(); + if loop_def == Def::Err { + None + } else if let Def::Label(loop_id) = loop_def { + Some(match self.hir_map.expect_expr(loop_id).node { + hir::ExprWhile(..) => LoopKind::WhileLoop, + hir::ExprLoop(_, _, source) => LoopKind::Loop(source), + ref r => span_bug!(e.span, + "break label resolved to a non-loop: {:?}", r), + }) + } else { + span_bug!(e.span, "break resolved to a non-label") + } + } else if let Loop(kind) = self.cx { + Some(kind) + } else { + // `break` outside a loop - caught below + None + }; + match loop_kind { + None | Some(LoopKind::Loop(hir::LoopSource::Loop)) => (), + Some(kind) => { + struct_span_err!(self.sess, e.span, E0571, + "`break` with value from a `{}` loop", + kind.name()) + .span_label(e.span, + &format!("can only break with a value inside `loop`")) + .emit(); + } + } + } + self.require_loop("break", e.span); + } hir::ExprAgain(_) => self.require_loop("continue", e.span), _ => intravisit::walk_expr(self, e), } } } -impl<'a> CheckLoopVisitor<'a> { +impl<'a, 'ast> CheckLoopVisitor<'a, 'ast> { fn with_context(&mut self, cx: Context, f: F) - where F: FnOnce(&mut CheckLoopVisitor<'a>) + where F: FnOnce(&mut CheckLoopVisitor<'a, 'ast>) { let old_cx = self.cx; self.cx = cx; @@ -79,7 +138,7 @@ impl<'a> CheckLoopVisitor<'a> { fn require_loop(&self, name: &str, span: Span) { match self.cx { - Loop => {} + Loop(_) => {} Closure => { struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name) .span_label(span, &format!("cannot break inside of a closure")) diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 4438241999a3..1bfc445fca98 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -69,9 +69,9 @@ pub fn load_plugins(sess: &Session, for plugin in plugins { // plugins must have a name and can't be key = value match plugin.name() { - Some(ref name) if !plugin.is_value_str() => { + Some(name) if !plugin.is_value_str() => { let args = plugin.meta_item_list().map(ToOwned::to_owned); - loader.load_plugin(plugin.span, name, args.unwrap_or_default()); + loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default()); }, _ => call_malformed_plugin_attribute(sess, attr.span), } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 88e248e2efa3..fe2f9713d1be 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -17,7 +17,7 @@ use rustc::mir::transform::MirMapPass; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT}; use syntax::ext::base::MacroExpanderFn; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax::ast; use syntax::feature_gate::AttributeType; use syntax_pos::Span; @@ -101,7 +101,7 @@ impl<'a> Registry<'a> { /// /// This is the most general hook into `libsyntax`'s expansion behavior. pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { - if name.as_str() == "macro_rules" { + if name == "macro_rules" { panic!("user-defined macros may not be named `macro_rules`"); } self.syntax_exts.push((name, match extension { @@ -121,7 +121,7 @@ impl<'a> Registry<'a> { /// It builds for you a `NormalTT` that calls `expander`, /// and also takes care of interning the macro's name. pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) { - self.register_syntax_extension(token::intern(name), + self.register_syntax_extension(Symbol::intern(name), NormalTT(Box::new(expander), None, false)); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 627c72ff8c92..ff2f25a12fc8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -31,7 +31,6 @@ use std::rc::Rc; use syntax::ast::Name; use syntax::attr; -use syntax::parse::token; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind}; use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind}; @@ -41,7 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::expand::mark_tts; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -139,7 +138,7 @@ impl<'b> Resolver<'b> { match view_path.node { ViewPathSimple(binding, ref full_path) => { let mut source = full_path.segments.last().unwrap().identifier; - let source_name = source.name.as_str(); + let source_name = source.name; if source_name == "mod" || source_name == "self" { resolve_error(self, view_path.span, @@ -582,7 +581,7 @@ impl<'b> Resolver<'b> { }); } else { for (name, span) in legacy_imports.imports { - let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None); + let result = self.resolve_name_in_module(module, name, MacroNS, false, None); if let Success(binding) = result { self.legacy_import_macro(name, binding, span, allow_shadowing); } else { @@ -592,7 +591,7 @@ impl<'b> Resolver<'b> { } for (name, span) in legacy_imports.reexports { self.used_crates.insert(module.def_id().unwrap().krate); - let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None); + let result = self.resolve_name_in_module(module, name, MacroNS, false, None); if let Success(binding) = result { self.macro_exports.push(Export { name: name, def: binding.def() }); } else { @@ -607,7 +606,7 @@ impl<'b> Resolver<'b> { if attr.check_name("macro_escape") { let msg = "macro_escape is a deprecated synonym for macro_use"; let mut err = self.session.struct_span_warn(attr.span, msg); - if let ast::AttrStyle::Inner = attr.node.style { + if let ast::AttrStyle::Inner = attr.style { err.help("consider an outer attribute, #[macro_use] mod ...").emit(); } else { err.emit(); @@ -632,7 +631,7 @@ impl<'b> Resolver<'b> { match attr.meta_item_list() { Some(names) => for attr in names { if let Some(word) = attr.word() { - imports.imports.push((token::intern(&word.name()), attr.span())); + imports.imports.push((word.name(), attr.span())); } else { span_err!(self.session, attr.span(), E0466, "bad macro import"); } @@ -646,7 +645,7 @@ impl<'b> Resolver<'b> { if let Some(names) = attr.meta_item_list() { for attr in names { if let Some(word) = attr.word() { - imports.reexports.push((token::intern(&word.name()), attr.span())); + imports.reexports.push((word.name(), attr.span())); } else { bad_macro_reexport(self, attr.span()); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5eb269030a00..d54f4e7b20c7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -59,7 +59,7 @@ items under a new local name. An example of this error: -```compile_fail +```ignore use foo::baz; use bar::*; // error, do `use foo::baz as quux` instead on the previous line diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a3a60e4f6d75..ab3d361a940f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -57,7 +57,7 @@ use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; -use syntax::parse::token::{self, keywords}; +use syntax::symbol::{Symbol, keywords}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; @@ -90,7 +90,7 @@ mod resolve_imports; enum SuggestionType { Macro(String), - Function(token::InternedString), + Function(Symbol), NotFound, } @@ -1039,7 +1039,7 @@ impl PrimitiveTypeTable { } fn intern(&mut self, string: &str, primitive_type: PrimTy) { - self.primitive_types.insert(token::intern(string), primitive_type); + self.primitive_types.insert(Symbol::intern(string), primitive_type); } } @@ -1131,7 +1131,6 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - new_import_semantics: bool, // true if `#![feature(item_like_imports)]` use_extern_macros: bool, // true if `#![feature(use_extern_macros)]` pub exported_macros: Vec, @@ -1333,7 +1332,6 @@ impl<'a> Resolver<'a> { span: DUMMY_SP, vis: ty::Visibility::Public, }), - new_import_semantics: session.features.borrow().item_like_imports, use_extern_macros: session.features.borrow().use_extern_macros, exported_macros: Vec::new(), @@ -1442,7 +1440,7 @@ impl<'a> Resolver<'a> { -> ResolveResult> { fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>) -> Option> { - match this.resolve_name_in_module(module, needle, TypeNS, false, false, None) { + match this.resolve_name_in_module(module, needle, TypeNS, false, None) { Success(binding) if binding.is_extern_crate() => Some(module), _ => if let (&ModuleKind::Def(..), Some(parent)) = (&module.kind, module.parent) { search_parent_externals(this, needle, parent) @@ -1460,9 +1458,8 @@ impl<'a> Resolver<'a> { // modules as we go. while index < module_path_len { let name = module_path[index].name; - match self.resolve_name_in_module(search_module, name, TypeNS, false, false, span) { + match self.resolve_name_in_module(search_module, name, TypeNS, false, span) { Failed(_) => { - let segment_name = name.as_str(); let module_name = module_to_string(search_module); let msg = if "???" == &module_name { let current_module = self.current_module; @@ -1480,10 +1477,10 @@ impl<'a> Resolver<'a> { format!("Did you mean `{}{}`?", prefix, path_str) } - None => format!("Maybe a missing `extern crate {};`?", segment_name), + None => format!("Maybe a missing `extern crate {};`?", name), } } else { - format!("Could not find `{}` in `{}`", segment_name, module_name) + format!("Could not find `{}` in `{}`", name, module_name) }; return Failed(span.map(|span| (span, msg))); @@ -1617,7 +1614,7 @@ impl<'a> Resolver<'a> { if let ModuleRibKind(module) = self.ribs[ns][i].kind { let name = ident.name; - let item = self.resolve_name_in_module(module, name, ns, true, false, record_used); + let item = self.resolve_name_in_module(module, name, ns, false, record_used); if let Success(binding) = item { // The ident resolves to an item. return Some(LexicalScopeBinding::Item(binding)); @@ -1626,7 +1623,7 @@ impl<'a> Resolver<'a> { if let ModuleKind::Block(..) = module.kind { // We can see through blocks } else if !module.no_implicit_prelude { return self.prelude.and_then(|prelude| { - self.resolve_name_in_module(prelude, name, ns, false, false, None).success() + self.resolve_name_in_module(prelude, name, ns, false, None).success() }).map(LexicalScopeBinding::Item) } else { return None; @@ -1651,7 +1648,7 @@ impl<'a> Resolver<'a> { /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) * fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option) -> ResolveResult> { - if &*module_path[0].name.as_str() == "$crate" { + if module_path[0].name == "$crate" { return Success(PrefixFound(self.resolve_crate_var(module_path[0].ctxt), 1)); } @@ -1667,7 +1664,7 @@ impl<'a> Resolver<'a> { self.module_map[&self.current_module.normal_ancestor_id.unwrap()]; // Now loop through all the `super`s we find. - while i < module_path.len() && "super" == module_path[i].name.as_str() { + while i < module_path.len() && module_path[i].name == "super" { debug!("(resolving module prefix) resolving `super` at {}", module_to_string(&containing_module)); if let Some(parent) = containing_module.parent { @@ -2635,7 +2632,7 @@ impl<'a> Resolver<'a> { let qualified_binding = self.resolve_module_relative_path(span, segments, namespace); match (qualified_binding, unqualified_def) { (Ok(binding), Some(ref ud)) if binding.def() == ud.def && - segments[0].identifier.name.as_str() != "$crate" => { + segments[0].identifier.name != "$crate" => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, id, @@ -2772,7 +2769,7 @@ impl<'a> Resolver<'a> { }; let name = segments.last().unwrap().identifier.name; - let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span)); + let result = self.resolve_name_in_module(module, name, namespace, false, Some(span)); result.success().ok_or(false) } @@ -2800,7 +2797,7 @@ impl<'a> Resolver<'a> { }; let name = segments.last().unwrap().ident().name; - let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span)); + let result = self.resolve_name_in_module(module, name, namespace, false, Some(span)); result.success().ok_or(false) } @@ -2881,7 +2878,7 @@ impl<'a> Resolver<'a> { } fn find_best_match(&mut self, name: &str) -> SuggestionType { - if let Some(macro_name) = self.macro_names.iter().find(|n| n.as_str() == name) { + if let Some(macro_name) = self.macro_names.iter().find(|&n| n == &name) { return SuggestionType::Macro(format!("{}!", macro_name)); } @@ -2891,7 +2888,7 @@ impl<'a> Resolver<'a> { .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name)); if let Some(found) = find_best_match_for_name(names, name, None) { - if name != found { + if found != name { return SuggestionType::Function(found); } } SuggestionType::NotFound @@ -3000,8 +2997,7 @@ impl<'a> Resolver<'a> { false // Stop advancing }); - if method_scope && - &path_name[..] == keywords::SelfValue.name().as_str() { + if method_scope && keywords::SelfValue.name() == &*path_name { resolve_error(self, expr.span, ResolutionError::SelfNotAvailableInStaticMethod); @@ -3078,22 +3074,25 @@ impl<'a> Resolver<'a> { visit::walk_expr(self, expr); } - ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => { + ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { match self.search_label(label.node) { None => { self.record_def(expr.id, err_path_resolution()); resolve_error(self, label.span, - ResolutionError::UndeclaredLabel(&label.node.name.as_str())) + ResolutionError::UndeclaredLabel(&label.node.name.as_str())); } Some(def @ Def::Label(_)) => { // Since this def is a label, it is never read. - self.record_def(expr.id, PathResolution::new(def)) + self.record_def(expr.id, PathResolution::new(def)); } Some(_) => { - span_bug!(expr.span, "label wasn't mapped to a label def!") + span_bug!(expr.span, "label wasn't mapped to a label def!"); } } + + // visit `break` argument if any + visit::walk_expr(self, expr); } ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { @@ -3606,7 +3605,7 @@ fn module_to_string(module: Module) -> String { } } else { // danger, shouldn't be ident? - names.push(token::str_to_ident("")); + names.push(Ident::from_str("")); collect_mod(names, module.parent.unwrap()); } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 524d491a464e..62adf382a69a 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -27,7 +27,6 @@ use syntax::ext::expand::Expansion; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::fold::Folder; -use syntax::parse::token::intern; use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::Visitor; @@ -116,7 +115,7 @@ impl<'a> base::Resolver for Resolver<'a> { impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> { fn fold_path(&mut self, mut path: ast::Path) -> ast::Path { let ident = path.segments[0].identifier; - if &ident.name.as_str() == "$crate" { + if ident.name == "$crate" { path.global = true; let module = self.0.resolve_crate_var(ident.ctxt); if module.is_local() { @@ -152,7 +151,7 @@ impl<'a> base::Resolver for Resolver<'a> { } fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) { - if &def.ident.name.as_str() == "macro_rules" { + if def.ident.name == "macro_rules" { self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`"); } @@ -207,8 +206,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn find_attr_invoc(&mut self, attrs: &mut Vec) -> Option { for i in 0..attrs.len() { - let name = intern(&attrs[i].name()); - match self.builtin_macros.get(&name).cloned() { + match self.builtin_macros.get(&attrs[i].name()).cloned() { Some(binding) => match *self.get_macro(binding) { MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => { return Some(attrs.remove(i)) @@ -272,7 +270,7 @@ impl<'a> Resolver<'a> { loop { // Since expanded macros may not shadow the lexical scope (enforced below), // we can ignore unresolved invocations (indicated by the penultimate argument). - match self.resolve_name_in_module(module, name, ns, true, true, record_used) { + match self.resolve_name_in_module(module, name, ns, true, record_used) { Success(binding) => { let span = match record_used { Some(span) => span, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index d0ce1acaadf6..47bd1f71084a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -75,7 +75,6 @@ pub struct NameResolution<'a> { single_imports: SingleImports<'a>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option<&'a NameBinding<'a>>, - duplicate_globs: Vec<&'a NameBinding<'a>>, } #[derive(Clone, Debug)] @@ -141,7 +140,6 @@ impl<'a> Resolver<'a> { module: Module<'a>, name: Name, ns: Namespace, - allow_private_imports: bool, ignore_unresolved_invocations: bool, record_used: Option) -> ResolveResult<&'a NameBinding<'a>> { @@ -153,18 +151,8 @@ impl<'a> Resolver<'a> { _ => return Failed(None), // This happens when there is a cycle of imports }; - let new_import_semantics = self.new_import_semantics; - let is_disallowed_private_import = |binding: &NameBinding| { - !new_import_semantics && !allow_private_imports && // disallowed - binding.vis != ty::Visibility::Public && binding.is_import() && // non-`pub` import - !binding.is_extern_crate() // not an `extern crate` - }; - if let Some(span) = record_used { if let Some(binding) = resolution.binding { - if is_disallowed_private_import(binding) { - return Failed(None); - } if self.record_use(name, ns, binding, span) { return Success(self.dummy_binding); } @@ -177,9 +165,8 @@ impl<'a> Resolver<'a> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { - let usable = - this.is_accessible(binding.vis) && !is_disallowed_private_import(binding) || - binding.is_extern_crate(); // c.f. issue #37020 + // `extern crate` are always usable for backwards compatability, see issue #37020. + let usable = this.is_accessible(binding.vis) || binding.is_extern_crate(); if usable { Success(binding) } else { Failed(None) } }; @@ -202,7 +189,7 @@ impl<'a> Resolver<'a> { SingleImport { source, .. } => source, _ => unreachable!(), }; - match self.resolve_name_in_module(module, name, ns, true, false, None) { + match self.resolve_name_in_module(module, name, ns, false, None) { Failed(_) => {} _ => return Indeterminate, } @@ -224,7 +211,7 @@ impl<'a> Resolver<'a> { for directive in module.globs.borrow().iter() { if self.is_accessible(directive.vis.get()) { if let Some(module) = directive.imported_module.get() { - let result = self.resolve_name_in_module(module, name, ns, true, false, None); + let result = self.resolve_name_in_module(module, name, ns, false, None); if let Indeterminate = result { return Indeterminate; } @@ -311,10 +298,8 @@ impl<'a> Resolver<'a> { self.update_resolution(module, name, ns, |this, resolution| { if let Some(old_binding) = resolution.binding { if binding.is_glob_import() { - if !this.new_import_semantics { - resolution.duplicate_globs.push(binding); - } else if !old_binding.is_glob_import() && - !(ns == MacroNS && old_binding.expansion != Mark::root()) { + if !old_binding.is_glob_import() && + !(ns == MacroNS && old_binding.expansion != Mark::root()) { } else if binding.def() != old_binding.def() { resolution.binding = Some(this.ambiguity(old_binding, binding)); } else if !old_binding.vis.is_at_least(binding.vis, this) { @@ -322,11 +307,8 @@ impl<'a> Resolver<'a> { resolution.binding = Some(binding); } } else if old_binding.is_glob_import() { - if !this.new_import_semantics { - resolution.duplicate_globs.push(old_binding); - resolution.binding = Some(binding); - } else if ns == MacroNS && binding.expansion != Mark::root() && - binding.def() != old_binding.def() { + if ns == MacroNS && binding.expansion != Mark::root() && + binding.def() != old_binding.def() { resolution.binding = Some(this.ambiguity(binding, old_binding)); } else { resolution.binding = Some(binding); @@ -366,7 +348,7 @@ impl<'a> Resolver<'a> { let t = f(self, resolution); match resolution.binding() { - _ if !self.new_import_semantics && old_binding.is_some() => return t, + _ if old_binding.is_some() => return t, None => return t, Some(binding) => match old_binding { Some(old_binding) if old_binding as *const _ == binding as *const _ => return t, @@ -377,10 +359,7 @@ impl<'a> Resolver<'a> { // Define `binding` in `module`s glob importers. for directive in module.glob_importers.borrow_mut().iter() { - if match self.new_import_semantics { - true => self.is_accessible_from(binding.vis, directive.parent), - false => binding.vis == ty::Visibility::Public, - } { + if self.is_accessible_from(binding.vis, directive.parent) { let imported_binding = self.import(binding, directive); let _ = self.try_define(directive.parent, name, ns, imported_binding); } @@ -528,7 +507,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.per_ns(|this, ns| { if let Err(Undetermined) = result[ns].get() { result[ns].set({ - match this.resolve_name_in_module(module, source, ns, false, false, None) { + match this.resolve_name_in_module(module, source, ns, false, None) { Success(binding) => Ok(binding), Indeterminate => Err(Undetermined), Failed(_) => Err(Determined), @@ -624,7 +603,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if all_ns_err { let mut all_ns_failed = true; self.per_ns(|this, ns| { - match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) { + match this.resolve_name_in_module(module, name, ns, false, Some(span)) { Success(_) => all_ns_failed = false, _ => {} } @@ -729,8 +708,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { resolution.borrow().binding().map(|binding| (*name, binding)) }).collect::>(); for ((name, ns), binding) in bindings { - if binding.pseudo_vis() == ty::Visibility::Public || - self.new_import_semantics && self.is_accessible(binding.vis) { + if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) { let imported_binding = self.import(binding, directive); let _ = self.try_define(directive.parent, name, ns, imported_binding); } @@ -761,20 +739,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { None => continue, }; - // Report conflicts - if !self.new_import_semantics { - for duplicate_glob in resolution.duplicate_globs.iter() { - // FIXME #31337: We currently allow items to shadow glob-imported re-exports. - if !binding.is_import() { - if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind { - if binding.is_import() { continue } - } - } - - self.report_conflict(module, name, ns, duplicate_glob, binding); - } - } - if binding.vis == ty::Visibility::Public && (binding.is_import() || binding.is_extern_crate()) { let def = binding.def(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e83c2359979c..87b2b88fe33f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -39,7 +39,8 @@ use std::collections::hash_map::DefaultHasher; use std::hash::*; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; -use syntax::parse::token::{self, keywords}; +use syntax::parse::token; +use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{path_to_string, ty_to_string, bounds_to_string, generics_to_string}; use syntax::ptr::P; diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 778f01841416..bd5da588a864 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -54,7 +54,8 @@ use std::path::{Path, PathBuf}; use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; -use syntax::parse::token::{self, keywords, InternedString}; +use syntax::parse::token; +use syntax::symbol::{Symbol, keywords}; use syntax::visit::{self, Visitor}; use syntax::print::pprust::{ty_to_string, arg_to_string}; use syntax::codemap::MacroAttribute; @@ -119,7 +120,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } }; result.push(CrateData { - name: (&self.tcx.sess.cstore.crate_name(n)[..]).to_owned(), + name: self.tcx.sess.cstore.crate_name(n).to_string(), number: n.as_u32(), span: span, }); @@ -728,16 +729,16 @@ impl Visitor for PathCollector { } fn docs_for_attrs(attrs: &[Attribute]) -> String { - let doc = InternedString::new("doc"); + let doc = Symbol::intern("doc"); let mut result = String::new(); for attr in attrs { if attr.name() == doc { - if let Some(ref val) = attr.value_str() { - if attr.node.is_sugared_doc { - result.push_str(&strip_doc_comment_decoration(val)); + if let Some(val) = attr.value_str() { + if attr.is_sugared_doc { + result.push_str(&strip_doc_comment_decoration(&val.as_str())); } else { - result.push_str(val); + result.push_str(&val.as_str()); } result.push('\n'); } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 9ec764b82f86..e06aefd865f1 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -18,7 +18,8 @@ use std::path::Path; use syntax::ast; use syntax::parse::lexer::{self, Reader, StringReader}; -use syntax::parse::token::{self, keywords, Token}; +use syntax::parse::token::{self, Token}; +use syntax::symbol::keywords; use syntax_pos::*; #[derive(Clone)] diff --git a/src/librustc_trans/asm.rs b/src/librustc_trans/asm.rs index 8c704cc32993..665e12cbe879 100644 --- a/src/librustc_trans/asm.rs +++ b/src/librustc_trans/asm.rs @@ -88,7 +88,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, AsmDialect::Intel => llvm::AsmDialect::Intel, }; - let asm = CString::new(ia.asm.as_bytes()).unwrap(); + let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap(); let constraint_cstr = CString::new(all_constraints).unwrap(); let r = InlineAsmCall(bcx, asm.as_ptr(), diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs index 264ed4cd12fc..898e65ce391e 100644 --- a/src/librustc_trans/assert_module_sources.rs +++ b/src/librustc_trans/assert_module_sources.rs @@ -29,7 +29,6 @@ use rustc::ty::TyCtxt; use syntax::ast; -use syntax::parse::token::InternedString; use {ModuleSource, ModuleTranslation}; @@ -77,7 +76,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { } let mname = self.field(attr, MODULE); - let mtrans = self.modules.iter().find(|mtrans| &mtrans.name[..] == &mname[..]); + let mtrans = self.modules.iter().find(|mtrans| *mtrans.name == *mname.as_str()); let mtrans = match mtrans { Some(m) => m, None => { @@ -113,7 +112,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { } } - fn field(&self, attr: &ast::Attribute, name: &str) -> InternedString { + fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name { for item in attr.meta_item_list().unwrap_or(&[]) { if item.check_name(name) { if let Some(value) = item.value_str() { @@ -137,7 +136,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { let config = &self.tcx.sess.parse_sess.config; let value = self.field(attr, CFG); debug!("check_config(config={:?}, value={:?})", config, value); - if config.iter().any(|c| c.check_name(&value[..])) { + if config.iter().any(|&(name, _)| name == value) { debug!("check_config: matched"); return true; } diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs index df8dd7750ae0..11ab6dcaa87f 100644 --- a/src/librustc_trans/back/archive.rs +++ b/src/librustc_trans/back/archive.rs @@ -231,7 +231,7 @@ impl<'a> ArchiveBuilder<'a> { } fn llvm_archive_kind(&self) -> Result { - let kind = &self.config.sess.target.target.options.archive_format[..]; + let kind = &*self.config.sess.target.target.options.archive_format; kind.parse().map_err(|_| kind) } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 95d63311ee6e..648dc4c24c9a 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -19,7 +19,7 @@ use session::config::{OutputFilenames, Input, OutputType}; use session::filesearch; use session::search_paths::PathKind; use session::Session; -use middle::cstore::{self, LinkMeta, NativeLibrary}; +use middle::cstore::{self, LinkMeta, NativeLibrary, LibSource}; use middle::cstore::{LinkagePreference, NativeLibraryKind}; use middle::dependency_format::Linkage; use CrateTranslation; @@ -44,6 +44,7 @@ use std::str; use flate; use syntax::ast; use syntax::attr; +use syntax::symbol::Symbol; use syntax_pos::Span; // RLIB LLVM-BYTECODE OBJECT LAYOUT @@ -93,8 +94,8 @@ pub fn find_crate_name(sess: Option<&Session>, if let Some(sess) = sess { if let Some(ref s) = sess.opts.crate_name { - if let Some((attr, ref name)) = attr_crate_name { - if *s != &name[..] { + if let Some((attr, name)) = attr_crate_name { + if name != &**s { let msg = format!("--crate-name and #[crate_name] are \ required to match, but `{}` != `{}`", s, name); @@ -123,14 +124,13 @@ pub fn find_crate_name(sess: Option<&Session>, } "rust_out".to_string() - } pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap, name: &str) -> LinkMeta { let r = LinkMeta { - crate_name: name.to_owned(), + crate_name: Symbol::intern(name), crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()), }; info!("{:?}", r); @@ -263,6 +263,9 @@ pub fn filename_for_input(sess: &Session, config::CrateTypeRlib => { outputs.out_directory.join(&format!("lib{}.rlib", libname)) } + config::CrateTypeMetadata => { + outputs.out_directory.join(&format!("lib{}.rmeta", libname)) + } config::CrateTypeCdylib | config::CrateTypeProcMacro | config::CrateTypeDylib => { @@ -298,7 +301,7 @@ pub fn each_linked_rlib(sess: &Session, .or_else(|| fmts.get(&config::CrateTypeCdylib)) .or_else(|| fmts.get(&config::CrateTypeProcMacro)); let fmts = fmts.unwrap_or_else(|| { - bug!("could not find formats for rlibs") + bug!("could not find formats for rlibs"); }); for (cnum, path) in crates { match fmts[cnum.as_usize() - 1] { @@ -307,8 +310,12 @@ pub fn each_linked_rlib(sess: &Session, } let name = sess.cstore.crate_name(cnum).clone(); let path = match path { - Some(p) => p, - None => { + LibSource::Some(p) => p, + LibSource::MetadataOnly => { + sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file", + name)); + } + LibSource::None => { sess.fatal(&format!("could not find rlib for: `{}`", name)); } }; @@ -352,6 +359,9 @@ fn link_binary_output(sess: &Session, config::CrateTypeStaticlib => { link_staticlib(sess, &objects, &out_filename, tmpdir.path()); } + config::CrateTypeMetadata => { + emit_metadata(sess, trans, &out_filename); + } _ => { link_natively(sess, crate_type, &objects, &out_filename, trans, outputs, tmpdir.path()); @@ -390,6 +400,13 @@ fn archive_config<'a>(sess: &'a Session, } } +fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) { + let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata)); + if let Err(e) = result { + sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); + } +} + // Create an 'rlib' // // An rlib in its current incarnation is essentially a renamed .a file. The @@ -403,6 +420,7 @@ fn link_rlib<'a>(sess: &'a Session, tmpdir: &Path) -> ArchiveBuilder<'a> { info!("preparing rlib from {:?} to {:?}", objects, out_filename); let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None)); + for obj in objects { ab.add_file(obj); } @@ -429,7 +447,7 @@ fn link_rlib<'a>(sess: &'a Session, NativeLibraryKind::NativeFramework | NativeLibraryKind::NativeUnknown => continue, } - ab.add_native_library(&lib.name); + ab.add_native_library(&lib.name.as_str()); } // After adding all files to the archive, we need to update the @@ -464,15 +482,7 @@ fn link_rlib<'a>(sess: &'a Session, // here so concurrent builds in the same directory don't try to use // the same filename for metadata (stomping over one another) let metadata = tmpdir.join(sess.cstore.metadata_filename()); - match fs::File::create(&metadata).and_then(|mut f| { - f.write_all(&trans.metadata) - }) { - Ok(..) => {} - Err(e) => { - sess.fatal(&format!("failed to write {}: {}", - metadata.display(), e)); - } - } + emit_metadata(sess, trans, &metadata); ab.add_file(&metadata); // For LTO purposes, the bytecode of this library is also inserted @@ -615,7 +625,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, let skip_object_files = native_libs.iter().any(|lib| { lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib) }); - ab.add_rlib(path, &name, sess.lto(), skip_object_files).unwrap(); + ab.add_rlib(path, &name.as_str(), sess.lto(), skip_object_files).unwrap(); all_native_libs.extend(sess.cstore.native_libraries(cnum)); }); @@ -934,15 +944,15 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { // don't otherwise explicitly reference them. This can occur for // libraries which are just providing bindings, libraries with generic // functions, etc. - cmd.link_whole_staticlib(&l.name, &search_path); + cmd.link_whole_staticlib(&l.name.as_str(), &search_path); } cmd.hint_dynamic(); for lib in others { match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name), - NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name), + NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), + NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), NativeLibraryKind::NativeStatic => bug!(), } } @@ -1185,8 +1195,8 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { continue } match lib.kind { - NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name), - NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name), + NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), + NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), // ignore statically included native libraries here as we've // already included them when we included the rust library diff --git a/src/librustc_trans/back/rpath.rs b/src/librustc_trans/back/rpath.rs index 8758cdcf9d0a..ccaa0d4e1b1b 100644 --- a/src/librustc_trans/back/rpath.rs +++ b/src/librustc_trans/back/rpath.rs @@ -14,9 +14,10 @@ use std::path::{Path, PathBuf}; use std::fs; use rustc::hir::def_id::CrateNum; +use rustc::middle::cstore::LibSource; pub struct RPathConfig<'a> { - pub used_crates: Vec<(CrateNum, Option)>, + pub used_crates: Vec<(CrateNum, LibSource)>, pub out_filename: PathBuf, pub is_like_osx: bool, pub has_rpath: bool, @@ -35,7 +36,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec { debug!("preparing the RPATH!"); let libs = config.used_crates.clone(); - let libs = libs.into_iter().filter_map(|(_, l)| l).collect::>(); + let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::>(); let rpaths = get_rpaths(config, &libs[..]); flags.extend_from_slice(&rpaths_to_flags(&rpaths[..])); diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs index 0ad663f05b48..ff40cfda5ff7 100644 --- a/src/librustc_trans/back/symbol_names.rs +++ b/src/librustc_trans/back/symbol_names.rs @@ -113,7 +113,7 @@ use rustc::hir::map::definitions::{DefPath, DefPathData}; use rustc::util::common::record_time; use syntax::attr; -use syntax::parse::token::{self, InternedString}; +use syntax::symbol::{Symbol, InternedString}; fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, @@ -275,7 +275,7 @@ impl ItemPathBuffer for SymbolPathBuffer { } fn push(&mut self, text: &str) { - self.names.push(token::intern(text).as_str()); + self.names.push(Symbol::intern(text).as_str()); } } @@ -288,7 +288,7 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, krate: LOCAL_CRATE, }; let hash = get_symbol_hash(scx, &empty_def_path, t, None); - let path = [token::intern_and_get_ident(prefix)]; + let path = [Symbol::intern(prefix).as_str()]; mangle(path.iter().cloned(), &hash) } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 0c0b7fbf4afe..4353c7bd5864 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1128,11 +1128,11 @@ pub fn set_link_section(ccx: &CrateContext, llval: ValueRef, attrs: &[ast::Attribute]) { if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") { - if contains_null(§) { + if contains_null(§.as_str()) { ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §)); } unsafe { - let buf = CString::new(sect.as_bytes()).unwrap(); + let buf = CString::new(sect.as_str().as_bytes()).unwrap(); llvm::LLVMSetSection(llval, buf.as_ptr()); } } @@ -1260,7 +1260,8 @@ fn write_metadata(cx: &SharedCrateContext, config::CrateTypeStaticlib | config::CrateTypeCdylib => MetadataKind::None, - config::CrateTypeRlib => MetadataKind::Uncompressed, + config::CrateTypeRlib | + config::CrateTypeMetadata => MetadataKind::Uncompressed, config::CrateTypeDylib | config::CrateTypeProcMacro => MetadataKind::Compressed, @@ -1600,7 +1601,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert_module_sources::assert_module_sources(tcx, &modules); // Skip crate items and just output metadata in -Z no-trans mode. - if tcx.sess.opts.debugging_opts.no_trans { + if tcx.sess.opts.debugging_opts.no_trans || + tcx.sess.crate_types.borrow().iter().all(|ct| ct == &config::CrateTypeMetadata) { let linker_info = LinkerInfo::new(&shared_ccx, &[]); return CrateTranslation { modules: modules, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 5902b0b1ce07..5c7b004375ed 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -663,7 +663,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { -> bool { (bare_fn_ty.abi == Abi::RustIntrinsic || bare_fn_ty.abi == Abi::PlatformIntrinsic) && - tcx.item_name(def_id).as_str() == "drop_in_place" + tcx.item_name(def_id) == "drop_in_place" } } } diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index df70a6e81166..29925d964da2 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -52,8 +52,7 @@ use std::ffi::CString; use std::cell::{Cell, RefCell, Ref}; use syntax::ast; -use syntax::parse::token::InternedString; -use syntax::parse::token; +use syntax::symbol::{Symbol, InternedString}; use syntax_pos::{DUMMY_SP, Span}; pub use context::{CrateContext, SharedCrateContext}; @@ -225,7 +224,7 @@ impl<'a, 'tcx> VariantInfo<'tcx> { VariantInfo { discr: Disr(0), fields: v.iter().enumerate().map(|(i, &t)| { - Field(token::intern(&i.to_string()), t) + Field(Symbol::intern(&i.to_string()), t) }).collect() } } diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 670a84565faf..4186721c122a 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -123,7 +123,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef { // extern "C" fn() from being non-null, so we can't just declare a // static and call it a day. Some linkages (like weak) will make it such // that the static actually has a null value. - let linkage = match base::llvm_linkage_by_name(&name) { + let linkage = match base::llvm_linkage_by_name(&name.as_str()) { Some(linkage) => linkage, None => { ccx.sess().span_fatal(span, "invalid linkage specified"); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 7657fc7d1c8b..771c5ef6d9d2 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -42,7 +42,7 @@ use std::ptr; use std::rc::Rc; use std::str; use syntax::ast; -use syntax::parse::token::InternedString; +use syntax::symbol::InternedString; use abi::FnType; pub struct Stats { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 5b9ef78ddc22..5d01ca892b31 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -44,10 +44,8 @@ use std::ffi::CString; use std::fmt::Write; use std::path::Path; use std::ptr; -use std::rc::Rc; -use syntax::util::interner::Interner; use syntax::ast; -use syntax::parse::token; +use syntax::symbol::{Interner, InternedString}; use syntax_pos::{self, Span}; @@ -117,9 +115,8 @@ impl<'tcx> TypeMap<'tcx> { unique_type_id: UniqueTypeId, metadata: DIType) { if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { - let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id); bug!("Type metadata for unique id '{}' is already in the TypeMap!", - &unique_type_id_str[..]); + self.get_unique_type_id_as_string(unique_type_id)); } } @@ -133,7 +130,7 @@ impl<'tcx> TypeMap<'tcx> { // Get the string representation of a UniqueTypeId. This method will fail if // the id is unknown. - fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc { + fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str { let UniqueTypeId(interner_key) = unique_type_id; self.unique_id_interner.get(interner_key) } @@ -182,7 +179,7 @@ impl<'tcx> TypeMap<'tcx> { -> UniqueTypeId { let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type); let enum_variant_type_id = format!("{}::{}", - &self.get_unique_type_id_as_string(enum_type_id), + self.get_unique_type_id_as_string(enum_type_id), variant_name); let interner_key = self.unique_id_interner.intern(&enum_variant_type_id); UniqueTypeId(interner_key) @@ -623,14 +620,12 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { Some(metadata) => metadata, None => { - let unique_type_id_str = - type_map.get_unique_type_id_as_string(unique_type_id); span_bug!(usage_site_span, "Expected type metadata for unique \ type id '{}' to already be in \ the debuginfo::TypeMap but it \ was not. (Ty = {})", - &unique_type_id_str[..], + type_map.get_unique_type_id_as_string(unique_type_id), t); } }; @@ -638,14 +633,12 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, match type_map.find_metadata_for_type(t) { Some(metadata) => { if metadata != metadata_for_uid { - let unique_type_id_str = - type_map.get_unique_type_id_as_string(unique_type_id); span_bug!(usage_site_span, "Mismatch between Ty and \ UniqueTypeId maps in \ debuginfo::TypeMap. \ UniqueTypeId={}, Ty={}", - &unique_type_id_str[..], + type_map.get_unique_type_id_as_string(unique_type_id), t); } } @@ -809,7 +802,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, }; fn fallback_path(scc: &SharedCrateContext) -> CString { - CString::new(scc.link_meta().crate_name.clone()).unwrap() + CString::new(scc.link_meta().crate_name.to_string()).unwrap() } } @@ -1526,13 +1519,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let enum_llvm_type = type_of::type_of(cx, enum_type); let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type); - let unique_type_id_str = debug_context(cx) - .type_map - .borrow() - .get_unique_type_id_as_string(unique_type_id); - let enum_name = CString::new(enum_name).unwrap(); - let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap(); + let unique_type_id_str = CString::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() + ).unwrap(); let enum_metadata = unsafe { llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), @@ -1566,7 +1556,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn get_enum_discriminant_name(cx: &CrateContext, def_id: DefId) - -> token::InternedString { + -> InternedString { cx.tcx().item_name(def_id).as_str() } } @@ -1669,11 +1659,10 @@ fn create_struct_stub(cx: &CrateContext, -> DICompositeType { let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type); - let unique_type_id_str = debug_context(cx).type_map - .borrow() - .get_unique_type_id_as_string(unique_type_id); let name = CString::new(struct_type_name).unwrap(); - let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap(); + let unique_type_id = CString::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() + ).unwrap(); let metadata_stub = unsafe { // LLVMRustDIBuilderCreateStructType() wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions @@ -1707,11 +1696,10 @@ fn create_union_stub(cx: &CrateContext, -> DICompositeType { let (union_size, union_align) = size_and_align_of(cx, union_llvm_type); - let unique_type_id_str = debug_context(cx).type_map - .borrow() - .get_unique_type_id_as_string(unique_type_id); let name = CString::new(union_type_name).unwrap(); - let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap(); + let unique_type_id = CString::new( + debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() + ).unwrap(); let metadata_stub = unsafe { // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 5953ec4aaedf..a0477c9fc1ee 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -35,7 +35,7 @@ pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> S } let name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(), data => data.as_interned_str() }; @@ -64,7 +64,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { }); let namespace_name = match def_key.disambiguated_data.data { - DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(), data => data.as_interned_str() }; diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 956402edc116..fce1ce561055 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -156,7 +156,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, qualified: bool, output: &mut String) { if qualified { - output.push_str(&cx.tcx().crate_name(def_id.krate)); + output.push_str(&cx.tcx().crate_name(def_id.krate).as_str()); for path_element in cx.tcx().def_path(def_id).data { output.push_str("::"); output.push_str(&path_element.data.as_interned_str()); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index b1b09d3ca20d..016a76a72531 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -30,7 +30,7 @@ use rustc::ty::{self, Ty}; use Disr; use rustc::hir; use syntax::ast; -use syntax::parse::token; +use syntax::symbol::Symbol; use rustc::session::Session; use syntax_pos::{Span, DUMMY_SP}; @@ -107,7 +107,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let sig = tcx.erase_late_bound_regions_and_normalize(&fty.sig); let arg_tys = sig.inputs; let ret_ty = sig.output; - let name = tcx.item_name(def_id).as_str(); + let name = &*tcx.item_name(def_id).as_str(); let span = match call_debug_location { DebugLoc::ScopeAt(_, span) => span, @@ -123,15 +123,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Call(bcx, llfn, &[], call_debug_location); Unreachable(bcx); return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to())); - } else if &name[..] == "unreachable" { + } else if name == "unreachable" { Unreachable(bcx); return Result::new(bcx, C_nil(ccx)); } let llret_ty = type_of::type_of(ccx, ret_ty); - let simple = get_simple_intrinsic(ccx, &name); - let llval = match (simple, &name[..]) { + let simple = get_simple_intrinsic(ccx, name); + let llval = match (simple, name) { (Some(llfn), _) => { Call(bcx, llfn, &llargs, call_debug_location) } @@ -208,7 +208,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } (_, "type_name") => { let tp_ty = substs.type_at(0); - let ty_name = token::intern_and_get_ident(&tp_ty.to_string()); + let ty_name = Symbol::intern(&tp_ty.to_string()).as_str(); C_str_slice(ccx, ty_name) } (_, "type_id") => { @@ -340,7 +340,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let sty = &arg_tys[0].sty; match int_type_width_signed(sty, ccx) { Some((width, signed)) => - match &*name { + match name { "ctlz" => count_zeros_intrinsic(bcx, &format!("llvm.ctlz.i{}", width), llargs[0], call_debug_location), "cttz" => count_zeros_intrinsic(bcx, &format!("llvm.cttz.i{}", width), @@ -394,7 +394,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let sty = &arg_tys[0].sty; match float_type_width(sty) { Some(_width) => - match &*name { + match name { "fadd_fast" => FAddFast(bcx, llargs[0], llargs[1], call_debug_location), "fsub_fast" => FSubFast(bcx, llargs[0], llargs[1], call_debug_location), "fmul_fast" => FMulFast(bcx, llargs[0], llargs[1], call_debug_location), diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index b22bcf9825a2..29e6f6af416b 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -30,7 +30,7 @@ use glue; use type_::Type; use rustc_data_structures::fx::FxHashMap; -use syntax::parse::token; +use syntax::symbol::Symbol; use super::{MirContext, LocalRef}; use super::analyze::CleanupKind; @@ -116,6 +116,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { if let Some(cleanup_pad) = cleanup_pad { bcx.cleanup_ret(cleanup_pad, None); } else { + let llpersonality = bcx.fcx().eh_personality(); + bcx.set_personality_fn(llpersonality); + let ps = self.get_personality_slot(&bcx); let lp = bcx.load(ps); bcx.with_block(|bcx| { @@ -321,7 +324,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { // Get the location information. let loc = bcx.sess().codemap().lookup_char_pos(span.lo); - let filename = token::intern_and_get_ident(&loc.file.name); + let filename = Symbol::intern(&loc.file.name).as_str(); let filename = C_str_slice(bcx.ccx(), filename); let line = C_u32(bcx.ccx(), loc.line as u32); @@ -351,7 +354,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { const_err) } mir::AssertMessage::Math(ref err) => { - let msg_str = token::intern_and_get_ident(err.description()); + let msg_str = Symbol::intern(err.description()).as_str(); let msg_str = C_str_slice(bcx.ccx(), msg_str); let msg_file_line = C_struct(bcx.ccx(), &[msg_str, filename, line], diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index 12b17c26cbc4..12cbfcef7d26 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -21,7 +21,7 @@ use machine; use type_of; use syntax_pos::{DUMMY_SP, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos}; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use std::cell::Ref; use std::iter; diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 09a1cbd319ac..a36960993e47 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -132,7 +132,7 @@ use std::sync::Arc; use std::collections::hash_map::DefaultHasher; use symbol_map::SymbolMap; use syntax::ast::NodeId; -use syntax::parse::token::{self, InternedString}; +use syntax::symbol::{Symbol, InternedString}; use trans_item::TransItem; use util::nodemap::{FxHashMap, FxHashSet}; @@ -272,7 +272,7 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { - merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]); + merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str()); debug_dump(scx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } @@ -320,7 +320,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, let codegen_unit_name = match characteristic_def_id { Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile), - None => InternedString::new(FALLBACK_CODEGEN_UNIT), + None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(), }; let make_codegen_unit = || { @@ -365,7 +365,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, // always ensure we have at least one CGU; otherwise, if we have a // crate with just types (for example), we could wind up with no CGU if codegen_units.is_empty() { - let codegen_unit_name = InternedString::new(FALLBACK_CODEGEN_UNIT); + let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(); codegen_units.entry(codegen_unit_name.clone()) .or_insert_with(|| CodegenUnit::empty(codegen_unit_name.clone())); } @@ -523,7 +523,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut mod_path = String::with_capacity(64); let def_path = tcx.def_path(def_id); - mod_path.push_str(&tcx.crate_name(def_path.krate)); + mod_path.push_str(&tcx.crate_name(def_path.krate).as_str()); for part in tcx.def_path(def_id) .data @@ -542,14 +542,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mod_path.push_str(".volatile"); } - return token::intern_and_get_ident(&mod_path[..]); + return Symbol::intern(&mod_path[..]).as_str(); } fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString { - token::intern_and_get_ident(&format!("{}{}{}", - crate_name, - NUMBERED_CODEGEN_UNIT_MARKER, - index)[..]) + Symbol::intern(&format!("{}{}{}", crate_name, NUMBERED_CODEGEN_UNIT_MARKER, index)).as_str() } fn debug_dump<'a, 'b, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 7fa59127704d..f2d1e375793b 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -285,7 +285,7 @@ impl<'a, 'tcx> TransItem<'tcx> { let attributes = tcx.get_attrs(def_id); if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") { - if let Some(linkage) = base::llvm_linkage_by_name(&name) { + if let Some(linkage) = base::llvm_linkage_by_name(&name.as_str()) { Some(linkage) } else { let span = tcx.map.span_if_local(def_id); @@ -531,7 +531,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { // some_crate:: if !(self.omit_local_crate_name && def_id.is_local()) { - output.push_str(&self.tcx.crate_name(def_path.krate)); + output.push_str(&self.tcx.crate_name(def_path.krate).as_str()); output.push_str("::"); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9bde6b0c4d99..c5db8bc8cedc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -71,7 +71,7 @@ use util::nodemap::{NodeMap, FxHashSet}; use std::cell::RefCell; use syntax::{abi, ast}; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::parse::token::{self, keywords}; +use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, Pos}; use errors::DiagnosticBuilder; @@ -645,7 +645,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { }; let output_binding = ConvertedBinding { - item_name: token::intern(FN_OUTPUT_NAME), + item_name: Symbol::intern(FN_OUTPUT_NAME), ty: output, span: output_span }; @@ -1252,7 +1252,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { if bounds.len() > 1 { let spans = bounds.iter().map(|b| { self.tcx().associated_items(b.def_id()).find(|item| { - item.kind == ty::AssociatedKind::Type && item.name.as_str() == assoc_name + item.kind == ty::AssociatedKind::Type && item.name == assoc_name }) .and_then(|item| self.tcx().map.as_local_node_id(item.def_id)) .and_then(|node_id| self.tcx().map.opt_span(node_id)) diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 900c22a8176e..e72dba858c56 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -20,7 +20,7 @@ use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::hir; use syntax_pos::Span; -use syntax::parse::token; +use syntax::symbol::Symbol; #[derive(Copy, Clone, Debug)] enum AutoderefKind { @@ -120,7 +120,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { let normalized = traits::normalize_projection_type(&mut selcx, ty::ProjectionTy { trait_ref: trait_ref, - item_name: token::intern("Target"), + item_name: Symbol::intern("Target"), }, cause, 0); @@ -198,7 +198,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (PreferMutLvalue, Some(trait_did)) => { self.lookup_method_in_trait(span, base_expr, - token::intern("deref_mut"), + Symbol::intern("deref_mut"), trait_did, base_ty, None) @@ -211,7 +211,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (None, Some(trait_did)) => { self.lookup_method_in_trait(span, base_expr, - token::intern("deref"), + Symbol::intern("deref"), trait_did, base_ty, None) diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7606a5b7a4d4..3ffbbd1be801 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -16,8 +16,7 @@ use hir::def_id::{DefId, LOCAL_CRATE}; use hir::print; use rustc::{infer, traits}; use rustc::ty::{self, LvaluePreference, Ty}; -use syntax::parse::token; -use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; use rustc::hir; @@ -46,7 +45,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_call(&self, call_expr: &'gcx hir::Expr, callee_expr: &'gcx hir::Expr, - arg_exprs: &'gcx [P], + arg_exprs: &'gcx [hir::Expr], expected: Expectation<'tcx>) -> Ty<'tcx> { let original_callee_ty = self.check_expr(callee_expr); @@ -160,9 +159,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> Option> { // Try the options that are least restrictive on the caller first. for &(opt_trait_def_id, method_name) in - &[(self.tcx.lang_items.fn_trait(), token::intern("call")), - (self.tcx.lang_items.fn_mut_trait(), token::intern("call_mut")), - (self.tcx.lang_items.fn_once_trait(), token::intern("call_once"))] { + &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call")), + (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut")), + (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"))] { let trait_def_id = match opt_trait_def_id { Some(def_id) => def_id, None => continue, @@ -189,7 +188,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn confirm_builtin_call(&self, call_expr: &hir::Expr, callee_ty: Ty<'tcx>, - arg_exprs: &'gcx [P], + arg_exprs: &'gcx [hir::Expr], expected: Expectation<'tcx>) -> Ty<'tcx> { let error_fn_sig; @@ -272,7 +271,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn confirm_deferred_closure_call(&self, call_expr: &hir::Expr, - arg_exprs: &'gcx [P], + arg_exprs: &'gcx [hir::Expr], expected: Expectation<'tcx>, fn_sig: ty::FnSig<'tcx>) -> Ty<'tcx> { @@ -299,7 +298,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn confirm_overloaded_call(&self, call_expr: &hir::Expr, callee_expr: &'gcx hir::Expr, - arg_exprs: &'gcx [P], + arg_exprs: &'gcx [hir::Expr], expected: Expectation<'tcx>, method_callee: ty::MethodCallee<'tcx>) -> Ty<'tcx> { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 77106b8b0c3a..a07573a7b9ea 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -21,7 +21,7 @@ use {CrateCtxt, require_same_types}; use syntax::abi::Abi; use syntax::ast; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax_pos::Span; use rustc::hir; @@ -75,7 +75,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, /// and in libcore/intrinsics.rs pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { - let name = token::intern(&format!("P{}", n)); + let name = Symbol::intern(&format!("P{}", n)); ccx.tcx.mk_param(n, name) } @@ -326,7 +326,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { let param = |n| { - let name = token::intern(&format!("P{}", n)); + let name = Symbol::intern(&format!("P{}", n)); ccx.tcx.mk_param(n, name) }; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 66a532fd76ac..bd34e993e1e8 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -342,7 +342,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let def = pick.item.def(); if let probe::InherentImplPick = pick.kind { if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) { - let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str()); + let msg = format!("{} `{}` is private", def.kind_name(), method_name); self.tcx.sess.span_err(span, &msg); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f08178e49fb2..eeb7bb287002 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,7 +103,7 @@ use session::{Session, CompileResult}; use CrateCtxt; use TypeAndSubsts; use lint; -use util::common::{block_query, ErrorReported, indenter, loop_query}; +use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap}; use std::cell::{Cell, Ref, RefCell}; @@ -115,8 +115,8 @@ use syntax::ast; use syntax::attr; use syntax::codemap::{self, original_sp, Spanned}; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::parse::token::{self, InternedString, keywords}; use syntax::ptr::P; +use syntax::symbol::{Symbol, InternedString, keywords}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{self, BytePos, Span}; @@ -407,6 +407,34 @@ impl Diverges { } } +#[derive(Clone)] +pub struct LoopCtxt<'gcx, 'tcx> { + unified: Ty<'tcx>, + coerce_to: Ty<'tcx>, + break_exprs: Vec<&'gcx hir::Expr>, + may_break: bool, +} + +#[derive(Clone)] +pub struct EnclosingLoops<'gcx, 'tcx> { + stack: Vec>, + by_id: NodeMap, +} + +impl<'gcx, 'tcx> EnclosingLoops<'gcx, 'tcx> { + fn find_loop(&mut self, id: Option) -> Option<&mut LoopCtxt<'gcx, 'tcx>> { + if let Some(id) = id { + if let Some(ix) = self.by_id.get(&id).cloned() { + Some(&mut self.stack[ix]) + } else { + None + } + } else { + self.stack.last_mut() + } + } +} + #[derive(Clone)] pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { ast_ty_to_ty_cache: RefCell>>, @@ -433,6 +461,8 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// Whether any child nodes have any type errors. has_errors: Cell, + enclosing_loops: RefCell>, + inh: &'a Inherited<'a, 'gcx, 'tcx>, } @@ -931,7 +961,8 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, if let Some(ref attr) = item.attrs.iter().find(|a| { a.check_name("rustc_on_unimplemented") }) { - if let Some(ref istring) = attr.value_str() { + if let Some(istring) = attr.value_str() { + let istring = istring.as_str(); let parser = Parser::new(&istring); let types = &generics.types; for token in parser { @@ -942,7 +973,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, Position::ArgumentNamed(s) if s == "Self" => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match types.iter().find(|t| { - t.name.as_str() == s + t.name == s }) { Some(_) => (), None => { @@ -1502,6 +1533,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ast::CRATE_NODE_ID)), diverges: Cell::new(Diverges::Maybe), has_errors: Cell::new(false), + enclosing_loops: RefCell::new(EnclosingLoops { + stack: Vec::new(), + by_id: NodeMap(), + }), inh: inh, } } @@ -2369,7 +2404,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (PreferMutLvalue, Some(trait_did)) => { self.lookup_method_in_trait_adjusted(expr.span, Some(&base_expr), - token::intern("index_mut"), + Symbol::intern("index_mut"), trait_did, autoderefs, unsize, @@ -2384,7 +2419,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (None, Some(trait_did)) => { self.lookup_method_in_trait_adjusted(expr.span, Some(&base_expr), - token::intern("index"), + Symbol::intern("index"), trait_did, autoderefs, unsize, @@ -2408,7 +2443,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { sp: Span, method_fn_ty: Ty<'tcx>, callee_expr: &'gcx hir::Expr, - args_no_rcvr: &'gcx [P], + args_no_rcvr: &'gcx [hir::Expr], tuple_arguments: TupleArgumentsFlag, expected: Expectation<'tcx>) -> Ty<'tcx> { @@ -2447,7 +2482,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { sp: Span, fn_inputs: &[Ty<'tcx>], expected_arg_tys: &[Ty<'tcx>], - args: &'gcx [P], + args: &'gcx [hir::Expr], variadic: bool, tuple_arguments: TupleArgumentsFlag) { let tcx = self.tcx; @@ -2821,7 +2856,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn check_method_call(&self, expr: &'gcx hir::Expr, method_name: Spanned, - args: &'gcx [P], + args: &'gcx [hir::Expr], tps: &[P], expected: Expectation<'tcx>, lvalue_pref: LvaluePreference) -> Ty<'tcx> { @@ -3027,7 +3062,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn suggest_field_name(variant: ty::VariantDef<'tcx>, field: &Spanned, skip : Vec) - -> Option { + -> Option { let name = field.node.as_str(); let names = variant.fields.iter().filter_map(|field| { // ignore already set fields and private fields from non-local crates @@ -3126,7 +3161,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::TyAdt(adt, ..) if adt.is_enum() => { struct_span_err!(self.tcx.sess, field.name.span, E0559, "{} `{}::{}` has no field named `{}`", - kind_name, actual, variant.name.as_str(), field.name.node) + kind_name, actual, variant.name, field.name.node) } _ => { struct_span_err!(self.tcx.sess, field.name.span, E0560, @@ -3146,7 +3181,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyAdt(adt, ..) if adt.is_enum() => { err.span_label(field.name.span, &format!("`{}::{}` does not have this field", - ty, variant.name.as_str())); + ty, variant.name)); } _ => { err.span_label(field.name.span, &format!("`{}` does not have this field", ty)); @@ -3583,7 +3618,74 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.mk_nil() } - hir::ExprBreak(_) => { tcx.types.never } + hir::ExprBreak(ref label_opt, ref expr_opt) => { + let loop_id = if label_opt.is_some() { + let loop_def = tcx.expect_def(expr.id); + if let Def::Label(loop_id) = loop_def { + Some(Some(loop_id)) + } else if loop_def == Def::Err { + // an error was already printed, so just ignore it + None + } else { + span_bug!(expr.span, "break label resolved to a non-label"); + } + } else { + Some(None) + }; + if let Some(loop_id) = loop_id { + let coerce_to = { + let mut enclosing_loops = self.enclosing_loops.borrow_mut(); + enclosing_loops.find_loop(loop_id).map(|ctxt| ctxt.coerce_to) + }; + if let Some(coerce_to) = coerce_to { + let e_ty; + let cause; + if let Some(ref e) = *expr_opt { + // Recurse without `enclosing_loops` borrowed. + e_ty = self.check_expr_with_hint(e, coerce_to); + cause = self.misc(e.span); + // Notably, the recursive call may alter coerce_to - must not keep using it! + } else { + // `break` without argument acts like `break ()`. + e_ty = tcx.mk_nil(); + cause = self.misc(expr.span); + } + let mut enclosing_loops = self.enclosing_loops.borrow_mut(); + let ctxt = enclosing_loops.find_loop(loop_id).unwrap(); + + let result = if let Some(ref e) = *expr_opt { + // Special-case the first element, as it has no "previous expressions". + let result = if !ctxt.may_break { + self.try_coerce(e, e_ty, ctxt.coerce_to) + } else { + self.try_find_coercion_lub(&cause, || ctxt.break_exprs.iter().cloned(), + ctxt.unified, e, e_ty) + }; + + ctxt.break_exprs.push(e); + result + } else { + self.eq_types(true, &cause, e_ty, ctxt.unified) + .map(|InferOk { obligations, .. }| { + // FIXME(#32730) propagate obligations + assert!(obligations.is_empty()); + e_ty + }) + }; + match result { + Ok(ty) => ctxt.unified = ty, + Err(err) => { + self.report_mismatched_types(&cause, ctxt.unified, e_ty, err); + } + } + + ctxt.may_break = true; + } + // Otherwise, we failed to find the enclosing loop; this can only happen if the + // `break` was not inside a loop at all, which is caught by the loop-checking pass. + } + tcx.types.never + } hir::ExprAgain(_) => { tcx.types.never } hir::ExprRet(ref expr_opt) => { if let Some(ref e) = *expr_opt { @@ -3634,12 +3736,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expr.span, expected) } hir::ExprWhile(ref cond, ref body, _) => { - self.check_expr_has_type(&cond, tcx.types.bool); - let cond_diverging = self.diverges.get(); - self.check_block_no_value(&body); + let unified = self.tcx.mk_nil(); + let coerce_to = unified; + let ctxt = LoopCtxt { + unified: unified, + coerce_to: coerce_to, + break_exprs: vec![], + may_break: true, + }; + self.with_loop_ctxt(expr.id, ctxt, || { + self.check_expr_has_type(&cond, tcx.types.bool); + let cond_diverging = self.diverges.get(); + self.check_block_no_value(&body); - // We may never reach the body so it diverging means nothing. - self.diverges.set(cond_diverging); + // We may never reach the body so it diverging means nothing. + self.diverges.set(cond_diverging); + }); if self.has_errors.get() { tcx.types.err @@ -3647,14 +3759,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_nil() } } - hir::ExprLoop(ref body, _) => { - self.check_block_no_value(&body); - if may_break(tcx, expr.id, &body) { + hir::ExprLoop(ref body, _, _) => { + let unified = self.next_ty_var(); + let coerce_to = expected.only_has_type(self).unwrap_or(unified); + let ctxt = LoopCtxt { + unified: unified, + coerce_to: coerce_to, + break_exprs: vec![], + may_break: false, + }; + + let ctxt = self.with_loop_ctxt(expr.id, ctxt, || { + self.check_block_no_value(&body); + }); + if ctxt.may_break { // No way to know whether it's diverging because // of a `break` or an outer `break` or `return. self.diverges.set(Diverges::Maybe); - tcx.mk_nil() + ctxt.unified } else { tcx.types.never } @@ -3669,10 +3792,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_block_with_expected(&b, expected) } hir::ExprCall(ref callee, ref args) => { - self.check_call(expr, &callee, &args[..], expected) + self.check_call(expr, &callee, args, expected) } hir::ExprMethodCall(name, ref tps, ref args) => { - self.check_method_call(expr, name, &args[..], &tps[..], expected, lvalue_pref) + self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref) } hir::ExprCast(ref e, ref t) => { if let hir::TyArray(_, ref count_expr) = t.node { @@ -3727,7 +3850,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let result = if i == 0 { self.try_coerce(e, e_ty, coerce_to) } else { - let prev_elems = || args[..i].iter().map(|e| &**e); + let prev_elems = || args[..i].iter().map(|e| &*e); self.try_find_coercion_lub(&cause, prev_elems, unified, e, e_ty) }; @@ -4436,19 +4559,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions); if lifetimes.len() > lifetime_defs.len() { let span = lifetimes[lifetime_defs.len()].span; - span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); - } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() { - span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - count(lifetime_defs.len()), - count(lifetimes.len())); + struct_span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected {}, found {}", + count(lifetime_defs.len()), + count(lifetimes.len())) + .span_label(span, &format!("unexpected lifetime parameter{}", + match lifetimes.len() { 1 => "", _ => "s" })) + .emit(); } + // The case where there is not enough lifetime parameters is not checked, + // because this is not possible - a function never takes lifetime parameters. + // See discussion for Pull Request 36208. + // Check provided type parameters. let type_defs = segment.map_or(&[][..], |(_, generics)| { if generics.parent.is_none() { @@ -4529,27 +4653,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.tcx.types.err }) } -} -// Returns true if b contains a break that can exit from b -pub fn may_break(tcx: TyCtxt, id: ast::NodeId, b: &hir::Block) -> bool { - // First: is there an unlabeled break immediately - // inside the loop? - (loop_query(&b, |e| { - match *e { - hir::ExprBreak(None) => true, - _ => false + fn with_loop_ctxt(&self, id: ast::NodeId, ctxt: LoopCtxt<'gcx, 'tcx>, f: F) + -> LoopCtxt<'gcx, 'tcx> { + let index; + { + let mut enclosing_loops = self.enclosing_loops.borrow_mut(); + index = enclosing_loops.stack.len(); + enclosing_loops.by_id.insert(id, index); + enclosing_loops.stack.push(ctxt); } - })) || - // Second: is there a labeled break with label - // nested anywhere inside the loop? - (block_query(b, |e| { - if let hir::ExprBreak(Some(_)) = e.node { - tcx.expect_def(e.id) == Def::Label(id) - } else { - false + f(); + { + let mut enclosing_loops = self.enclosing_loops.borrow_mut(); + debug_assert!(enclosing_loops.stack.len() == index + 1); + enclosing_loops.by_id.remove(&id).expect("missing loop context"); + (enclosing_loops.stack.pop().expect("missing loop context")) } - })) + } } pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 8b4975b7e3a2..adb8c6be42bc 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -14,7 +14,7 @@ use super::FnCtxt; use hir::def_id::DefId; use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue}; use syntax::ast; -use syntax::parse::token; +use syntax::symbol::Symbol; use rustc::hir; impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { @@ -182,7 +182,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let rhs_ty_var = self.next_ty_var(); let return_ty = match self.lookup_op_method(expr, lhs_ty, vec![rhs_ty_var], - token::intern(name), trait_def_id, + Symbol::intern(name), trait_def_id, lhs_expr) { Ok(return_ty) => return_ty, Err(()) => { @@ -248,9 +248,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method(ex, operand_ty, vec![], - token::intern(mname), trait_did, - operand_expr) { + let mname = Symbol::intern(mname); + match self.lookup_op_method(ex, operand_ty, vec![], mname, trait_did, operand_expr) { Ok(t) => t, Err(()) => { self.type_error_message(ex.span, |actual| { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index a280001d5e99..c613b62bf2d8 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -613,11 +613,11 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { hir::ExprCall(ref callee, ref args) => { if has_method_map { self.constrain_call(expr, Some(&callee), - args.iter().map(|e| &**e), false); + args.iter().map(|e| &*e), false); } else { self.constrain_callee(callee.id, expr, &callee); self.constrain_call(expr, None, - args.iter().map(|e| &**e), false); + args.iter().map(|e| &*e), false); } intravisit::walk_expr(self, expr); @@ -625,7 +625,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { hir::ExprMethodCall(.., ref args) => { self.constrain_call(expr, Some(&args[0]), - args[1..].iter().map(|e| &**e), false); + args[1..].iter().map(|e| &*e), false); intravisit::walk_expr(self, expr); } @@ -742,7 +742,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { self.check_expr_fn_block(expr, &body); } - hir::ExprLoop(ref body, _) => { + hir::ExprLoop(ref body, _, _) => { let repeating_scope = self.set_repeating_scope(body.id); intravisit::walk_expr(self, expr); self.set_repeating_scope(repeating_scope); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 535b6bcdcba1..48d79a3ba4c8 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -79,7 +79,7 @@ use rustc_const_math::ConstInt; use std::cell::RefCell; use syntax::{abi, ast, attr}; -use syntax::parse::token::{self, keywords}; +use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; use rustc::hir::{self, map as hir_map, print as pprust}; @@ -585,7 +585,7 @@ fn convert_closure<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| { fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { index: (base_generics.count() as u32) + (i as u32), - name: token::intern(""), + name: Symbol::intern(""), def_id: def_id, default_def_id: base_def_id, default: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a141d0e4788d..2cc1882ce3ea 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -24,9 +24,9 @@ use syntax::abi::Abi; use syntax::ast; use syntax::attr; use syntax::codemap::Spanned; -use syntax::parse::token::keywords; use syntax::ptr::P; use syntax::print::pprust as syntax_pprust; +use syntax::symbol::keywords; use syntax_pos::{self, DUMMY_SP, Pos}; use rustc_trans::back::link; @@ -242,7 +242,7 @@ impl Clean for CrateNum { } }); ExternalCrate { - name: (&cx.sess().cstore.crate_name(self.0)[..]).to_owned(), + name: cx.sess().cstore.crate_name(self.0).to_string(), attrs: cx.sess().cstore.item_attrs(root).clean(cx), primitives: primitives, } @@ -2577,7 +2577,7 @@ impl Clean> for doctree::Import { // #[doc(no_inline)] attribute is present. // Don't inline doc(hidden) imports so they can be stripped at a later stage. let denied = self.vis != hir::Public || self.attrs.iter().any(|a| { - &a.name()[..] == "doc" && match a.meta_item_list() { + a.name() == "doc" && match a.meta_item_list() { Some(l) => attr::list_contains_name(l, "no_inline") || attr::list_contains_name(l, "hidden"), None => false, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 44dadc4367b5..31fbcb5059f8 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2437,7 +2437,6 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, write!(w, "}}")?; } write!(w, "")?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it)?; if !e.variants.is_empty() { @@ -3053,7 +3052,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, Some("macro"), None, None))?; - render_stability_since_raw(w, it.stable_since(), None)?; document(w, cx, it) } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 3fc1267c06e8..0cb9a49ad67b 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -349,12 +349,47 @@ impl File { }) } + /// Changes the permissions on the underlying file. + /// + /// # Platform-specific behavior + /// + /// This function currently corresponds to the `fchmod` function on Unix and + /// the `SetFileInformationByHandle` function on Windows. Note that, this + /// [may change in the future][changes]. + /// + /// [changes]: ../io/index.html#platform-specific-behavior + /// + /// # Errors + /// + /// This function will return an error if the user lacks permission change + /// attributes on the underlying file. It may also return an error in other + /// os-specific unspecified cases. + /// + /// # Examples + /// + /// ``` + /// #![feature(set_permissions_atomic)] + /// # fn foo() -> std::io::Result<()> { + /// use std::fs::File; + /// + /// let file = File::open("foo.txt")?; + /// let mut perms = file.metadata()?.permissions(); + /// perms.set_readonly(true); + /// file.set_permissions(perms)?; + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "set_permissions_atomic", issue="37916")] + pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { + self.inner.set_permissions(perm.0) + } + /// Get the path that this file points to. /// /// This function is only implemented on Redox, but could be /// implemented on other operating systems using readlink #[cfg(target_os = "redox")] - #[stable(feature = "rust1", since = "1.14.0")] + #[unstable(feature = "file_path", issue="0")] pub fn path(&self) -> io::Result { self.inner.path() } @@ -2479,6 +2514,24 @@ mod tests { check!(fs::set_permissions(&file, p)); } + #[test] + fn fchmod_works() { + let tmpdir = tmpdir(); + let path = tmpdir.join("in.txt"); + + let file = check!(File::create(&path)); + let attr = check!(fs::metadata(&path)); + assert!(!attr.permissions().readonly()); + let mut p = attr.permissions(); + p.set_readonly(true); + check!(file.set_permissions(p.clone())); + let attr = check!(fs::metadata(&path)); + assert!(attr.permissions().readonly()); + + p.set_readonly(false); + check!(file.set_permissions(p)); + } + #[test] fn sync_doesnt_kill_anything() { let tmpdir = tmpdir(); diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 20dc5b3801ba..1c016015b792 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -31,7 +31,7 @@ pub enum SocketAddr { /// An IPv4 socket address which is a (ip, port) combination. #[stable(feature = "rust1", since = "1.0.0")] V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4), - /// An IPv6 socket address + /// An IPv6 socket address. #[stable(feature = "rust1", since = "1.0.0")] V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6), } @@ -48,6 +48,16 @@ pub struct SocketAddrV6 { inner: c::sockaddr_in6 } impl SocketAddr { /// Creates a new socket address from the (ip, port) pair. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn new(ip: IpAddr, port: u16) -> SocketAddr { match ip { @@ -57,6 +67,15 @@ impl SocketAddr { } /// Returns the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); + /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] pub fn ip(&self) -> IpAddr { match *self { @@ -66,6 +85,16 @@ impl SocketAddr { } /// Change the IP address associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1))); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_ip(&mut self, new_ip: IpAddr) { // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away. @@ -77,6 +106,15 @@ impl SocketAddr { } /// Returns the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.port(), 8080); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn port(&self) -> u16 { match *self { @@ -86,6 +124,16 @@ impl SocketAddr { } /// Change the port number associated with this socket address. + /// + /// # Examples + /// + /// ``` + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// socket.set_port(1025); + /// assert_eq!(socket.port(), 1025); + /// ``` #[stable(feature = "sockaddr_setters", since = "1.9.0")] pub fn set_port(&mut self, new_port: u16) { match *self { @@ -96,6 +144,20 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address, /// false if it's a valid IPv6 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), true); + /// assert_eq!(socket.is_ipv6(), false); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv4(&self) -> bool { match *self { @@ -106,6 +168,21 @@ impl SocketAddr { /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address, /// false if it's a valid IPv4 address. + /// + /// # Examples + /// + /// ``` + /// #![feature(sockaddr_checker)] + /// + /// use std::net::{IpAddr, Ipv6Addr, SocketAddr}; + /// + /// fn main() { + /// let socket = SocketAddr::new( + /// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080); + /// assert_eq!(socket.is_ipv4(), false); + /// assert_eq!(socket.is_ipv6(), true); + /// } + /// ``` #[unstable(feature = "sockaddr_checker", issue = "36949")] pub fn is_ipv6(&self) -> bool { match *self { diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 9d21a76e81b9..c99fda9febc2 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -825,6 +825,21 @@ pub fn exit(code: i32) -> ! { ::sys::os::exit(code) } +/// Terminates the process in an abnormal fashion. +/// +/// The function will never return and will immediately terminate the current +/// process in a platform specific "abnormal" manner. +/// +/// Note that because this function never returns, and that it terminates the +/// process, no destructors on the current stack or any other thread's stack +/// will be run. If a clean shutdown is needed it is recommended to only call +/// this function at a known point where there are no more destructors left +/// to run. +#[unstable(feature = "process_abort", issue = "37838")] +pub fn abort() -> ! { + unsafe { ::sys::abort_internal() }; +} + #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use io::prelude::*; diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0b43fd2ac8c4..9ee0458b5da3 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -526,6 +526,11 @@ impl File { pub fn fd(&self) -> &FileDesc { &self.0 } pub fn into_fd(self) -> FileDesc { self.0 } + + pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> { + cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?; + Ok(()) + } } impl DirBuilder { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index ce563dc7b16d..1a563127f7f0 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -182,6 +182,7 @@ pub const ERROR_INVALID_HANDLE: DWORD = 6; pub const ERROR_NO_MORE_FILES: DWORD = 18; pub const ERROR_HANDLE_EOF: DWORD = 38; pub const ERROR_FILE_EXISTS: DWORD = 80; +pub const ERROR_INVALID_PARAMETER: DWORD = 87; pub const ERROR_BROKEN_PIPE: DWORD = 109; pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120; pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122; @@ -388,6 +389,15 @@ pub enum FILE_INFO_BY_HANDLE_CLASS { MaximumFileInfoByHandlesClass } +#[repr(C)] +pub struct FILE_BASIC_INFO { + pub CreationTime: LARGE_INTEGER, + pub LastAccessTime: LARGE_INTEGER, + pub LastWriteTime: LARGE_INTEGER, + pub ChangeTime: LARGE_INTEGER, + pub FileAttributes: DWORD, +} + #[repr(C)] pub struct FILE_END_OF_FILE_INFO { pub EndOfFile: LARGE_INTEGER, diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 98fd15f863ba..7d7d78bbd873 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -417,6 +417,24 @@ impl File { Ok(PathBuf::from(OsString::from_wide(subst))) } } + + pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> { + let mut info = c::FILE_BASIC_INFO { + CreationTime: 0, + LastAccessTime: 0, + LastWriteTime: 0, + ChangeTime: 0, + FileAttributes: perm.attrs, + }; + let size = mem::size_of_val(&info); + cvt(unsafe { + c::SetFileInformationByHandle(self.handle.raw(), + c::FileBasicInfo, + &mut info as *mut _ as *mut _, + size as c::DWORD) + })?; + Ok(()) + } } impl FromInner for File { diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index ed7e88e72cd5..1eb173054764 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -43,6 +43,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { let reader; let mut name; let mut tries = 0; + let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS; loop { tries += 1; let key: u64 = rand::thread_rng().gen(); @@ -56,12 +57,12 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { let handle = c::CreateNamedPipeW(wide_name.as_ptr(), c::PIPE_ACCESS_INBOUND | - c::FILE_FLAG_FIRST_PIPE_INSTANCE | - c::FILE_FLAG_OVERLAPPED, + c::FILE_FLAG_FIRST_PIPE_INSTANCE | + c::FILE_FLAG_OVERLAPPED, c::PIPE_TYPE_BYTE | - c::PIPE_READMODE_BYTE | - c::PIPE_WAIT | - c::PIPE_REJECT_REMOTE_CLIENTS, + c::PIPE_READMODE_BYTE | + c::PIPE_WAIT | + reject_remote_clients_flag, 1, 4096, 4096, @@ -76,11 +77,27 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { // // Don't try again too much though as this could also perhaps be a // legit error. + // If ERROR_INVALID_PARAMETER is returned, this probably means we're + // running on pre-Vista version where PIPE_REJECT_REMOTE_CLIENTS is + // not supported, so we continue retrying without it. This implies + // reduced security on Windows versions older than Vista by allowing + // connections to this pipe from remote machines. + // Proper fix would increase the number of FFI imports and introduce + // significant amount of Windows XP specific code with no clean + // testing strategy + // for more info see https://github.com/rust-lang/rust/pull/37677 if handle == c::INVALID_HANDLE_VALUE { let err = io::Error::last_os_error(); - if tries < 10 && - err.raw_os_error() == Some(c::ERROR_ACCESS_DENIED as i32) { - continue + let raw_os_err = err.raw_os_error(); + if tries < 10 { + if raw_os_err == Some(c::ERROR_ACCESS_DENIED as i32) { + continue + } else if reject_remote_clients_flag != 0 && + raw_os_err == Some(c::ERROR_INVALID_PARAMETER as i32) { + reject_remote_clients_flag = 0; + tries -= 1; + continue + } } return Err(err) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f5cd089e923d..2a911aceb9d9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -14,71 +14,43 @@ pub use self::TyParamBound::*; pub use self::UnsafeSource::*; pub use self::ViewPath_::*; pub use self::PathParameters::*; +pub use symbol::Symbol as Name; pub use util::ThinVec; use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId}; use codemap::{respan, Spanned}; use abi::Abi; use ext::hygiene::SyntaxContext; -use parse::token::{self, keywords, InternedString}; use print::pprust; use ptr::P; +use symbol::{Symbol, keywords}; use tokenstream::{TokenTree}; +use std::collections::HashSet; use std::fmt; use std::rc::Rc; use std::u32; use serialize::{self, Encodable, Decodable, Encoder, Decoder}; -/// A name is a part of an identifier, representing a string or gensym. It's -/// the result of interning. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Name(pub u32); - /// An identifier contains a Name (index into the interner /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros That Work Together" #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct Ident { - pub name: Name, + pub name: Symbol, pub ctxt: SyntaxContext } -impl Name { - pub fn as_str(self) -> token::InternedString { - token::InternedString::new_from_name(self) - } -} - -impl fmt::Debug for Name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}({})", self, self.0) - } -} - -impl fmt::Display for Name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) - } -} - -impl Encodable for Name { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) - } -} - -impl Decodable for Name { - fn decode(d: &mut D) -> Result { - Ok(token::intern(&d.read_str()?)) - } -} - impl Ident { pub const fn with_empty_ctxt(name: Name) -> Ident { Ident { name: name, ctxt: SyntaxContext::empty() } } + + /// Maps a string to an identifier with an empty syntax context. + pub fn from_str(s: &str) -> Ident { + Ident::with_empty_ctxt(Symbol::intern(s)) + } } impl fmt::Debug for Ident { @@ -401,7 +373,7 @@ impl Generics { } pub fn span_for_name(&self, name: &str) -> Option { for t in &self.ty_params { - if t.ident.name.as_str() == name { + if t.ident.name == name { return Some(t.span); } } @@ -479,7 +451,7 @@ pub struct WhereEqPredicate { /// The set of MetaItems that define the compilation environment of the crate, /// used to drive conditional compilation -pub type CrateConfig = Vec>; +pub type CrateConfig = HashSet<(Name, Option)>; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Crate { @@ -498,7 +470,7 @@ pub type NestedMetaItem = Spanned; #[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialEq)] pub enum NestedMetaItemKind { /// A full MetaItem, for recursive meta items. - MetaItem(P), + MetaItem(MetaItem), /// A literal. /// /// E.g. "foo", 64, true @@ -508,53 +480,30 @@ pub enum NestedMetaItemKind { /// A spanned compile-time attribute item. /// /// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` -pub type MetaItem = Spanned; +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct MetaItem { + pub name: Name, + pub node: MetaItemKind, + pub span: Span, +} /// A compile-time attribute item. /// /// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` -#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum MetaItemKind { /// Word meta item. /// /// E.g. `test` as in `#[test]` - Word(InternedString), + Word, /// List meta item. /// /// E.g. `derive(..)` as in `#[derive(..)]` - List(InternedString, Vec), + List(Vec), /// Name value meta item. /// /// E.g. `feature = "foo"` as in `#[feature = "foo"]` - NameValue(InternedString, Lit), -} - -// can't be derived because the MetaItemKind::List requires an unordered comparison -impl PartialEq for MetaItemKind { - fn eq(&self, other: &MetaItemKind) -> bool { - use self::MetaItemKind::*; - match *self { - Word(ref ns) => match *other { - Word(ref no) => (*ns) == (*no), - _ => false - }, - List(ref ns, ref miss) => match *other { - List(ref no, ref miso) => { - ns == no && - miss.iter().all(|mi| { - miso.iter().any(|x| x.node == mi.node) - }) - } - _ => false - }, - NameValue(ref ns, ref vs) => match *other { - NameValue(ref no, ref vo) => { - (*ns) == (*no) && vs.node == vo.node - } - _ => false - }, - } - } + NameValue(Lit) } /// A Block (`{ .. }`). @@ -1050,8 +999,8 @@ pub enum ExprKind { /// A referencing operation (`&a` or `&mut a`) AddrOf(Mutability, P), - /// A `break`, with an optional label to break - Break(Option), + /// A `break`, with an optional label to break, and an optional expression + Break(Option, Option>), /// A `continue`, with an optional label Continue(Option), /// A `return`, with an optional value to be returned @@ -1149,7 +1098,7 @@ pub enum LitIntType { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum LitKind { /// A string literal (`"foo"`) - Str(InternedString, StrStyle), + Str(Symbol, StrStyle), /// A byte string (`b"foo"`) ByteStr(Rc>), /// A byte char (`b'f'`) @@ -1159,9 +1108,9 @@ pub enum LitKind { /// An integer literal (`1`) Int(u64, LitIntType), /// A float literal (`1f64` or `1E10f64`) - Float(InternedString, FloatTy), + Float(Symbol, FloatTy), /// A float literal without a suffix (`1.0 or 1.0E10`) - FloatUnsuffixed(InternedString), + FloatUnsuffixed(Symbol), /// A boolean literal Bool(bool), } @@ -1493,7 +1442,7 @@ pub enum AsmDialect { /// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct InlineAsmOutput { - pub constraint: InternedString, + pub constraint: Symbol, pub expr: P, pub is_rw: bool, pub is_indirect: bool, @@ -1504,11 +1453,11 @@ pub struct InlineAsmOutput { /// E.g. `asm!("NOP");` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct InlineAsm { - pub asm: InternedString, + pub asm: Symbol, pub asm_str_style: StrStyle, pub outputs: Vec, - pub inputs: Vec<(InternedString, P)>, - pub clobbers: Vec, + pub inputs: Vec<(Symbol, P)>, + pub clobbers: Vec, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, @@ -1755,8 +1704,6 @@ impl ViewPath_ { } } -/// Meta-data associated with an item -pub type Attribute = Spanned; /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be @@ -1770,13 +1717,15 @@ pub enum AttrStyle { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub struct AttrId(pub usize); +/// Meta-data associated with an item /// Doc-comments are promoted to attributes that have is_sugared_doc = true #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct Attribute_ { +pub struct Attribute { pub id: AttrId, pub style: AttrStyle, - pub value: P, + pub value: MetaItem, pub is_sugared_doc: bool, + pub span: Span, } /// TraitRef's appear in impls. diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 2977e340a3c0..45c120e0b95c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -15,17 +15,17 @@ pub use self::ReprAttr::*; pub use self::IntType::*; use ast; -use ast::{AttrId, Attribute, Attribute_}; +use ast::{AttrId, Attribute, Name}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, Expr, Item, Local, Stmt, StmtKind}; -use codemap::{respan, spanned, dummy_spanned}; +use codemap::{spanned, dummy_spanned, mk_sp}; use syntax_pos::{Span, BytePos, DUMMY_SP}; use errors::Handler; use feature_gate::{Features, GatedCfg}; use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use parse::token::InternedString; -use parse::{ParseSess, token}; +use parse::ParseSess; use ptr::P; +use symbol::Symbol; use util::ThinVec; use std::cell::{RefCell, Cell}; @@ -37,8 +37,8 @@ thread_local! { } enum AttrError { - MultipleItem(InternedString), - UnknownMetaItem(InternedString), + MultipleItem(Name), + UnknownMetaItem(Name), MissingSince, MissingFeature, MultipleStabilityLevels, @@ -61,7 +61,7 @@ fn handle_errors(diag: &Handler, span: Span, error: AttrError) { pub fn mark_used(attr: &Attribute) { debug!("Marking {:?} as used.", attr); - let AttrId(id) = attr.node.id; + let AttrId(id) = attr.id; USED_ATTRS.with(|slot| { let idx = (id / 64) as usize; let shift = id % 64; @@ -73,7 +73,7 @@ pub fn mark_used(attr: &Attribute) { } pub fn is_used(attr: &Attribute) -> bool { - let AttrId(id) = attr.node.id; + let AttrId(id) = attr.id; USED_ATTRS.with(|slot| { let idx = (id / 64) as usize; let shift = id % 64; @@ -84,7 +84,7 @@ pub fn is_used(attr: &Attribute) -> bool { pub fn mark_known(attr: &Attribute) { debug!("Marking {:?} as known.", attr); - let AttrId(id) = attr.node.id; + let AttrId(id) = attr.id; KNOWN_ATTRS.with(|slot| { let idx = (id / 64) as usize; let shift = id % 64; @@ -96,7 +96,7 @@ pub fn mark_known(attr: &Attribute) { } pub fn is_known(attr: &Attribute) -> bool { - let AttrId(id) = attr.node.id; + let AttrId(id) = attr.id; KNOWN_ATTRS.with(|slot| { let idx = (id / 64) as usize; let shift = id % 64; @@ -107,7 +107,7 @@ pub fn is_known(attr: &Attribute) -> bool { impl NestedMetaItem { /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem. - pub fn meta_item(&self) -> Option<&P> { + pub fn meta_item(&self) -> Option<&MetaItem> { match self.node { NestedMetaItemKind::MetaItem(ref item) => Some(&item), _ => None @@ -134,18 +134,18 @@ impl NestedMetaItem { /// Returns the name of the meta item, e.g. `foo` in `#[foo]`, /// `#[foo="bar"]` and `#[foo(bar)]`, if self is a MetaItem - pub fn name(&self) -> Option { + pub fn name(&self) -> Option { self.meta_item().and_then(|meta_item| Some(meta_item.name())) } /// Gets the string value if self is a MetaItem and the MetaItem is a /// MetaItemKind::NameValue variant containing a string, otherwise None. - pub fn value_str(&self) -> Option { + pub fn value_str(&self) -> Option { self.meta_item().and_then(|meta_item| meta_item.value_str()) } /// Returns a MetaItem if self is a MetaItem with Kind Word. - pub fn word(&self) -> Option<&P> { + pub fn word(&self) -> Option<&MetaItem> { self.meta_item().and_then(|meta_item| if meta_item.is_word() { Some(meta_item) } else { @@ -186,16 +186,16 @@ impl NestedMetaItem { impl Attribute { pub fn check_name(&self, name: &str) -> bool { - let matches = name == &self.name()[..]; + let matches = self.name() == name; if matches { mark_used(self); } matches } - pub fn name(&self) -> InternedString { self.meta().name() } + pub fn name(&self) -> Name { self.meta().name() } - pub fn value_str(&self) -> Option { + pub fn value_str(&self) -> Option { self.meta().value_str() } @@ -218,17 +218,13 @@ impl Attribute { } impl MetaItem { - pub fn name(&self) -> InternedString { - match self.node { - MetaItemKind::Word(ref n) => (*n).clone(), - MetaItemKind::NameValue(ref n, _) => (*n).clone(), - MetaItemKind::List(ref n, _) => (*n).clone(), - } + pub fn name(&self) -> Name { + self.name } - pub fn value_str(&self) -> Option { + pub fn value_str(&self) -> Option { match self.node { - MetaItemKind::NameValue(_, ref v) => { + MetaItemKind::NameValue(ref v) => { match v.node { ast::LitKind::Str(ref s, _) => Some((*s).clone()), _ => None, @@ -240,14 +236,14 @@ impl MetaItem { pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> { match self.node { - MetaItemKind::List(_, ref l) => Some(&l[..]), + MetaItemKind::List(ref l) => Some(&l[..]), _ => None } } pub fn is_word(&self) -> bool { match self.node { - MetaItemKind::Word(_) => true, + MetaItemKind::Word => true, _ => false, } } @@ -255,7 +251,7 @@ impl MetaItem { pub fn span(&self) -> Span { self.span } pub fn check_name(&self, name: &str) -> bool { - name == &self.name()[..] + self.name() == name } pub fn is_value_str(&self) -> bool { @@ -270,7 +266,7 @@ impl MetaItem { impl Attribute { /// Extract the MetaItem from inside this Attribute. pub fn meta(&self) -> &MetaItem { - &self.node.value + &self.value } /// Convert self to a normal #[doc="foo"] comment, if it is a @@ -279,16 +275,15 @@ impl Attribute { pub fn with_desugared_doc(&self, f: F) -> T where F: FnOnce(&Attribute) -> T, { - if self.node.is_sugared_doc { + if self.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( - InternedString::new("doc"), - token::intern_and_get_ident(&strip_doc_comment_decoration( - &comment))); - if self.node.style == ast::AttrStyle::Outer { - f(&mk_attr_outer(self.node.id, meta)) + Symbol::intern("doc"), + Symbol::intern(&strip_doc_comment_decoration(&comment.as_str()))); + if self.style == ast::AttrStyle::Outer { + f(&mk_attr_outer(self.id, meta)) } else { - f(&mk_attr_inner(self.node.id, meta)) + f(&mk_attr_inner(self.id, meta)) } } else { f(self) @@ -298,41 +293,37 @@ impl Attribute { /* Constructors */ -pub fn mk_name_value_item_str(name: InternedString, value: InternedString) - -> P { +pub fn mk_name_value_item_str(name: Name, value: Symbol) -> MetaItem { let value_lit = dummy_spanned(ast::LitKind::Str(value, ast::StrStyle::Cooked)); mk_spanned_name_value_item(DUMMY_SP, name, value_lit) } -pub fn mk_name_value_item(name: InternedString, value: ast::Lit) - -> P { +pub fn mk_name_value_item(name: Name, value: ast::Lit) -> MetaItem { mk_spanned_name_value_item(DUMMY_SP, name, value) } -pub fn mk_list_item(name: InternedString, items: Vec) -> P { +pub fn mk_list_item(name: Name, items: Vec) -> MetaItem { mk_spanned_list_item(DUMMY_SP, name, items) } -pub fn mk_list_word_item(name: InternedString) -> ast::NestedMetaItem { +pub fn mk_list_word_item(name: Name) -> ast::NestedMetaItem { dummy_spanned(NestedMetaItemKind::MetaItem(mk_spanned_word_item(DUMMY_SP, name))) } -pub fn mk_word_item(name: InternedString) -> P { +pub fn mk_word_item(name: Name) -> MetaItem { mk_spanned_word_item(DUMMY_SP, name) } -pub fn mk_spanned_name_value_item(sp: Span, name: InternedString, value: ast::Lit) - -> P { - P(respan(sp, MetaItemKind::NameValue(name, value))) +pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem { + MetaItem { span: sp, name: name, node: MetaItemKind::NameValue(value) } } -pub fn mk_spanned_list_item(sp: Span, name: InternedString, items: Vec) - -> P { - P(respan(sp, MetaItemKind::List(name, items))) +pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec) -> MetaItem { + MetaItem { span: sp, name: name, node: MetaItemKind::List(items) } } -pub fn mk_spanned_word_item(sp: Span, name: InternedString) -> P { - P(respan(sp, MetaItemKind::Word(name))) +pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem { + MetaItem { span: sp, name: name, node: MetaItemKind::Word } } @@ -349,71 +340,63 @@ pub fn mk_attr_id() -> AttrId { } /// Returns an inner attribute with the given value. -pub fn mk_attr_inner(id: AttrId, item: P) -> Attribute { +pub fn mk_attr_inner(id: AttrId, item: MetaItem) -> Attribute { mk_spanned_attr_inner(DUMMY_SP, id, item) } /// Returns an innter attribute with the given value and span. -pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: P) -> Attribute { - respan(sp, - Attribute_ { - id: id, - style: ast::AttrStyle::Inner, - value: item, - is_sugared_doc: false, - }) +pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute { + Attribute { + id: id, + style: ast::AttrStyle::Inner, + value: item, + is_sugared_doc: false, + span: sp, + } } /// Returns an outer attribute with the given value. -pub fn mk_attr_outer(id: AttrId, item: P) -> Attribute { +pub fn mk_attr_outer(id: AttrId, item: MetaItem) -> Attribute { mk_spanned_attr_outer(DUMMY_SP, id, item) } /// Returns an outer attribute with the given value and span. -pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: P) -> Attribute { - respan(sp, - Attribute_ { - id: id, - style: ast::AttrStyle::Outer, - value: item, - is_sugared_doc: false, - }) +pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute { + Attribute { + id: id, + style: ast::AttrStyle::Outer, + value: item, + is_sugared_doc: false, + span: sp, + } } -pub fn mk_doc_attr_outer(id: AttrId, item: P, is_sugared_doc: bool) -> Attribute { - dummy_spanned(Attribute_ { +pub fn mk_doc_attr_outer(id: AttrId, item: MetaItem, is_sugared_doc: bool) -> Attribute { + Attribute { id: id, style: ast::AttrStyle::Outer, value: item, is_sugared_doc: is_sugared_doc, - }) + span: DUMMY_SP, + } } -pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos, - hi: BytePos) +pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, lo: BytePos, hi: BytePos) -> Attribute { - let style = doc_comment_style(&text); + let style = doc_comment_style(&text.as_str()); let lit = spanned(lo, hi, ast::LitKind::Str(text, ast::StrStyle::Cooked)); - let attr = Attribute_ { + Attribute { id: id, style: style, - value: P(spanned(lo, hi, MetaItemKind::NameValue(InternedString::new("doc"), lit))), - is_sugared_doc: true - }; - spanned(lo, hi, attr) -} - -/* Searching */ -/// Check if `needle` occurs in `haystack` by a structural -/// comparison. This is slightly subtle, and relies on ignoring the -/// span included in the `==` comparison a plain MetaItem. -pub fn contains(haystack: &[P], needle: &MetaItem) -> bool { - debug!("attr::contains (name={})", needle.name()); - haystack.iter().any(|item| { - debug!(" testing: {}", item.name()); - item.node == needle.node - }) + value: MetaItem { + span: mk_sp(lo, hi), + name: Symbol::intern("doc"), + node: MetaItemKind::NameValue(lit), + }, + is_sugared_doc: true, + span: mk_sp(lo, hi), + } } pub fn list_contains_name(items: &[NestedMetaItem], name: &str) -> bool { @@ -432,15 +415,13 @@ pub fn contains_name(attrs: &[Attribute], name: &str) -> bool { }) } -pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) - -> Option { +pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option { attrs.iter() .find(|at| at.check_name(name)) .and_then(|at| at.value_str()) } -pub fn last_meta_item_value_str_by_name(items: &[P], name: &str) - -> Option { +pub fn last_meta_item_value_str_by_name(items: &[MetaItem], name: &str) -> Option { items.iter() .rev() .find(|mi| mi.check_name(name)) @@ -449,12 +430,12 @@ pub fn last_meta_item_value_str_by_name(items: &[P], name: &str) /* Higher-level applications */ -pub fn find_crate_name(attrs: &[Attribute]) -> Option { +pub fn find_crate_name(attrs: &[Attribute]) -> Option { first_attr_value_str_by_name(attrs, "crate_name") } /// Find the value of #[export_name=*] attribute and check its validity. -pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option { +pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option { attrs.iter().fold(None, |ia,attr| { if attr.check_name("export_name") { if let s@Some(_) = attr.value_str() { @@ -488,13 +469,14 @@ pub enum InlineAttr { /// Determine what `#[inline]` attribute is present in `attrs`, if any. pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr { - attrs.iter().fold(InlineAttr::None, |ia,attr| { - match attr.node.value.node { - MetaItemKind::Word(ref n) if n == "inline" => { + attrs.iter().fold(InlineAttr::None, |ia, attr| { + match attr.value.node { + _ if attr.value.name != "inline" => ia, + MetaItemKind::Word => { mark_used(attr); InlineAttr::Hint } - MetaItemKind::List(ref n, ref items) if n == "inline" => { + MetaItemKind::List(ref items) => { mark_used(attr); if items.len() != 1 { diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); }); @@ -527,7 +509,7 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool { match cfg.node { - ast::MetaItemKind::List(ref pred, ref mis) => { + ast::MetaItemKind::List(ref mis) => { for mi in mis.iter() { if !mi.is_meta_item() { handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral); @@ -537,7 +519,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat // The unwraps below may look dangerous, but we've already asserted // that they won't fail with the loop above. - match &pred[..] { + match &*cfg.name.as_str() { "any" => mis.iter().any(|mi| { cfg_matches(mi.meta_item().unwrap(), sess, features) }), @@ -558,11 +540,11 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat } } }, - ast::MetaItemKind::Word(_) | ast::MetaItemKind::NameValue(..) => { + ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => { if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) { gated_cfg.check_and_emit(sess, feats); } - contains(&sess.config, cfg) + sess.config.contains(&(cfg.name(), cfg.value_str())) } } } @@ -571,7 +553,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)] pub struct Stability { pub level: StabilityLevel, - pub feature: InternedString, + pub feature: Symbol, pub rustc_depr: Option, } @@ -579,20 +561,20 @@ pub struct Stability { #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] pub enum StabilityLevel { // Reason for the current stability level and the relevant rust-lang issue - Unstable { reason: Option, issue: u32 }, - Stable { since: InternedString }, + Unstable { reason: Option, issue: u32 }, + Stable { since: Symbol }, } #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] pub struct RustcDeprecation { - pub since: InternedString, - pub reason: InternedString, + pub since: Symbol, + pub reason: Symbol, } #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)] pub struct Deprecation { - pub since: Option, - pub note: Option, + pub since: Option, + pub note: Option, } impl StabilityLevel { @@ -611,7 +593,6 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, 'outer: for attr in attrs_iter { let tag = attr.name(); - let tag = &*tag; if tag != "rustc_deprecated" && tag != "unstable" && tag != "stable" { continue // not a stability level } @@ -619,7 +600,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, mark_used(attr); if let Some(metas) = attr.meta_item_list() { - let get = |meta: &MetaItem, item: &mut Option| { + let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); return false @@ -633,7 +614,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } }; - match tag { + match &*tag.as_str() { "rustc_deprecated" => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, @@ -645,7 +626,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut reason = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name() { + match &*mi.name().as_str() { "since" => if !get(mi, &mut since) { continue 'outer }, "reason" => if !get(mi, &mut reason) { continue 'outer }, _ => { @@ -688,7 +669,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut issue = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.name() { + match &*mi.name().as_str() { "feature" => if !get(mi, &mut feature) { continue 'outer }, "reason" => if !get(mi, &mut reason) { continue 'outer }, "issue" => if !get(mi, &mut issue) { continue 'outer }, @@ -710,7 +691,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, level: Unstable { reason: reason, issue: { - if let Ok(issue) = issue.parse() { + if let Ok(issue) = issue.as_str().parse() { issue } else { span_err!(diagnostic, attr.span(), E0545, @@ -743,7 +724,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut since = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name() { + match &*mi.name().as_str() { "feature" => if !get(mi, &mut feature) { continue 'outer }, "since" => if !get(mi, &mut since) { continue 'outer }, _ => { @@ -821,7 +802,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, } depr = if let Some(metas) = attr.meta_item_list() { - let get = |meta: &MetaItem, item: &mut Option| { + let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); return false @@ -839,7 +820,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, let mut note = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.name() { + match &*mi.name().as_str() { "since" => if !get(mi, &mut since) { continue 'outer }, "note" => if !get(mi, &mut note) { continue 'outer }, _ => { @@ -875,7 +856,7 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute], find_deprecation_generic(diagnostic, attrs.iter(), item_sp) } -pub fn require_unique_names(diagnostic: &Handler, metas: &[P]) { +pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) { let mut set = HashSet::new(); for meta in metas { let name = meta.name(); @@ -896,8 +877,8 @@ pub fn require_unique_names(diagnostic: &Handler, metas: &[P]) { /// structure layout, and `packed` to remove padding. pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec { let mut acc = Vec::new(); - match attr.node.value.node { - ast::MetaItemKind::List(ref s, ref items) if s == "repr" => { + match attr.value.node { + ast::MetaItemKind::List(ref items) if attr.value.name == "repr" => { mark_used(attr); for item in items { if !item.is_meta_item() { @@ -906,7 +887,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec } if let Some(mi) = item.word() { - let word = &*mi.name(); + let word = &*mi.name().as_str(); let hint = match word { // Can't use "extern" because it's not a lexical identifier. "C" => Some(ReprExtern), diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 49012ad036a9..3cdfa718eaba 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -871,6 +871,7 @@ impl CodeMapper for CodeMap { #[cfg(test)] mod tests { use super::*; + use symbol::keywords; use std::rc::Rc; #[test] @@ -1097,10 +1098,9 @@ mod tests { #[test] fn t11() { // Test span_to_expanded_string works with expansion - use ast::Name; let cm = init_code_map(); let root = Span { lo: BytePos(0), hi: BytePos(11), expn_id: NO_EXPANSION }; - let format = ExpnFormat::MacroBang(Name(0u32)); + let format = ExpnFormat::MacroBang(keywords::Invalid.name()); let callee = NameAndSpan { format: format, allow_internal_unstable: false, span: None }; @@ -1197,11 +1197,9 @@ mod tests { fn init_expansion_chain(cm: &CodeMap) -> Span { // Creates an expansion chain containing two recursive calls // root -> expA -> expA -> expB -> expB -> end - use ast::Name; - let root = Span { lo: BytePos(0), hi: BytePos(11), expn_id: NO_EXPANSION }; - let format_root = ExpnFormat::MacroBang(Name(0u32)); + let format_root = ExpnFormat::MacroBang(keywords::Invalid.name()); let callee_root = NameAndSpan { format: format_root, allow_internal_unstable: false, span: Some(root) }; @@ -1210,7 +1208,7 @@ mod tests { let id_a1 = cm.record_expansion(info_a1); let span_a1 = Span { lo: BytePos(12), hi: BytePos(23), expn_id: id_a1 }; - let format_a = ExpnFormat::MacroBang(Name(1u32)); + let format_a = ExpnFormat::MacroBang(keywords::As.name()); let callee_a = NameAndSpan { format: format_a, allow_internal_unstable: false, span: Some(span_a1) }; @@ -1223,7 +1221,7 @@ mod tests { let id_b1 = cm.record_expansion(info_b1); let span_b1 = Span { lo: BytePos(25), hi: BytePos(36), expn_id: id_b1 }; - let format_b = ExpnFormat::MacroBang(Name(2u32)); + let format_b = ExpnFormat::MacroBang(keywords::Box.name()); let callee_b = NameAndSpan { format: format_b, allow_internal_unstable: false, span: None }; diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 02429f02738f..89eea3f6f8b2 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -12,7 +12,7 @@ use attr::HasAttrs; use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue}; use {fold, attr}; use ast; -use codemap::{Spanned, respan}; +use codemap::Spanned; use parse::ParseSess; use ptr::P; @@ -106,12 +106,13 @@ impl<'a> StripUnconfigured<'a> { match (cfg.meta_item(), mi.meta_item()) { (Some(cfg), Some(mi)) => if cfg_matches(&cfg, self.sess, self.features) { - self.process_cfg_attr(respan(mi.span, ast::Attribute_ { + self.process_cfg_attr(ast::Attribute { id: attr::mk_attr_id(), - style: attr.node.style, + style: attr.style, value: mi.clone(), is_sugared_doc: false, - })) + span: mi.span, + }) } else { None }, @@ -131,8 +132,8 @@ impl<'a> StripUnconfigured<'a> { return false; } - let mis = match attr.node.value.node { - ast::MetaItemKind::List(_, ref mis) if is_cfg(&attr) => mis, + let mis = match attr.value.node { + ast::MetaItemKind::List(ref mis) if is_cfg(&attr) => mis, _ => return true }; @@ -160,7 +161,7 @@ impl<'a> StripUnconfigured<'a> { attr.span, GateIssue::Language, EXPLAIN_STMT_ATTR_SYNTAX); - if attr.node.is_sugared_doc { + if attr.is_sugared_doc { err.help("`///` is for documentation comments. For a plain comment, use `//`."); } err.emit(); diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 81c8e0bdb826..fe5cb87ad59b 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -19,6 +19,7 @@ use ext::base::{ExtCtxt, MacEager, MacResult}; use ext::build::AstBuilder; use parse::token; use ptr::P; +use symbol::Symbol; use tokenstream::{TokenTree}; use util::small_vector::SmallVector; @@ -141,7 +142,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, )); } }); - let sym = Ident::with_empty_ctxt(token::gensym(&format!( + let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!( "__register_diagnostic_{}", code ))); MacEager::items(SmallVector::many(vec![ @@ -194,11 +195,11 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, let (count, expr) = with_registered_diagnostics(|diagnostics| { let descriptions: Vec> = - diagnostics.iter().filter_map(|(code, info)| { + diagnostics.iter().filter_map(|(&code, info)| { info.description.map(|description| { ecx.expr_tuple(span, vec![ - ecx.expr_str(span, code.as_str()), - ecx.expr_str(span, description.as_str()) + ecx.expr_str(span, code), + ecx.expr_str(span, description) ]) }) }).collect(); diff --git a/src/libsyntax/entry.rs b/src/libsyntax/entry.rs index 7014e576e2b8..93ca1948ed84 100644 --- a/src/libsyntax/entry.rs +++ b/src/libsyntax/entry.rs @@ -28,7 +28,7 @@ pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType { EntryPointType::Start } else if attr::contains_name(&item.attrs, "main") { EntryPointType::MainAttr - } else if item.ident.name.as_str() == "main" { + } else if item.ident.name == "main" { if depth == 1 { // This is a top-level function so can be 'main' EntryPointType::MainNamed diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7f66b060052e..ddbca47429d1 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -18,10 +18,10 @@ use errors::DiagnosticBuilder; use ext::expand::{self, Expansion}; use ext::hygiene::Mark; use fold::{self, Folder}; -use parse::{self, parser}; +use parse::{self, parser, DirectoryOwnership}; use parse::token; -use parse::token::{InternedString, str_to_ident}; use ptr::P; +use symbol::Symbol; use util::small_vector::SmallVector; use std::path::PathBuf; @@ -568,9 +568,7 @@ pub struct ExpansionData { pub depth: usize, pub backtrace: ExpnId, pub module: Rc, - - // True if non-inline modules without a `#[path]` are forbidden at the root of this expansion. - pub no_noninline_mod: bool, + pub directory_ownership: DirectoryOwnership, } /// One of these is made during expansion and incrementally updated as we go; @@ -601,7 +599,7 @@ impl<'a> ExtCtxt<'a> { depth: 0, backtrace: NO_EXPANSION, module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), - no_noninline_mod: false, + directory_ownership: DirectoryOwnership::Owned, }, } } @@ -643,7 +641,7 @@ impl<'a> ExtCtxt<'a> { loop { if self.codemap().with_expn_info(expn_id, |info| { info.map_or(None, |i| { - if i.callee.name().as_str() == "include" { + if i.callee.name() == "include" { // Stop going up the backtrace once include! is encountered return None; } @@ -735,7 +733,7 @@ impl<'a> ExtCtxt<'a> { self.ecfg.trace_mac = x } pub fn ident_of(&self, st: &str) -> ast::Ident { - str_to_ident(st) + ast::Ident::from_str(st) } pub fn std_path(&self, components: &[&str]) -> Vec { let mut v = Vec::new(); @@ -746,7 +744,7 @@ impl<'a> ExtCtxt<'a> { return v } pub fn name_of(&self, st: &str) -> ast::Name { - token::intern(st) + Symbol::intern(st) } } @@ -754,7 +752,7 @@ impl<'a> ExtCtxt<'a> { /// emitting `err_msg` if `expr` is not a string literal. This does not stop /// compilation on error, merely emits a non-fatal error and returns None. pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P, err_msg: &str) - -> Option> { + -> Option> { // Update `expr.span`'s expn_id now in case expr is an `include!` macro invocation. let expr = expr.map(|mut expr| { expr.span.expn_id = cx.backtrace(); @@ -765,7 +763,7 @@ pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P, err_msg: &st let expr = cx.expander().fold_expr(expr); match expr.node { ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(ref s, style) => return Some(respan(expr.span, (s.clone(), style))), + ast::LitKind::Str(s, style) => return Some(respan(expr.span, (s, style))), _ => cx.span_err(l.span, err_msg) }, _ => cx.span_err(expr.span, err_msg) @@ -774,7 +772,7 @@ pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P, err_msg: &st } pub fn expr_to_string(cx: &mut ExtCtxt, expr: P, err_msg: &str) - -> Option<(InternedString, ast::StrStyle)> { + -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node) } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index c3e28cbb006a..a208b934d79e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -14,8 +14,8 @@ use attr; use syntax_pos::{Span, DUMMY_SP, Pos}; use codemap::{dummy_spanned, respan, Spanned}; use ext::base::ExtCtxt; -use parse::token::{self, keywords, InternedString}; use ptr::P; +use symbol::{Symbol, keywords}; // Transitional reexports so qquote can find the paths it is looking for mod syntax { @@ -149,7 +149,7 @@ pub trait AstBuilder { fn expr_vec(&self, sp: Span, exprs: Vec>) -> P; fn expr_vec_ng(&self, sp: Span) -> P; fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P; - fn expr_str(&self, sp: Span, s: InternedString) -> P; + fn expr_str(&self, sp: Span, s: Symbol) -> P; fn expr_some(&self, sp: Span, expr: P) -> P; fn expr_none(&self, sp: Span) -> P; @@ -158,7 +158,7 @@ pub trait AstBuilder { fn expr_tuple(&self, sp: Span, exprs: Vec>) -> P; - fn expr_fail(&self, span: Span, msg: InternedString) -> P; + fn expr_fail(&self, span: Span, msg: Symbol) -> P; fn expr_unreachable(&self, span: Span) -> P; fn expr_ok(&self, span: Span, expr: P) -> P; @@ -275,22 +275,22 @@ pub trait AstBuilder { generics: Generics) -> P; fn item_ty(&self, span: Span, name: Ident, ty: P) -> P; - fn attribute(&self, sp: Span, mi: P) -> ast::Attribute; + fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute; - fn meta_word(&self, sp: Span, w: InternedString) -> P; + fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem; - fn meta_list_item_word(&self, sp: Span, w: InternedString) -> ast::NestedMetaItem; + fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem; fn meta_list(&self, sp: Span, - name: InternedString, + name: ast::Name, mis: Vec ) - -> P; + -> ast::MetaItem; fn meta_name_value(&self, sp: Span, - name: InternedString, + name: ast::Name, value: ast::LitKind) - -> P; + -> ast::MetaItem; fn item_use(&self, sp: Span, vis: ast::Visibility, vp: P) -> P; @@ -755,7 +755,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_vec_slice(&self, sp: Span, exprs: Vec>) -> P { self.expr_addr_of(sp, self.expr_vec(sp, exprs)) } - fn expr_str(&self, sp: Span, s: InternedString) -> P { + fn expr_str(&self, sp: Span, s: Symbol) -> P { self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) } @@ -777,7 +777,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn expr_break(&self, sp: Span) -> P { - self.expr(sp, ast::ExprKind::Break(None)) + self.expr(sp, ast::ExprKind::Break(None, None)) } @@ -785,10 +785,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Tup(exprs)) } - fn expr_fail(&self, span: Span, msg: InternedString) -> P { + fn expr_fail(&self, span: Span, msg: Symbol) -> P { let loc = self.codemap().lookup_char_pos(span.lo); - let expr_file = self.expr_str(span, - token::intern_and_get_ident(&loc.file.name)); + let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name)); let expr_line = self.expr_u32(span, loc.line as u32); let expr_file_line_tuple = self.expr_tuple(span, vec![expr_file, expr_line]); let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); @@ -801,9 +800,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_unreachable(&self, span: Span) -> P { - self.expr_fail(span, - InternedString::new( - "internal error: entered unreachable code")) + self.expr_fail(span, Symbol::intern("internal error: entered unreachable code")) } fn expr_ok(&self, sp: Span, expr: P) -> P { @@ -1146,25 +1143,25 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.item_ty_poly(span, name, ty, Generics::default()) } - fn attribute(&self, sp: Span, mi: P) -> ast::Attribute { + fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute { attr::mk_spanned_attr_outer(sp, attr::mk_attr_id(), mi) } - fn meta_word(&self, sp: Span, w: InternedString) -> P { + fn meta_word(&self, sp: Span, w: ast::Name) -> ast::MetaItem { attr::mk_spanned_word_item(sp, w) } - fn meta_list_item_word(&self, sp: Span, w: InternedString) -> ast::NestedMetaItem { + fn meta_list_item_word(&self, sp: Span, w: ast::Name) -> ast::NestedMetaItem { respan(sp, ast::NestedMetaItemKind::MetaItem(attr::mk_spanned_word_item(sp, w))) } - fn meta_list(&self, sp: Span, name: InternedString, mis: Vec) - -> P { + fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec) + -> ast::MetaItem { attr::mk_spanned_list_item(sp, name, mis) } - fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind) - -> P { + fn meta_name_value(&self, sp: Span, name: ast::Name, value: ast::LitKind) + -> ast::MetaItem { attr::mk_spanned_name_value_item(sp, name, respan(sp, value)) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 8e0c3ce8448d..fd6cae1e1b66 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -21,12 +21,13 @@ use ext::base::*; use feature_gate::{self, Features}; use fold; use fold::*; -use parse::{ParseSess, PResult, lexer}; +use parse::{ParseSess, DirectoryOwnership, PResult, lexer}; use parse::parser::Parser; -use parse::token::{self, intern, keywords}; +use parse::token; use print::pprust; use ptr::P; use std_inject; +use symbol::keywords; use tokenstream::{TokenTree, TokenStream}; use util::small_vector::SmallVector; use visit::Visitor; @@ -190,7 +191,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { self.cx.crate_root = std_inject::injected_crate_name(&krate); let mut module = ModuleData { - mod_path: vec![token::str_to_ident(&self.cx.ecfg.crate_name)], + mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)], directory: PathBuf::from(self.cx.codemap().span_to_filename(krate.span)), }; module.directory.pop(); @@ -246,7 +247,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.resolver.resolve_macro(scope, &mac.node.path, force) } InvocationKind::Attr { ref attr, .. } => { - let ident = ast::Ident::with_empty_ctxt(intern(&*attr.name())); + let ident = Ident::with_empty_ctxt(attr.name()); let path = ast::Path::from_ident(attr.span, ident); self.cx.resolver.resolve_macro(scope, &path, force) } @@ -341,7 +342,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; attr::mark_used(&attr); - let name = intern(&attr.name()); + let name = attr.name(); self.cx.bt_push(ExpnInfo { call_site: attr.span, callee: NameAndSpan { @@ -353,12 +354,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { match *ext { MultiModifier(ref mac) => { - let item = mac.expand(self.cx, attr.span, &attr.node.value, item); + let item = mac.expand(self.cx, attr.span, &attr.value, item); kind.expect_from_annotatables(item) } MultiDecorator(ref mac) => { let mut items = Vec::new(); - mac.expand(self.cx, attr.span, &attr.node.value, &item, + mac.expand(self.cx, attr.span, &attr.value, &item, &mut |item| items.push(item)); items.push(item); kind.expect_from_annotatables(items) @@ -726,9 +727,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { } fn fold_block(&mut self, block: P) -> P { - let no_noninline_mod = mem::replace(&mut self.cx.current_expansion.no_noninline_mod, true); + let old_directory_ownership = self.cx.current_expansion.directory_ownership; + self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock; let result = noop_fold_block(block, self); - self.cx.current_expansion.no_noninline_mod = no_noninline_mod; + self.cx.current_expansion.directory_ownership = old_directory_ownership; result } @@ -767,7 +769,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { return noop_fold_item(item, self); } - let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod; + let orig_directory_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); @@ -778,23 +780,28 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { if inline_module { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { - self.cx.current_expansion.no_noninline_mod = false; - module.directory.push(&*path); + self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned; + module.directory.push(&*path.as_str()); } else { module.directory.push(&*item.ident.name.as_str()); } } else { - self.cx.current_expansion.no_noninline_mod = false; - module.directory = + let mut path = PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner)); - module.directory.pop(); + let directory_ownership = match path.file_name().unwrap().to_str() { + Some("mod.rs") => DirectoryOwnership::Owned, + _ => DirectoryOwnership::UnownedViaMod(false), + }; + path.pop(); + module.directory = path; + self.cx.current_expansion.directory_ownership = directory_ownership; } let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); let result = noop_fold_item(item, self); self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.no_noninline_mod = orig_no_noninline_mod; + self.cx.current_expansion.directory_ownership = orig_directory_ownership; return result; } // Ensure that test functions are accessible from the test harness. diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index e323dd2f6232..4fe57a8345e9 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -13,8 +13,8 @@ use codemap::{DUMMY_SP, dummy_spanned}; use ext::base::ExtCtxt; use ext::expand::{Expansion, ExpansionKind}; use fold::*; -use parse::token::{intern, keywords}; use ptr::P; +use symbol::{Symbol, keywords}; use util::move_map::MoveMap; use util::small_vector::SmallVector; @@ -227,7 +227,7 @@ pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion { span: DUMMY_SP, global: false, segments: vec![ast::PathSegment { - identifier: ast::Ident::with_empty_ctxt(intern("macro_rules")), + identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")), parameters: ast::PathParameters::none(), }], }, diff --git a/src/libsyntax/ext/proc_macro_shim.rs b/src/libsyntax/ext/proc_macro_shim.rs index dc3a01f41bc9..21ce89a6dd5b 100644 --- a/src/libsyntax/ext/proc_macro_shim.rs +++ b/src/libsyntax/ext/proc_macro_shim.rs @@ -66,6 +66,7 @@ pub mod prelude { pub use ast::Ident; pub use codemap::{DUMMY_SP, Span}; pub use ext::base::{ExtCtxt, MacResult}; - pub use parse::token::{self, Token, DelimToken, keywords, str_to_ident}; + pub use parse::token::{self, Token, DelimToken}; + pub use symbol::keywords; pub use tokenstream::{TokenTree, TokenStream}; } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 969cfa292ce8..aa777a19a9bc 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -33,6 +33,7 @@ pub mod rt { use parse::{self, token, classify}; use ptr::P; use std::rc::Rc; + use symbol::Symbol; use tokenstream::{self, TokenTree}; @@ -211,7 +212,7 @@ pub mod rt { impl_to_tokens_slice! { P, [] } impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] } - impl ToTokens for P { + impl ToTokens for ast::MetaItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { let nt = token::NtMeta(self.clone()); vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] @@ -223,13 +224,13 @@ pub mod rt { let mut r = vec![]; // FIXME: The spans could be better r.push(TokenTree::Token(self.span, token::Pound)); - if self.node.style == ast::AttrStyle::Inner { + if self.style == ast::AttrStyle::Inner { r.push(TokenTree::Token(self.span, token::Not)); } r.push(TokenTree::Delimited(self.span, Rc::new(tokenstream::Delimited { delim: token::Bracket, open_span: self.span, - tts: self.node.value.to_tokens(cx), + tts: self.value.to_tokens(cx), close_span: self.span, }))); r @@ -238,8 +239,7 @@ pub mod rt { impl ToTokens for str { fn to_tokens(&self, cx: &ExtCtxt) -> Vec { - let lit = ast::LitKind::Str( - token::intern_and_get_ident(self), ast::StrStyle::Cooked); + let lit = ast::LitKind::Str(Symbol::intern(self), ast::StrStyle::Cooked); dummy_spanned(lit).to_tokens(cx) } } @@ -405,7 +405,7 @@ pub fn parse_block_panic(parser: &mut Parser) -> P { panictry!(parser.parse_block()) } -pub fn parse_meta_item_panic(parser: &mut Parser) -> P { +pub fn parse_meta_item_panic(parser: &mut Parser) -> ast::MetaItem { panictry!(parser.parse_meta_item()) } @@ -527,17 +527,17 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt, base::MacEager::expr(expanded) } -fn ids_ext(strs: Vec ) -> Vec { - strs.iter().map(|str| str_to_ident(&(*str))).collect() +fn ids_ext(strs: Vec) -> Vec { + strs.iter().map(|s| ast::Ident::from_str(s)).collect() } -fn id_ext(str: &str) -> ast::Ident { - str_to_ident(str) +fn id_ext(s: &str) -> ast::Ident { + ast::Ident::from_str(s) } // Lift an ident to the expr that evaluates to that ident. fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P { - let e_str = cx.expr_str(sp, ident.name.as_str()); + let e_str = cx.expr_str(sp, ident.name); cx.expr_method_call(sp, cx.expr_ident(sp, id_ext("ext_cx")), id_ext("ident_of"), @@ -546,7 +546,7 @@ fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P { // Lift a name to the expr that evaluates to that name fn mk_name(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P { - let e_str = cx.expr_str(sp, ident.name.as_str()); + let e_str = cx.expr_str(sp, ident.name); cx.expr_method_call(sp, cx.expr_ident(sp, id_ext("ext_cx")), id_ext("name_of"), diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index bda84cdaf39e..39b92c7d007d 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -13,10 +13,11 @@ use syntax_pos::{self, Pos, Span}; use ext::base::*; use ext::base; use ext::build::AstBuilder; -use parse::token; +use parse::{token, DirectoryOwnership}; use parse; use print::pprust; use ptr::P; +use symbol::Symbol; use tokenstream; use util::small_vector::SmallVector; @@ -60,15 +61,13 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) let topmost = cx.expansion_cause(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - let filename = token::intern_and_get_ident(&loc.file.name); - base::MacEager::expr(cx.expr_str(topmost, filename)) + base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name))) } pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) -> Box { let s = pprust::tts_to_string(tts); - base::MacEager::expr(cx.expr_str(sp, - token::intern_and_get_ident(&s[..]))) + base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) } pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) @@ -77,9 +76,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree]) let mod_path = &cx.current_expansion.module.mod_path; let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); - base::MacEager::expr(cx.expr_str( - sp, - token::intern_and_get_ident(&string[..]))) + base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))) } /// include! : parse the given file as an expr @@ -93,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T }; // The file will be added to the code map by the parser let path = res_rel_file(cx, sp, Path::new(&file)); - let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, true, None, sp); + let directory_ownership = DirectoryOwnership::Owned; + let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp); struct ExpandResult<'a> { p: parse::parser::Parser<'a>, @@ -144,10 +142,9 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT // Add this input file to the code map to make it available as // dependency information let filename = format!("{}", file.display()); - let interned = token::intern_and_get_ident(&src[..]); cx.codemap().new_filemap_and_lines(&filename, None, &src); - base::MacEager::expr(cx.expr_str(sp, interned)) + base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&src))) } Err(_) => { cx.span_err(sp, diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 552d4de96174..4164b4a93ec9 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -19,10 +19,11 @@ use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::{parse, parse_failure_msg}; use parse::ParseSess; use parse::lexer::new_tt_reader; -use parse::parser::{Parser, Restrictions}; -use parse::token::{self, gensym_ident, NtTT, Token}; +use parse::parser::Parser; +use parse::token::{self, NtTT, Token}; use parse::token::Token::*; use print; +use symbol::Symbol; use tokenstream::{self, TokenTree}; use std::collections::{HashMap}; @@ -116,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, let trncbr = new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs); let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr)); - p.directory = cx.current_expansion.module.directory.clone(); - p.restrictions = match cx.current_expansion.no_noninline_mod { - true => Restrictions::NO_NONINLINE_MOD, - false => Restrictions::empty(), - }; + let module = &cx.current_expansion.module; + p.directory.path = module.directory.clone(); + p.directory.ownership = cx.current_expansion.directory_ownership; + p.root_module_name = + module.mod_path.last().map(|id| (*id.name.as_str()).to_owned()); + p.check_unknown_macro_variable(); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. @@ -187,16 +189,16 @@ impl IdentMacroExpander for MacroRulesExpander { /// Converts a `macro_rules!` invocation into a syntax extension. pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { - let lhs_nm = gensym_ident("lhs"); - let rhs_nm = gensym_ident("rhs"); + let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs")); + let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs")); // The pattern that macro_rules matches. // The grammar for macro_rules! is: // $( $lhs:tt => $rhs:tt );+ // ...quasiquoting this would be nice. // These spans won't matter, anyways - let match_lhs_tok = MatchNt(lhs_nm, token::str_to_ident("tt")); - let match_rhs_tok = MatchNt(rhs_nm, token::str_to_ident("tt")); + let match_lhs_tok = MatchNt(lhs_nm, ast::Ident::from_str("tt")); + let match_rhs_tok = MatchNt(rhs_nm, ast::Ident::from_str("tt")); let argument_gram = vec![ TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition { tts: vec![ @@ -790,8 +792,7 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result "pat" => { match *tok { FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true), - Ident(i) if (i.name.as_str() == "if" || - i.name.as_str() == "in") => Ok(true), + Ident(i) if i.name == "if" || i.name == "in" => Ok(true), _ => Ok(false) } }, @@ -799,8 +800,8 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result match *tok { OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) | Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true), - MatchNt(_, ref frag) if frag.name.as_str() == "block" => Ok(true), - Ident(i) if i.name.as_str() == "as" || i.name.as_str() == "where" => Ok(true), + MatchNt(_, ref frag) if frag.name == "block" => Ok(true), + Ident(i) if i.name == "as" || i.name == "where" => Ok(true), _ => Ok(false) } }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index ea66fdc31cf0..aa6a29b78b07 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -33,7 +33,7 @@ use syntax_pos::Span; use errors::{DiagnosticBuilder, Handler}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; -use parse::token::InternedString; +use symbol::Symbol; use std::ascii::AsciiExt; use std::env; @@ -59,9 +59,9 @@ macro_rules! declare_features { /// A set of features to be used by later passes. pub struct Features { /// #![feature] attrs for stable language features, for error reporting - pub declared_stable_lang_features: Vec<(InternedString, Span)>, + pub declared_stable_lang_features: Vec<(Symbol, Span)>, /// #![feature] attrs for non-language (library) features - pub declared_lib_features: Vec<(InternedString, Span)>, + pub declared_lib_features: Vec<(Symbol, Span)>, $(pub $feature: bool),+ } @@ -284,9 +284,6 @@ declare_features! ( // instead of just the platforms on which it is the C ABI (active, abi_sysv64, "1.13.0", Some(36167)), - // Use the import semantics from RFC 1560. - (active, item_like_imports, "1.13.0", Some(35120)), - // Macros 1.1 (active, proc_macro, "1.13.0", Some(35900)), @@ -316,6 +313,9 @@ declare_features! ( (active, link_cfg, "1.14.0", Some(37406)), (active, use_extern_macros, "1.15.0", Some(35896)), + + // Allows `break {expr}` with a value inside `loop`s. + (active, loop_break_value, "1.14.0", Some(37339)), ); declare_features! ( @@ -362,6 +362,7 @@ declare_features! ( (accepted, question_mark, "1.13.0", Some(31436)), // Allows `..` in tuple (struct) patterns (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)), + (accepted, item_like_imports, "1.14.0", Some(35120)), ); // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -757,7 +758,7 @@ pub struct GatedCfg { impl GatedCfg { pub fn gate(cfg: &ast::MetaItem) -> Option { - let name = cfg.name(); + let name = &*cfg.name().as_str(); GATED_CFGS.iter() .position(|info| info.0 == name) .map(|idx| { @@ -804,7 +805,7 @@ macro_rules! gate_feature { impl<'a> Context<'a> { fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) { debug!("check_attribute(attr = {:?})", attr); - let name = &*attr.name(); + let name = &*attr.name().as_str(); for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES { if n == name { if let &Gated(_, ref name, ref desc, ref has_feature) = gateage { @@ -991,11 +992,11 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool { use ast::NestedMetaItemKind::*; match item.node { - Word(..) => false, - NameValue(_, ref lit) => !lit.node.is_str(), - List(_, ref list) => list.iter().any(|li| { + Word => false, + NameValue(ref lit) => !lit.node.is_str(), + List(ref list) => list.iter().any(|li| { match li.node { - MetaItem(ref mi) => contains_novel_literal(&**mi), + MetaItem(ref mi) => contains_novel_literal(&mi), Literal(_) => true, } }), @@ -1013,7 +1014,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> { self.context.check_attribute(attr, false); } - if contains_novel_literal(&*(attr.node.value)) { + if contains_novel_literal(&attr.value) { gate_feature_post!(&self, attr_literals, attr.span, "non-string literals in attributes, or string \ literals in top-level positions, are experimental"); @@ -1121,9 +1122,8 @@ impl<'a> Visitor for PostExpansionVisitor<'a> { } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { - let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, - "link_name") { - Some(val) => val.starts_with("llvm."), + let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") { + Some(val) => val.as_str().starts_with("llvm."), _ => false }; if links_to_llvm { @@ -1192,6 +1192,10 @@ impl<'a> Visitor for PostExpansionVisitor<'a> { } } } + ast::ExprKind::Break(_, Some(_)) => { + gate_feature_post!(&self, loop_break_value, e.span, + "`break` with a value is experimental"); + } _ => {} } visit::walk_expr(self, e); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2e62f23578d8..6af8efb2a195 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -22,8 +22,9 @@ use ast::*; use ast; use syntax_pos::Span; use codemap::{Spanned, respan}; -use parse::token::{self, keywords}; +use parse::token; use ptr::P; +use symbol::keywords; use tokenstream::*; use util::small_vector::SmallVector; use util::move_map::MoveMap; @@ -43,7 +44,7 @@ pub trait Folder : Sized { noop_fold_crate(c, self) } - fn fold_meta_items(&mut self, meta_items: Vec>) -> Vec> { + fn fold_meta_items(&mut self, meta_items: Vec) -> Vec { noop_fold_meta_items(meta_items, self) } @@ -51,7 +52,7 @@ pub trait Folder : Sized { noop_fold_meta_list_item(list_item, self) } - fn fold_meta_item(&mut self, meta_item: P) -> P { + fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem { noop_fold_meta_item(meta_item, self) } @@ -293,8 +294,7 @@ pub trait Folder : Sized { } } -pub fn noop_fold_meta_items(meta_items: Vec>, fld: &mut T) - -> Vec> { +pub fn noop_fold_meta_items(meta_items: Vec, fld: &mut T) -> Vec { meta_items.move_map(|x| fld.fold_meta_item(x)) } @@ -486,16 +486,13 @@ pub fn noop_fold_local(l: P, fld: &mut T) -> P { }) } -pub fn noop_fold_attribute(at: Attribute, fld: &mut T) -> Option { - let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at; - Some(Spanned { - node: Attribute_ { - id: id, - style: style, - value: fld.fold_meta_item(value), - is_sugared_doc: is_sugared_doc - }, - span: fld.new_span(span) +pub fn noop_fold_attribute(attr: Attribute, fld: &mut T) -> Option { + Some(Attribute { + id: attr.id, + style: attr.style, + value: fld.fold_meta_item(attr.value), + is_sugared_doc: attr.is_sugared_doc, + span: fld.new_span(attr.span), }) } @@ -522,17 +519,18 @@ pub fn noop_fold_meta_list_item(li: NestedMetaItem, fld: &mut T) } } -pub fn noop_fold_meta_item(mi: P, fld: &mut T) -> P { - mi.map(|Spanned {node, span}| Spanned { - node: match node { - MetaItemKind::Word(id) => MetaItemKind::Word(id), - MetaItemKind::List(id, mis) => { - MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_list_item(e))) - } - MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s) +pub fn noop_fold_meta_item(mi: MetaItem, fld: &mut T) -> MetaItem { + MetaItem { + name: mi.name, + node: match mi.node { + MetaItemKind::Word => MetaItemKind::Word, + MetaItemKind::List(mis) => { + MetaItemKind::List(mis.move_map(|e| fld.fold_meta_list_item(e))) + }, + MetaItemKind::NameValue(s) => MetaItemKind::NameValue(s), }, - span: fld.new_span(span) - }) + span: fld.new_span(mi.span) + } } pub fn noop_fold_arg(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg { @@ -1240,10 +1238,11 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu }); ExprKind::Path(qself, folder.fold_path(path)) } - ExprKind::Break(opt_ident) => ExprKind::Break(opt_ident.map(|label| - respan(folder.new_span(label.span), - folder.fold_ident(label.node))) - ), + ExprKind::Break(opt_ident, opt_expr) => { + ExprKind::Break(opt_ident.map(|label| respan(folder.new_span(label.span), + folder.fold_ident(label.node))), + opt_expr.map(|e| folder.fold_expr(e))) + } ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label| respan(folder.new_span(label.span), folder.fold_ident(label.node))) @@ -1334,9 +1333,8 @@ pub fn noop_fold_vis(vis: Visibility, folder: &mut T) -> Visibility { #[cfg(test)] mod tests { use std::io; - use ast; + use ast::{self, Ident}; use util::parser_testing::{string_to_crate, matches_codepattern}; - use parse::token; use print::pprust; use fold; use super::*; @@ -1352,7 +1350,7 @@ mod tests { impl Folder for ToZzIdentFolder { fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident { - token::str_to_ident("zz") + Ident::from_str("zz") } fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { fold::noop_fold_mac(mac, self) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 34280812421a..5a1b0d4005e1 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -27,6 +27,7 @@ #![feature(associated_consts)] #![feature(const_fn)] #![feature(libc)] +#![feature(optin_builtin_traits)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(str_escape)] @@ -83,7 +84,6 @@ pub mod diagnostics { pub mod diagnostic_list; pub mod util { - pub mod interner; pub mod lev_distance; pub mod node_count; pub mod parser; @@ -118,6 +118,7 @@ pub mod ptr; pub mod show_span; pub mod std_inject; pub mod str; +pub mod symbol; pub mod test; pub mod tokenstream; pub mod visit; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 983c882eafca..ded676da3c67 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -11,12 +11,11 @@ use attr; use ast; use syntax_pos::{mk_sp, Span}; -use codemap::{spanned, Spanned}; +use codemap::spanned; use parse::common::SeqSep; use parse::PResult; use parse::token; use parse::parser::{Parser, TokenType}; -use ptr::P; #[derive(PartialEq, Eq, Debug)] enum InnerAttributeParsePolicy<'a> { @@ -49,13 +48,9 @@ impl<'a> Parser<'a> { just_parsed_doc_comment = false; } token::DocComment(s) => { - let attr = ::attr::mk_sugared_doc_attr( - attr::mk_attr_id(), - self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)), - self.span.lo, - self.span.hi - ); - if attr.node.style != ast::AttrStyle::Outer { + let Span { lo, hi, .. } = self.span; + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, lo, hi); + if attr.style != ast::AttrStyle::Outer { let mut err = self.fatal("expected outer doc comment"); err.note("inner doc comments like this (starting with \ `//!` or `/*!`) can only appear before items"); @@ -145,14 +140,12 @@ impl<'a> Parser<'a> { style = ast::AttrStyle::Inner; } - Ok(Spanned { + Ok(ast::Attribute { + id: attr::mk_attr_id(), + style: style, + value: value, + is_sugared_doc: false, span: span, - node: ast::Attribute_ { - id: attr::mk_attr_id(), - style: style, - value: value, - is_sugared_doc: false, - }, }) } @@ -172,15 +165,14 @@ impl<'a> Parser<'a> { } let attr = self.parse_attribute(true)?; - assert!(attr.node.style == ast::AttrStyle::Inner); + assert!(attr.style == ast::AttrStyle::Inner); attrs.push(attr); } token::DocComment(s) => { // we need to get the position of this token before we bump. let Span { lo, hi, .. } = self.span; - let str = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)); - let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi); - if attr.node.style == ast::AttrStyle::Inner { + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, lo, hi); + if attr.style == ast::AttrStyle::Inner { attrs.push(attr); self.bump(); } else { @@ -213,7 +205,7 @@ impl<'a> Parser<'a> { /// /// meta_item : IDENT ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; - pub fn parse_meta_item(&mut self) -> PResult<'a, P> { + pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { let nt_meta = match self.token { token::Interpolated(ref nt) => match **nt { token::NtMeta(ref e) => Some(e.clone()), @@ -229,24 +221,15 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let ident = self.parse_ident()?; - let name = self.id_to_interned_str(ident); - match self.token { - token::Eq => { - self.bump(); - let lit = self.parse_unsuffixed_lit()?; - let hi = self.prev_span.hi; - Ok(P(spanned(lo, hi, ast::MetaItemKind::NameValue(name, lit)))) - } - token::OpenDelim(token::Paren) => { - let inner_items = self.parse_meta_seq()?; - let hi = self.prev_span.hi; - Ok(P(spanned(lo, hi, ast::MetaItemKind::List(name, inner_items)))) - } - _ => { - let hi = self.prev_span.hi; - Ok(P(spanned(lo, hi, ast::MetaItemKind::Word(name)))) - } - } + let node = if self.eat(&token::Eq) { + ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?) + } else if self.token == token::OpenDelim(token::Paren) { + ast::MetaItemKind::List(self.parse_meta_seq()?) + } else { + ast::MetaItemKind::Word + }; + let hi = self.prev_span.hi; + Ok(ast::MetaItem { name: ident.name, node: node, span: mk_sp(lo, hi) }) } /// matches meta_item_inner : (meta_item | UNSUFFIXED_LIT) ; diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index cf48c445c80e..681dec0ab564 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use ast::{self, Ident}; use syntax_pos::{self, BytePos, CharPos, Pos, Span}; use codemap::CodeMap; use errors::{FatalError, Handler, DiagnosticBuilder}; use ext::tt::transcribe::tt_next_token; -use parse::token::{self, keywords, str_to_ident}; +use parse::token; use str::char_at; +use symbol::{Symbol, keywords}; use rustc_unicode::property::Pattern_White_Space; use std::borrow::Cow; @@ -350,13 +351,13 @@ impl<'a> StringReader<'a> { /// single-byte delimiter). pub fn name_from(&self, start: BytePos) -> ast::Name { debug!("taking an ident from {:?} to {:?}", start, self.pos); - self.with_str_from(start, token::intern) + self.with_str_from(start, Symbol::intern) } /// As name_from, with an explicit endpoint. pub fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name { debug!("taking an ident from {:?} to {:?}", start, end); - self.with_str_from_to(start, end, token::intern) + self.with_str_from_to(start, end, Symbol::intern) } /// Calls `f` with a string slice of the source text spanning from `start` @@ -492,7 +493,7 @@ impl<'a> StringReader<'a> { if string == "_" { None } else { - Some(token::intern(string)) + Some(Symbol::intern(string)) } }) } @@ -540,7 +541,7 @@ impl<'a> StringReader<'a> { self.with_str_from(start_bpos, |string| { // comments with only more "/"s are not doc comments let tok = if is_doc_comment(string) { - token::DocComment(token::intern(string)) + token::DocComment(Symbol::intern(string)) } else { token::Comment }; @@ -669,7 +670,7 @@ impl<'a> StringReader<'a> { } else { string.into() }; - token::DocComment(token::intern(&string[..])) + token::DocComment(Symbol::intern(&string[..])) } else { token::Comment }; @@ -758,7 +759,7 @@ impl<'a> StringReader<'a> { self.err_span_(start_bpos, self.pos, "no valid digits found for number"); - return token::Integer(token::intern("0")); + return token::Integer(Symbol::intern("0")); } // might be a float, but don't be greedy if this is actually an @@ -1097,7 +1098,7 @@ impl<'a> StringReader<'a> { token::Underscore } else { // FIXME: perform NFKC normalization here. (Issue #2253) - token::Ident(str_to_ident(string)) + token::Ident(Ident::from_str(string)) } })); } @@ -1277,13 +1278,13 @@ impl<'a> StringReader<'a> { // expansion purposes. See #12512 for the gory details of why // this is necessary. let ident = self.with_str_from(start, |lifetime_name| { - str_to_ident(&format!("'{}", lifetime_name)) + Ident::from_str(&format!("'{}", lifetime_name)) }); // Conjure up a "keyword checking ident" to make sure that // the lifetime name is not a keyword. let keyword_checking_ident = self.with_str_from(start, |lifetime_name| { - str_to_ident(lifetime_name) + Ident::from_str(lifetime_name) }); let keyword_checking_token = &token::Ident(keyword_checking_ident); let last_bpos = self.pos; @@ -1310,7 +1311,7 @@ impl<'a> StringReader<'a> { let id = if valid { self.name_from(start) } else { - token::intern("0") + Symbol::intern("0") }; self.bump(); // advance ch past token let suffix = self.scan_optional_raw_name(); @@ -1352,7 +1353,7 @@ impl<'a> StringReader<'a> { let id = if valid { self.name_from(start_bpos + BytePos(1)) } else { - token::intern("??") + Symbol::intern("??") }; self.bump(); let suffix = self.scan_optional_raw_name(); @@ -1424,7 +1425,7 @@ impl<'a> StringReader<'a> { let id = if valid { self.name_from_to(content_start_bpos, content_end_bpos) } else { - token::intern("??") + Symbol::intern("??") }; let suffix = self.scan_optional_raw_name(); return Ok(token::Literal(token::StrRaw(id, hash_count), suffix)); @@ -1551,7 +1552,7 @@ impl<'a> StringReader<'a> { let id = if valid { self.name_from(start) } else { - token::intern("?") + Symbol::intern("?") }; self.bump(); // advance ch past token return token::Byte(id); @@ -1584,7 +1585,7 @@ impl<'a> StringReader<'a> { let id = if valid { self.name_from(start) } else { - token::intern("??") + Symbol::intern("??") }; self.bump(); return token::ByteStr(id); @@ -1700,11 +1701,12 @@ fn ident_continue(c: Option) -> bool { mod tests { use super::*; + use ast::Ident; + use symbol::Symbol; use syntax_pos::{BytePos, Span, NO_EXPANSION}; use codemap::CodeMap; use errors; use parse::token; - use parse::token::str_to_ident; use std::io; use std::rc::Rc; @@ -1732,7 +1734,7 @@ mod tests { &sh, "/* my source file */ fn main() { println!(\"zebra\"); }\n" .to_string()); - let id = str_to_ident("fn"); + let id = Ident::from_str("fn"); assert_eq!(string_reader.next_token().tok, token::Comment); assert_eq!(string_reader.next_token().tok, token::Whitespace); let tok1 = string_reader.next_token(); @@ -1751,7 +1753,7 @@ mod tests { // read another token: let tok3 = string_reader.next_token(); let tok4 = TokenAndSpan { - tok: token::Ident(str_to_ident("main")), + tok: token::Ident(Ident::from_str("main")), sp: Span { lo: BytePos(24), hi: BytePos(28), @@ -1773,7 +1775,7 @@ mod tests { // make the identifier by looking up the string in the interner fn mk_ident(id: &str) -> token::Token { - token::Ident(str_to_ident(id)) + token::Ident(Ident::from_str(id)) } #[test] @@ -1813,7 +1815,7 @@ mod tests { let cm = Rc::new(CodeMap::new()); let sh = mk_sh(cm.clone()); assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok, - token::Literal(token::Char(token::intern("a")), None)); + token::Literal(token::Char(Symbol::intern("a")), None)); } #[test] @@ -1821,7 +1823,7 @@ mod tests { let cm = Rc::new(CodeMap::new()); let sh = mk_sh(cm.clone()); assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok, - token::Literal(token::Char(token::intern(" ")), None)); + token::Literal(token::Char(Symbol::intern(" ")), None)); } #[test] @@ -1829,7 +1831,7 @@ mod tests { let cm = Rc::new(CodeMap::new()); let sh = mk_sh(cm.clone()); assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok, - token::Literal(token::Char(token::intern("\\n")), None)); + token::Literal(token::Char(Symbol::intern("\\n")), None)); } #[test] @@ -1837,7 +1839,7 @@ mod tests { let cm = Rc::new(CodeMap::new()); let sh = mk_sh(cm.clone()); assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok, - token::Lifetime(token::str_to_ident("'abc"))); + token::Lifetime(Ident::from_str("'abc"))); } #[test] @@ -1847,7 +1849,7 @@ mod tests { assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()) .next_token() .tok, - token::Literal(token::StrRaw(token::intern("\"#a\\b\x00c\""), 3), None)); + token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None)); } #[test] @@ -1857,11 +1859,11 @@ mod tests { macro_rules! test { ($input: expr, $tok_type: ident, $tok_contents: expr) => {{ assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok, - token::Literal(token::$tok_type(token::intern($tok_contents)), - Some(token::intern("suffix")))); + token::Literal(token::$tok_type(Symbol::intern($tok_contents)), + Some(Symbol::intern("suffix")))); // with a whitespace separator: assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok, - token::Literal(token::$tok_type(token::intern($tok_contents)), + token::Literal(token::$tok_type(Symbol::intern($tok_contents)), None)); }} } @@ -1877,14 +1879,14 @@ mod tests { test!("1.0e10", Float, "1.0e10"); assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok, - token::Literal(token::Integer(token::intern("2")), - Some(token::intern("us")))); + token::Literal(token::Integer(Symbol::intern("2")), + Some(Symbol::intern("us")))); assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok, - token::Literal(token::StrRaw(token::intern("raw"), 3), - Some(token::intern("suffix")))); + token::Literal(token::StrRaw(Symbol::intern("raw"), 3), + Some(Symbol::intern("suffix")))); assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok, - token::Literal(token::ByteStrRaw(token::intern("raw"), 3), - Some(token::intern("suffix")))); + token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3), + Some(Symbol::intern("suffix")))); } #[test] @@ -1904,7 +1906,7 @@ mod tests { _ => panic!("expected a comment!"), } assert_eq!(lexer.next_token().tok, - token::Literal(token::Char(token::intern("a")), None)); + token::Literal(token::Char(Symbol::intern("a")), None)); } #[test] @@ -1917,6 +1919,6 @@ mod tests { assert_eq!(comment.sp, ::syntax_pos::mk_sp(BytePos(0), BytePos(7))); assert_eq!(lexer.next_token().tok, token::Whitespace); assert_eq!(lexer.next_token().tok, - token::DocComment(token::intern("/// test"))); + token::DocComment(Symbol::intern("/// test"))); } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 12408c7d3c95..bfaf00a3d3f0 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -16,12 +16,13 @@ use syntax_pos::{self, Span, FileMap}; use errors::{Handler, ColorConfig, DiagnosticBuilder}; use feature_gate::UnstableFeatures; use parse::parser::Parser; -use parse::token::InternedString; use ptr::P; use str::char_at; +use symbol::Symbol; use tokenstream; use std::cell::RefCell; +use std::collections::HashSet; use std::iter; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -64,7 +65,7 @@ impl ParseSess { ParseSess { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(), - config: Vec::new(), + config: HashSet::new(), included_mod_stack: RefCell::new(vec![]), code_map: code_map } @@ -75,6 +76,19 @@ impl ParseSess { } } +#[derive(Clone)] +pub struct Directory { + pub path: PathBuf, + pub ownership: DirectoryOwnership, +} + +#[derive(Copy, Clone)] +pub enum DirectoryOwnership { + Owned, + UnownedViaBlock, + UnownedViaMod(bool /* legacy warnings? */), +} + // a bunch of utility functions of the form parse__from_ // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and @@ -116,7 +130,7 @@ pub fn parse_item_from_source_str<'a>(name: String, source: String, sess: &'a Pa } pub fn parse_meta_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess) - -> PResult<'a, P> { + -> PResult<'a, ast::MetaItem> { new_parser_from_source_str(sess, name, source).parse_meta_item() } @@ -151,11 +165,11 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> /// On an error, use the given span as the source of the problem. pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, - owns_directory: bool, + directory_ownership: DirectoryOwnership, module_name: Option, sp: Span) -> Parser<'a> { let mut p = filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp))); - p.owns_directory = owns_directory; + p.directory.ownership = directory_ownership; p.root_module_name = module_name; p } @@ -371,13 +385,18 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s[1..].chars().all(|c| '0' <= c && c <= '9') } -fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, - sd: &Handler, sp: Span) -> ast::LitKind { +fn filtered_float_lit(data: Symbol, suffix: Option, sd: &Handler, sp: Span) + -> ast::LitKind { debug!("filtered_float_lit: {}, {:?}", data, suffix); - match suffix.as_ref().map(|s| &**s) { - Some("f32") => ast::LitKind::Float(data, ast::FloatTy::F32), - Some("f64") => ast::LitKind::Float(data, ast::FloatTy::F64), - Some(suf) => { + let suffix = match suffix { + Some(suffix) => suffix, + None => return ast::LitKind::FloatUnsuffixed(data), + }; + + match &*suffix.as_str() { + "f32" => ast::LitKind::Float(data, ast::FloatTy::F32), + "f64" => ast::LitKind::Float(data, ast::FloatTy::F64), + suf => { if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { // if it looks like a width, lets try to be helpful. sd.struct_span_err(sp, &format!("invalid width `{}` for float literal", &suf[1..])) @@ -391,16 +410,13 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, ast::LitKind::FloatUnsuffixed(data) } - None => ast::LitKind::FloatUnsuffixed(data) } } -pub fn float_lit(s: &str, suffix: Option, - sd: &Handler, sp: Span) -> ast::LitKind { +pub fn float_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> ast::LitKind { debug!("float_lit: {:?}, {:?}", s, suffix); // FIXME #2252: bounds checking float literals is deferred until trans let s = s.chars().filter(|&c| c != '_').collect::(); - let data = token::intern_and_get_ident(&s); - filtered_float_lit(data, suffix.as_ref().map(|s| &**s), sd, sp) + filtered_float_lit(Symbol::intern(&s), suffix, sd, sp) } /// Parse a string representing a byte literal into its final form. Similar to `char_lit` @@ -495,11 +511,7 @@ pub fn byte_str_lit(lit: &str) -> Rc> { Rc::new(res) } -pub fn integer_lit(s: &str, - suffix: Option, - sd: &Handler, - sp: Span) - -> ast::LitKind { +pub fn integer_lit(s: &str, suffix: Option, sd: &Handler, sp: Span) -> ast::LitKind { // s can only be ascii, byte indexing is fine let s2 = s.chars().filter(|&c| c != '_').collect::(); @@ -521,16 +533,15 @@ pub fn integer_lit(s: &str, } // 1f64 and 2f32 etc. are valid float literals. - if let Some(ref suf) = suffix { - if looks_like_width_suffix(&['f'], suf) { + if let Some(suf) = suffix { + if looks_like_width_suffix(&['f'], &suf.as_str()) { match base { 16 => sd.span_err(sp, "hexadecimal float literal is not supported"), 8 => sd.span_err(sp, "octal float literal is not supported"), 2 => sd.span_err(sp, "binary float literal is not supported"), _ => () } - let ident = token::intern_and_get_ident(&s); - return filtered_float_lit(ident, Some(&suf), sd, sp) + return filtered_float_lit(Symbol::intern(&s), Some(suf), sd, sp) } } @@ -538,9 +549,9 @@ pub fn integer_lit(s: &str, s = &s[2..]; } - if let Some(ref suf) = suffix { - if suf.is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")} - ty = match &**suf { + if let Some(suf) = suffix { + if suf.as_str().is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")} + ty = match &*suf.as_str() { "isize" => ast::LitIntType::Signed(ast::IntTy::Is), "i8" => ast::LitIntType::Signed(ast::IntTy::I8), "i16" => ast::LitIntType::Signed(ast::IntTy::I16), @@ -551,7 +562,7 @@ pub fn integer_lit(s: &str, "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16), "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32), "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64), - _ => { + suf => { // i and u look like widths, so lets // give an error message along those lines if looks_like_width_suffix(&['i', 'u'], suf) { @@ -599,12 +610,11 @@ mod tests { use std::rc::Rc; use syntax_pos::{self, Span, BytePos, Pos, NO_EXPANSION}; use codemap::Spanned; - use ast::{self, PatKind}; + use ast::{self, Ident, PatKind}; use abi::Abi; use attr::first_attr_value_str_by_name; use parse; use parse::parser::Parser; - use parse::token::{str_to_ident}; use print::pprust::item_to_string; use ptr::P; use tokenstream::{self, TokenTree}; @@ -626,7 +636,7 @@ mod tests { global: false, segments: vec![ ast::PathSegment { - identifier: str_to_ident("a"), + identifier: Ident::from_str("a"), parameters: ast::PathParameters::none(), } ], @@ -645,11 +655,11 @@ mod tests { global: true, segments: vec![ ast::PathSegment { - identifier: str_to_ident("a"), + identifier: Ident::from_str("a"), parameters: ast::PathParameters::none(), }, ast::PathSegment { - identifier: str_to_ident("b"), + identifier: Ident::from_str("b"), parameters: ast::PathParameters::none(), } ] @@ -678,8 +688,8 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(name_zip))), Some(&TokenTree::Delimited(_, ref macro_delimed)), ) - if name_macro_rules.name.as_str() == "macro_rules" - && name_zip.name.as_str() == "zip" => { + if name_macro_rules.name == "macro_rules" + && name_zip.name == "zip" => { let tts = ¯o_delimed.tts[..]; match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) { ( @@ -696,8 +706,7 @@ mod tests { Some(&TokenTree::Token(_, token::Dollar)), Some(&TokenTree::Token(_, token::Ident(ident))), ) - if first_delimed.delim == token::Paren - && ident.name.as_str() == "a" => {}, + if first_delimed.delim == token::Paren && ident.name == "a" => {}, _ => panic!("value 3: {:?}", **first_delimed), } let tts = &second_delimed.tts[..]; @@ -708,7 +717,7 @@ mod tests { Some(&TokenTree::Token(_, token::Ident(ident))), ) if second_delimed.delim == token::Paren - && ident.name.as_str() == "a" => {}, + && ident.name == "a" => {}, _ => panic!("value 4: {:?}", **second_delimed), } }, @@ -724,17 +733,17 @@ mod tests { let tts = string_to_tts("fn a (b : i32) { b; }".to_string()); let expected = vec![ - TokenTree::Token(sp(0, 2), token::Ident(str_to_ident("fn"))), - TokenTree::Token(sp(3, 4), token::Ident(str_to_ident("a"))), + TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"))), + TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"))), TokenTree::Delimited( sp(5, 14), Rc::new(tokenstream::Delimited { delim: token::DelimToken::Paren, open_span: sp(5, 6), tts: vec![ - TokenTree::Token(sp(6, 7), token::Ident(str_to_ident("b"))), + TokenTree::Token(sp(6, 7), token::Ident(Ident::from_str("b"))), TokenTree::Token(sp(8, 9), token::Colon), - TokenTree::Token(sp(10, 13), token::Ident(str_to_ident("i32"))), + TokenTree::Token(sp(10, 13), token::Ident(Ident::from_str("i32"))), ], close_span: sp(13, 14), })), @@ -744,7 +753,7 @@ mod tests { delim: token::DelimToken::Brace, open_span: sp(15, 16), tts: vec![ - TokenTree::Token(sp(17, 18), token::Ident(str_to_ident("b"))), + TokenTree::Token(sp(17, 18), token::Ident(Ident::from_str("b"))), TokenTree::Token(sp(18, 19), token::Semi), ], close_span: sp(20, 21), @@ -765,7 +774,7 @@ mod tests { global: false, segments: vec![ ast::PathSegment { - identifier: str_to_ident("d"), + identifier: Ident::from_str("d"), parameters: ast::PathParameters::none(), } ], @@ -788,7 +797,7 @@ mod tests { global:false, segments: vec![ ast::PathSegment { - identifier: str_to_ident("b"), + identifier: Ident::from_str("b"), parameters: ast::PathParameters::none(), } ], @@ -812,7 +821,7 @@ mod tests { id: ast::DUMMY_NODE_ID, node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable), Spanned{ span:sp(0, 1), - node: str_to_ident("b") + node: Ident::from_str("b") }, None), span: sp(0,1)})); @@ -824,7 +833,7 @@ mod tests { // this test depends on the intern order of "fn" and "i32" assert_eq!(string_to_item("fn a (b : i32) { b; }".to_string()), Some( - P(ast::Item{ident:str_to_ident("a"), + P(ast::Item{ident:Ident::from_str("a"), attrs:Vec::new(), id: ast::DUMMY_NODE_ID, node: ast::ItemKind::Fn(P(ast::FnDecl { @@ -835,8 +844,7 @@ mod tests { global:false, segments: vec![ ast::PathSegment { - identifier: - str_to_ident("i32"), + identifier: Ident::from_str("i32"), parameters: ast::PathParameters::none(), } ], @@ -849,7 +857,7 @@ mod tests { ast::BindingMode::ByValue(ast::Mutability::Immutable), Spanned{ span: sp(6,7), - node: str_to_ident("b")}, + node: Ident::from_str("b")}, None ), span: sp(6,7) @@ -884,9 +892,7 @@ mod tests { global:false, segments: vec![ ast::PathSegment { - identifier: - str_to_ident( - "b"), + identifier: Ident::from_str("b"), parameters: ast::PathParameters::none(), } @@ -998,12 +1004,12 @@ mod tests { let item = parse_item_from_source_str(name.clone(), source, &sess) .unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); - assert_eq!(&doc[..], "/// doc comment"); + assert_eq!(doc, "/// doc comment"); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name.clone(), source, &sess) .unwrap().unwrap(); - let docs = item.attrs.iter().filter(|a| &*a.name() == "doc") + let docs = item.attrs.iter().filter(|a| a.name() == "doc") .map(|a| a.value_str().unwrap().to_string()).collect::>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; assert_eq!(&docs[..], b); @@ -1011,7 +1017,7 @@ mod tests { let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name, source, &sess).unwrap().unwrap(); let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap(); - assert_eq!(&doc[..], "/** doc comment\n * with CRLF */"); + assert_eq!(doc, "/** doc comment\n * with CRLF */"); } #[test] diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2e38ca82d5db..49226be4147d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -38,7 +38,7 @@ use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; use ast::{BinOpKind, UnOp}; -use ast; +use {ast, attr}; use codemap::{self, CodeMap, Spanned, spanned, respan}; use syntax_pos::{self, Span, BytePos, mk_sp}; use errors::{self, DiagnosticBuilder}; @@ -48,13 +48,14 @@ use parse::classify; use parse::common::SeqSep; use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::ObsoleteSyntax; -use parse::token::{self, intern, keywords, MatchNt, SubstNt, InternedString}; -use parse::{new_sub_parser_from_file, ParseSess}; +use parse::token::{self, MatchNt, SubstNt}; +use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; use util::parser::{AssocOp, Fixity}; use print::pprust; use ptr::P; use parse::PResult; use tokenstream::{self, Delimited, SequenceRepetition, TokenTree}; +use symbol::{Symbol, keywords}; use util::ThinVec; use std::collections::HashSet; @@ -67,7 +68,6 @@ bitflags! { flags Restrictions: u8 { const RESTRICTION_STMT_EXPR = 1 << 0, const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, - const NO_NONINLINE_MOD = 1 << 2, } } @@ -199,12 +199,9 @@ pub struct Parser<'a> { /// extra detail when the same error is seen twice pub obsolete_set: HashSet, /// Used to determine the path to externally loaded source files - pub directory: PathBuf, + pub directory: Directory, /// Stack of open delimiters and their spans. Used for error message. pub open_braces: Vec<(token::DelimToken, Span)>, - /// Flag if this parser "owns" the directory that it is currently parsing - /// in. This will affect how nested files are looked up. - pub owns_directory: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. @@ -244,8 +241,9 @@ pub struct ModulePath { } pub struct ModulePathSuccess { - pub path: ::std::path::PathBuf, - pub owns_directory: bool, + pub path: PathBuf, + pub directory_ownership: DirectoryOwnership, + warn: bool, } pub struct ModulePathError { @@ -295,9 +293,8 @@ impl<'a> Parser<'a> { quote_depth: 0, parsing_token_tree: false, obsolete_set: HashSet::new(), - directory: PathBuf::new(), + directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned }, open_braces: Vec::new(), - owns_directory: true, root_module_name: None, expected_tokens: Vec::new(), tts: Vec::new(), @@ -309,8 +306,8 @@ impl<'a> Parser<'a> { parser.token = tok.tok; parser.span = tok.sp; if parser.span != syntax_pos::DUMMY_SP { - parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span)); - parser.directory.pop(); + parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span)); + parser.directory.path.pop(); } parser } @@ -998,10 +995,6 @@ impl<'a> Parser<'a> { &self.sess.span_diagnostic } - pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString { - id.name.as_str() - } - /// Is the current token one of the keywords that signals a bare function /// type? pub fn token_is_bare_fn_keyword(&mut self) -> bool { @@ -1523,34 +1516,28 @@ impl<'a> Parser<'a> { // float literals, so all the handling is done // internally. token::Integer(s) => { - (false, parse::integer_lit(&s.as_str(), - suf.as_ref().map(|s| s.as_str()), - &self.sess.span_diagnostic, - self.span)) + let diag = &self.sess.span_diagnostic; + (false, parse::integer_lit(&s.as_str(), suf, diag, self.span)) } token::Float(s) => { - (false, parse::float_lit(&s.as_str(), - suf.as_ref().map(|s| s.as_str()), - &self.sess.span_diagnostic, - self.span)) + let diag = &self.sess.span_diagnostic; + (false, parse::float_lit(&s.as_str(), suf, diag, self.span)) } token::Str_(s) => { - (true, - LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())), - ast::StrStyle::Cooked)) + let s = Symbol::intern(&parse::str_lit(&s.as_str())); + (true, LitKind::Str(s, ast::StrStyle::Cooked)) } token::StrRaw(s, n) => { - (true, - LitKind::Str( - token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())), - ast::StrStyle::Raw(n))) + let s = Symbol::intern(&parse::raw_str_lit(&s.as_str())); + (true, LitKind::Str(s, ast::StrStyle::Raw(n))) + } + token::ByteStr(i) => { + (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))) + } + token::ByteStrRaw(i, _) => { + (true, LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))) } - token::ByteStr(i) => - (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))), - token::ByteStrRaw(i, _) => - (true, - LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))), }; if suffix_illegal { @@ -2269,15 +2256,25 @@ impl<'a> Parser<'a> { ex = ExprKind::Ret(None); } } else if self.eat_keyword(keywords::Break) { - if self.token.is_lifetime() { - ex = ExprKind::Break(Some(Spanned { + let lt = if self.token.is_lifetime() { + let spanned_lt = Spanned { node: self.get_lifetime(), span: self.span - })); + }; self.bump(); + Some(spanned_lt) } else { - ex = ExprKind::Break(None); - } + None + }; + let e = if self.token.can_begin_expr() + && !(self.token == token::OpenDelim(token::Brace) + && self.restrictions.contains( + Restrictions::RESTRICTION_NO_STRUCT_LITERAL)) { + Some(self.parse_expr()?) + } else { + None + }; + ex = ExprKind::Break(lt, e); hi = self.prev_span.hi; } else if self.token.is_keyword(keywords::Let) { // Catch this syntax error here, instead of in `check_strict_keywords`, so @@ -2544,7 +2541,7 @@ impl<'a> Parser<'a> { let prev_span = self.prev_span; let fstr = n.as_str(); let mut err = self.diagnostic().struct_span_err(prev_span, - &format!("unexpected token: `{}`", n.as_str())); + &format!("unexpected token: `{}`", n)); if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::().ok() { Some(f) => f, @@ -2627,7 +2624,7 @@ impl<'a> Parser<'a> { }))); } else if self.token.is_keyword(keywords::Crate) { let ident = match self.token { - token::Ident(id) => ast::Ident { name: token::intern("$crate"), ..id }, + token::Ident(id) => ast::Ident { name: Symbol::intern("$crate"), ..id }, _ => unreachable!(), }; self.bump(); @@ -3751,9 +3748,7 @@ impl<'a> Parser<'a> { /// Emit an expected item after attributes error. fn expected_item_err(&self, attrs: &[Attribute]) { let message = match attrs.last() { - Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => { - "expected item after doc comment" - } + Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment", _ => "expected item after attributes", }; @@ -3977,9 +3972,11 @@ impl<'a> Parser<'a> { } } else { // FIXME: Bad copy of attrs - let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD; - match self.with_res(restrictions, - |this| this.parse_item_(attrs.clone(), false, true))? { + let old_directory_ownership = + mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); + let item = self.parse_item_(attrs.clone(), false, true)?; + self.directory.ownership = old_directory_ownership; + match item { Some(i) => Stmt { id: ast::DUMMY_NODE_ID, span: mk_sp(lo, i.span.hi), @@ -4837,7 +4834,7 @@ impl<'a> Parser<'a> { Visibility::Inherited => (), _ => { let is_macro_rules: bool = match self.token { - token::Ident(sid) => sid.name == intern("macro_rules"), + token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), _ => false, }; if is_macro_rules { @@ -5282,39 +5279,53 @@ impl<'a> Parser<'a> { self.bump(); if in_cfg { // This mod is in an external file. Let's go get it! - let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?; - Ok((id, m, Some(attrs))) + let ModulePathSuccess { path, directory_ownership, warn } = + self.submod_path(id, &outer_attrs, id_span)?; + let (module, mut attrs) = + self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; + if warn { + let attr = ast::Attribute { + id: attr::mk_attr_id(), + style: ast::AttrStyle::Outer, + value: ast::MetaItem { + name: Symbol::intern("warn_directory_ownership"), + node: ast::MetaItemKind::Word, + span: syntax_pos::DUMMY_SP, + }, + is_sugared_doc: false, + span: syntax_pos::DUMMY_SP, + }; + attr::mark_known(&attr); + attrs.push(attr); + } + Ok((id, module, Some(attrs))) } else { let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() }; Ok((id, ItemKind::Mod(placeholder), None)) } } else { - let directory = self.directory.clone(); - let restrictions = self.push_directory(id, &outer_attrs); + let old_directory = self.directory.clone(); + self.push_directory(id, &outer_attrs); self.expect(&token::OpenDelim(token::Brace))?; let mod_inner_lo = self.span.lo; let attrs = self.parse_inner_attributes()?; - let m = self.with_res(restrictions, |this| { - this.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo) - })?; - self.directory = directory; - Ok((id, ItemKind::Mod(m), Some(attrs))) + let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; + self.directory = old_directory; + Ok((id, ItemKind::Mod(module), Some(attrs))) } } - fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) -> Restrictions { - if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") { - self.directory.push(&*path); - self.restrictions - Restrictions::NO_NONINLINE_MOD + fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { + if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") { + self.directory.path.push(&*path.as_str()); + self.directory.ownership = DirectoryOwnership::Owned; } else { - let default_path = self.id_to_interned_str(id); - self.directory.push(&*default_path); - self.restrictions + self.directory.path.push(&*id.name.as_str()); } } pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option { - ::attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d)) + attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d.as_str())) } /// Returns either a path to a module, or . @@ -5329,8 +5340,16 @@ impl<'a> Parser<'a> { let secondary_exists = codemap.file_exists(&secondary_path); let result = match (default_exists, secondary_exists) { - (true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }), - (false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }), + (true, false) => Ok(ModulePathSuccess { + path: default_path, + directory_ownership: DirectoryOwnership::UnownedViaMod(false), + warn: false, + }), + (false, true) => Ok(ModulePathSuccess { + path: secondary_path, + directory_ownership: DirectoryOwnership::Owned, + warn: false, + }), (false, false) => Err(ModulePathError { err_msg: format!("file not found for module `{}`", mod_name), help_msg: format!("name the file either {} or {} inside the directory {:?}", @@ -5358,13 +5377,20 @@ impl<'a> Parser<'a> { id: ast::Ident, outer_attrs: &[ast::Attribute], id_sp: Span) -> PResult<'a, ModulePathSuccess> { - if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &self.directory) { - return Ok(ModulePathSuccess { path: p, owns_directory: true }); + if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { + return Ok(ModulePathSuccess { + directory_ownership: match path.file_name().and_then(|s| s.to_str()) { + Some("mod.rs") => DirectoryOwnership::Owned, + _ => DirectoryOwnership::UnownedViaMod(true), + }, + path: path, + warn: false, + }); } - let paths = Parser::default_submod_path(id, &self.directory, self.sess.codemap()); + let paths = Parser::default_submod_path(id, &self.directory.path, self.sess.codemap()); - if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) { + if let DirectoryOwnership::UnownedViaBlock = self.directory.ownership { let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; let mut err = self.diagnostic().struct_span_err(id_sp, msg); @@ -5374,10 +5400,15 @@ impl<'a> Parser<'a> { err.span_note(id_sp, &msg); } return Err(err); - } else if !self.owns_directory { + } else if let DirectoryOwnership::UnownedViaMod(warn) = self.directory.ownership { + if warn { + if let Ok(result) = paths.result { + return Ok(ModulePathSuccess { warn: true, ..result }); + } + } let mut err = self.diagnostic().struct_span_err(id_sp, "cannot declare a new module at this location"); - let this_module = match self.directory.file_name() { + let this_module = match self.directory.path.file_name() { Some(file_name) => file_name.to_str().unwrap().to_owned(), None => self.root_module_name.as_ref().unwrap().clone(), }; @@ -5390,8 +5421,10 @@ impl<'a> Parser<'a> { &format!("... or maybe `use` the module `{}` instead \ of possibly redeclaring it", paths.name)); - } - return Err(err); + return Err(err); + } else { + return Err(err); + }; } match paths.result { @@ -5402,25 +5435,11 @@ impl<'a> Parser<'a> { /// Read a module from a source file. fn eval_src_mod(&mut self, - id: ast::Ident, - outer_attrs: &[ast::Attribute], + path: PathBuf, + directory_ownership: DirectoryOwnership, + name: String, id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec )> { - let ModulePathSuccess { path, owns_directory } = self.submod_path(id, - outer_attrs, - id_sp)?; - - self.eval_src_mod_from_path(path, - owns_directory, - id.to_string(), - id_sp) - } - - fn eval_src_mod_from_path(&mut self, - path: PathBuf, - owns_directory: bool, - name: String, - id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec )> { let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { let mut err = String::from("circular modules: "); @@ -5435,7 +5454,8 @@ impl<'a> Parser<'a> { included_mod_stack.push(path.clone()); drop(included_mod_stack); - let mut p0 = new_sub_parser_from_file(self.sess, &path, owns_directory, Some(name), id_sp); + let mut p0 = + new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); let mod_inner_lo = p0.span.lo; let mod_attrs = p0.parse_inner_attributes()?; let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; @@ -6128,26 +6148,17 @@ impl<'a> Parser<'a> { }) } - pub fn parse_optional_str(&mut self) - -> Option<(InternedString, - ast::StrStyle, - Option)> { + pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { let ret = match self.token { - token::Literal(token::Str_(s), suf) => { - let s = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)); - (s, ast::StrStyle::Cooked, suf) - } - token::Literal(token::StrRaw(s, n), suf) => { - let s = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)); - (s, ast::StrStyle::Raw(n), suf) - } + token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf), + token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf), _ => return None }; self.bump(); Some(ret) } - pub fn parse_str(&mut self) -> PResult<'a, (InternedString, StrStyle)> { + pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> { match self.parse_optional_str() { Some((s, style, suf)) => { let sp = self.prev_span; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 0198ee073d23..8ac39dd462e7 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -16,13 +16,10 @@ pub use self::Token::*; use ast::{self}; use ptr::P; -use util::interner::Interner; +use symbol::keywords; use tokenstream; -use serialize::{Decodable, Decoder, Encodable, Encoder}; -use std::cell::RefCell; use std::fmt; -use std::ops::Deref; use std::rc::Rc; #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -301,7 +298,7 @@ pub enum Nonterminal { NtTy(P), NtIdent(ast::SpannedIdent), /// Stuff inside brackets for attributes - NtMeta(P), + NtMeta(ast::MetaItem), NtPath(ast::Path), NtTT(tokenstream::TokenTree), // These are not exposed to macros, but are used by quasiquote. @@ -335,270 +332,3 @@ impl fmt::Debug for Nonterminal { } } } - -// In this macro, there is the requirement that the name (the number) must be monotonically -// increasing by one in the special identifiers, starting at 0; the same holds for the keywords, -// except starting from the next number instead of zero. -macro_rules! declare_keywords {( - $( ($index: expr, $konst: ident, $string: expr) )* -) => { - pub mod keywords { - use ast; - #[derive(Clone, Copy, PartialEq, Eq)] - pub struct Keyword { - ident: ast::Ident, - } - impl Keyword { - #[inline] pub fn ident(self) -> ast::Ident { self.ident } - #[inline] pub fn name(self) -> ast::Name { self.ident.name } - } - $( - #[allow(non_upper_case_globals)] - pub const $konst: Keyword = Keyword { - ident: ast::Ident::with_empty_ctxt(ast::Name($index)) - }; - )* - } - - fn mk_fresh_ident_interner() -> IdentInterner { - Interner::prefill(&[$($string,)*]) - } -}} - -// NB: leaving holes in the ident table is bad! a different ident will get -// interned with the id from the hole, but it will be between the min and max -// of the reserved words, and thus tagged as "reserved". -// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`, -// this should be rarely necessary though if the keywords are kept in alphabetic order. -declare_keywords! { - // Invalid identifier - (0, Invalid, "") - - // Strict keywords used in the language. - (1, As, "as") - (2, Box, "box") - (3, Break, "break") - (4, Const, "const") - (5, Continue, "continue") - (6, Crate, "crate") - (7, Else, "else") - (8, Enum, "enum") - (9, Extern, "extern") - (10, False, "false") - (11, Fn, "fn") - (12, For, "for") - (13, If, "if") - (14, Impl, "impl") - (15, In, "in") - (16, Let, "let") - (17, Loop, "loop") - (18, Match, "match") - (19, Mod, "mod") - (20, Move, "move") - (21, Mut, "mut") - (22, Pub, "pub") - (23, Ref, "ref") - (24, Return, "return") - (25, SelfValue, "self") - (26, SelfType, "Self") - (27, Static, "static") - (28, Struct, "struct") - (29, Super, "super") - (30, Trait, "trait") - (31, True, "true") - (32, Type, "type") - (33, Unsafe, "unsafe") - (34, Use, "use") - (35, Where, "where") - (36, While, "while") - - // Keywords reserved for future use. - (37, Abstract, "abstract") - (38, Alignof, "alignof") - (39, Become, "become") - (40, Do, "do") - (41, Final, "final") - (42, Macro, "macro") - (43, Offsetof, "offsetof") - (44, Override, "override") - (45, Priv, "priv") - (46, Proc, "proc") - (47, Pure, "pure") - (48, Sizeof, "sizeof") - (49, Typeof, "typeof") - (50, Unsized, "unsized") - (51, Virtual, "virtual") - (52, Yield, "yield") - - // Weak keywords, have special meaning only in specific contexts. - (53, Default, "default") - (54, StaticLifetime, "'static") - (55, Union, "union") -} - -// looks like we can get rid of this completely... -pub type IdentInterner = Interner; - -// if an interner exists in TLS, return it. Otherwise, prepare a -// fresh one. -// FIXME(eddyb) #8726 This should probably use a thread-local reference. -pub fn with_ident_interner T>(f: F) -> T { - thread_local!(static KEY: RefCell = { - RefCell::new(mk_fresh_ident_interner()) - }); - KEY.with(|interner| f(&mut *interner.borrow_mut())) -} - -/// Reset the ident interner to its initial state. -pub fn reset_ident_interner() { - with_ident_interner(|interner| *interner = mk_fresh_ident_interner()); -} - -pub fn clear_ident_interner() { - with_ident_interner(|interner| *interner = IdentInterner::new()); -} - -/// Represents a string stored in the thread-local interner. Because the -/// interner lives for the life of the thread, this can be safely treated as an -/// immortal string, as long as it never crosses between threads. -/// -/// FIXME(pcwalton): You must be careful about what you do in the destructors -/// of objects stored in TLS, because they may run after the interner is -/// destroyed. In particular, they must not access string contents. This can -/// be fixed in the future by just leaking all strings until thread death -/// somehow. -#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)] -pub struct InternedString { - string: Rc, -} - -impl InternedString { - #[inline] - pub fn new(string: &'static str) -> InternedString { - InternedString { - string: Rc::__from_str(string), - } - } - - #[inline] - pub fn new_from_name(name: ast::Name) -> InternedString { - with_ident_interner(|interner| InternedString { string: interner.get(name) }) - } -} - -impl Deref for InternedString { - type Target = str; - - fn deref(&self) -> &str { &self.string } -} - -impl fmt::Debug for InternedString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.string, f) - } -} - -impl fmt::Display for InternedString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.string, f) - } -} - -impl<'a> PartialEq<&'a str> for InternedString { - #[inline(always)] - fn eq(&self, other: & &'a str) -> bool { - PartialEq::eq(&self.string[..], *other) - } - #[inline(always)] - fn ne(&self, other: & &'a str) -> bool { - PartialEq::ne(&self.string[..], *other) - } -} - -impl<'a> PartialEq for &'a str { - #[inline(always)] - fn eq(&self, other: &InternedString) -> bool { - PartialEq::eq(*self, &other.string[..]) - } - #[inline(always)] - fn ne(&self, other: &InternedString) -> bool { - PartialEq::ne(*self, &other.string[..]) - } -} - -impl PartialEq for InternedString { - #[inline(always)] - fn eq(&self, other: &str) -> bool { - PartialEq::eq(&self.string[..], other) - } - #[inline(always)] - fn ne(&self, other: &str) -> bool { - PartialEq::ne(&self.string[..], other) - } -} - -impl PartialEq for str { - #[inline(always)] - fn eq(&self, other: &InternedString) -> bool { - PartialEq::eq(self, &other.string[..]) - } - #[inline(always)] - fn ne(&self, other: &InternedString) -> bool { - PartialEq::ne(self, &other.string[..]) - } -} - -impl Decodable for InternedString { - fn decode(d: &mut D) -> Result { - Ok(intern(&d.read_str()?).as_str()) - } -} - -impl Encodable for InternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.string) - } -} - -/// Interns and returns the string contents of an identifier, using the -/// thread-local interner. -#[inline] -pub fn intern_and_get_ident(s: &str) -> InternedString { - intern(s).as_str() -} - -/// Maps a string to its interned representation. -#[inline] -pub fn intern(s: &str) -> ast::Name { - with_ident_interner(|interner| interner.intern(s)) -} - -/// gensym's a new usize, using the current interner. -#[inline] -pub fn gensym(s: &str) -> ast::Name { - with_ident_interner(|interner| interner.gensym(s)) -} - -/// Maps a string to an identifier with an empty syntax context. -#[inline] -pub fn str_to_ident(s: &str) -> ast::Ident { - ast::Ident::with_empty_ctxt(intern(s)) -} - -/// Maps a string to a gensym'ed identifier. -#[inline] -pub fn gensym_ident(s: &str) -> ast::Ident { - ast::Ident::with_empty_ctxt(gensym(s)) -} - -// create a fresh name that maps to the same string as the old one. -// note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src))); -// that is, that the new name and the old one are connected to ptr_eq strings. -pub fn fresh_name(src: ast::Ident) -> ast::Name { - with_ident_interner(|interner| interner.gensym_copy(src.name)) - // following: debug version. Could work in final except that it's incompatible with - // good error messages and uses of struct names in ambiguous could-be-binding - // locations. Also definitely destroys the guarantee given above about ptr_eq. - /*let num = rand::thread_rng().gen_uint_range(0,0xffff); - gensym(format!("{}_{}",ident_to_string(src),num))*/ -} diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 203c19285ac2..c28b9d00501b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -19,7 +19,7 @@ use attr; use codemap::{self, CodeMap}; use syntax_pos::{self, BytePos}; use errors; -use parse::token::{self, keywords, BinOpToken, Token, InternedString}; +use parse::token::{self, BinOpToken, Token}; use parse::lexer::comments; use parse; use print::pp::{self, break_offset, word, space, zerobreak, hardbreak}; @@ -27,6 +27,7 @@ use print::pp::{Breaks, eof}; use print::pp::Breaks::{Consistent, Inconsistent}; use ptr::P; use std_inject; +use symbol::{Symbol, keywords}; use tokenstream::{self, TokenTree}; use std::ascii; @@ -119,14 +120,13 @@ pub fn print_crate<'a>(cm: &'a CodeMap, // of the feature gate, so we fake them up here. // #![feature(prelude_import)] - let prelude_import_meta = attr::mk_list_word_item(InternedString::new("prelude_import")); - let list = attr::mk_list_item(InternedString::new("feature"), - vec![prelude_import_meta]); + let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import")); + let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]); let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list); try!(s.print_attribute(&fake_attr)); // #![no_std] - let no_std_meta = attr::mk_word_item(InternedString::new("no_std")); + let no_std_meta = attr::mk_word_item(Symbol::intern("no_std")); let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta); try!(s.print_attribute(&fake_attr)); } @@ -630,7 +630,7 @@ pub trait PrintState<'a> { _ => () } match lit.node { - ast::LitKind::Str(ref st, style) => self.print_string(&st, style), + ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style), ast::LitKind::Byte(byte) => { let mut res = String::from("b'"); res.extend(ascii::escape_default(byte).map(|c| c as char)); @@ -664,7 +664,7 @@ pub trait PrintState<'a> { &f, t.ty_to_string())) } - ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f[..]), + ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f.as_str()), ast::LitKind::Bool(val) => { if val { word(self.writer(), "true") } else { word(self.writer(), "false") } } @@ -727,7 +727,7 @@ pub trait PrintState<'a> { trailing_hardbreak: bool) -> io::Result<()> { let mut count = 0; for attr in attrs { - if attr.node.style == kind { + if attr.style == kind { try!(self.print_attribute_inline(attr, is_inline)); if is_inline { try!(self.nbsp()); @@ -751,11 +751,11 @@ pub trait PrintState<'a> { try!(self.hardbreak_if_not_bol()); } try!(self.maybe_print_comment(attr.span.lo)); - if attr.node.is_sugared_doc { - try!(word(self.writer(), &attr.value_str().unwrap())); + if attr.is_sugared_doc { + try!(word(self.writer(), &attr.value_str().unwrap().as_str())); hardbreak(self.writer()) } else { - match attr.node.style { + match attr.style { ast::AttrStyle::Inner => try!(word(self.writer(), "#![")), ast::AttrStyle::Outer => try!(word(self.writer(), "#[")), } @@ -778,16 +778,16 @@ pub trait PrintState<'a> { fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> { try!(self.ibox(INDENT_UNIT)); match item.node { - ast::MetaItemKind::Word(ref name) => { - try!(word(self.writer(), &name)); + ast::MetaItemKind::Word => { + try!(word(self.writer(), &item.name.as_str())); } - ast::MetaItemKind::NameValue(ref name, ref value) => { - try!(self.word_space(&name[..])); + ast::MetaItemKind::NameValue(ref value) => { + try!(self.word_space(&item.name.as_str())); try!(self.word_space("=")); try!(self.print_literal(value)); } - ast::MetaItemKind::List(ref name, ref items) => { - try!(word(self.writer(), &name)); + ast::MetaItemKind::List(ref items) => { + try!(word(self.writer(), &item.name.as_str())); try!(self.popen()); try!(self.commasep(Consistent, &items[..], @@ -2191,13 +2191,17 @@ impl<'a> State<'a> { ast::ExprKind::Path(Some(ref qself), ref path) => { try!(self.print_qpath(path, qself, true)) } - ast::ExprKind::Break(opt_ident) => { + ast::ExprKind::Break(opt_ident, ref opt_expr) => { try!(word(&mut self.s, "break")); try!(space(&mut self.s)); if let Some(ident) = opt_ident { try!(self.print_ident(ident.node)); try!(space(&mut self.s)); } + if let Some(ref expr) = *opt_expr { + try!(self.print_expr(expr)); + try!(space(&mut self.s)); + } } ast::ExprKind::Continue(opt_ident) => { try!(word(&mut self.s, "continue")); @@ -2220,19 +2224,18 @@ impl<'a> State<'a> { ast::ExprKind::InlineAsm(ref a) => { try!(word(&mut self.s, "asm!")); try!(self.popen()); - try!(self.print_string(&a.asm, a.asm_str_style)); + try!(self.print_string(&a.asm.as_str(), a.asm_str_style)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, &a.outputs, - |s, out| { - let mut ch = out.constraint.chars(); + try!(self.commasep(Inconsistent, &a.outputs, |s, out| { + let constraint = out.constraint.as_str(); + let mut ch = constraint.chars(); match ch.next() { Some('=') if out.is_rw => { try!(s.print_string(&format!("+{}", ch.as_str()), ast::StrStyle::Cooked)) } - _ => try!(s.print_string(&out.constraint, - ast::StrStyle::Cooked)) + _ => try!(s.print_string(&constraint, ast::StrStyle::Cooked)) } try!(s.popen()); try!(s.print_expr(&out.expr)); @@ -2242,9 +2245,8 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, &a.inputs, - |s, &(ref co, ref o)| { - try!(s.print_string(&co, ast::StrStyle::Cooked)); + try!(self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { + try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked)); try!(s.popen()); try!(s.print_expr(&o)); try!(s.pclose()); @@ -2255,7 +2257,7 @@ impl<'a> State<'a> { try!(self.commasep(Inconsistent, &a.clobbers, |s, co| { - try!(s.print_string(&co, ast::StrStyle::Cooked)); + try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked)); Ok(()) })); @@ -3082,12 +3084,11 @@ mod tests { use ast; use codemap; - use parse::token; use syntax_pos; #[test] fn test_fun_to_string() { - let abba_ident = token::str_to_ident("abba"); + let abba_ident = ast::Ident::from_str("abba"); let decl = ast::FnDecl { inputs: Vec::new(), @@ -3103,7 +3104,7 @@ mod tests { #[test] fn test_variant_to_string() { - let ident = token::str_to_ident("principal_skinner"); + let ident = ast::Ident::from_str("principal_skinner"); let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ { name: ident, diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 1b63a2b70763..6a291ad9c408 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -10,10 +10,10 @@ use ast; use attr; +use symbol::{Symbol, keywords}; use syntax_pos::{DUMMY_SP, Span}; use codemap::{self, ExpnInfo, NameAndSpan, MacroAttribute}; -use parse::token::{intern, InternedString, keywords}; -use parse::{token, ParseSess}; +use parse::ParseSess; use ptr::P; /// Craft a span that will be ignored by the stability lint's @@ -23,7 +23,7 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span { let info = ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { - format: MacroAttribute(intern("std_inject")), + format: MacroAttribute(Symbol::intern("std_inject")), span: None, allow_internal_unstable: true, } @@ -53,14 +53,14 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, None => return krate, }; - let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string())); + let crate_name = Symbol::intern(&alt_std_name.unwrap_or(name.to_string())); krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(), - attr::mk_word_item(InternedString::new("macro_use")))], + attr::mk_word_item(Symbol::intern("macro_use")))], vis: ast::Visibility::Inherited, node: ast::ItemKind::ExternCrate(Some(crate_name)), - ident: token::str_to_ident(name), + ident: ast::Ident::from_str(name), id: ast::DUMMY_NODE_ID, span: DUMMY_SP, })); @@ -68,22 +68,21 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess, let span = ignored_span(sess, DUMMY_SP); krate.module.items.insert(0, P(ast::Item { attrs: vec![ast::Attribute { - node: ast::Attribute_ { - style: ast::AttrStyle::Outer, - value: P(ast::MetaItem { - node: ast::MetaItemKind::Word(token::intern_and_get_ident("prelude_import")), - span: span, - }), - id: attr::mk_attr_id(), - is_sugared_doc: false, + style: ast::AttrStyle::Outer, + value: ast::MetaItem { + name: Symbol::intern("prelude_import"), + node: ast::MetaItemKind::Word, + span: span, }, + id: attr::mk_attr_id(), + is_sugared_doc: false, span: span, }], vis: ast::Visibility::Inherited, node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path { global: false, segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment { - identifier: token::str_to_ident(name), + identifier: ast::Ident::from_str(name), parameters: ast::PathParameters::none(), }).collect(), span: span, diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs new file mode 100644 index 000000000000..fe9a176179ce --- /dev/null +++ b/src/libsyntax/symbol.rs @@ -0,0 +1,303 @@ +// 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. + +//! An "interner" is a data structure that associates values with usize tags and +//! allows bidirectional lookup; i.e. given a value, one can easily find the +//! type, and vice versa. + +use serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::cell::RefCell; +use std::collections::HashMap; +use std::fmt; + +/// A symbol is an interned or gensymed string. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Symbol(u32); + +// The interner in thread-local, so `Symbol` shouldn't move between threads. +impl !Send for Symbol { } + +impl Symbol { + /// Maps a string to its interned representation. + pub fn intern(string: &str) -> Self { + with_interner(|interner| interner.intern(string)) + } + + /// gensym's a new usize, using the current interner. + pub fn gensym(string: &str) -> Self { + with_interner(|interner| interner.gensym(string)) + } + + pub fn as_str(self) -> InternedString { + with_interner(|interner| unsafe { + InternedString { + string: ::std::mem::transmute::<&str, &str>(interner.get(self)) + } + }) + } + + pub fn as_u32(self) -> u32 { + self.0 + } +} + +impl fmt::Debug for Symbol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}({})", self, self.0) + } +} + +impl fmt::Display for Symbol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.as_str(), f) + } +} + +impl Encodable for Symbol { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_str(&self.as_str()) + } +} + +impl Decodable for Symbol { + fn decode(d: &mut D) -> Result { + Ok(Symbol::intern(&d.read_str()?)) + } +} + +impl<'a> PartialEq<&'a str> for Symbol { + fn eq(&self, other: &&str) -> bool { + *self.as_str() == **other + } +} + +#[derive(Default)] +pub struct Interner { + names: HashMap, Symbol>, + strings: Vec>, +} + +impl Interner { + pub fn new() -> Self { + Interner::default() + } + + fn prefill(init: &[&str]) -> Self { + let mut this = Interner::new(); + for &string in init { + this.intern(string); + } + this + } + + pub fn intern(&mut self, string: &str) -> Symbol { + if let Some(&name) = self.names.get(string) { + return name; + } + + let name = Symbol(self.strings.len() as u32); + let string = string.to_string().into_boxed_str(); + self.strings.push(string.clone()); + self.names.insert(string, name); + name + } + + fn gensym(&mut self, string: &str) -> Symbol { + let gensym = Symbol(self.strings.len() as u32); + // leave out of `names` to avoid colliding + self.strings.push(string.to_string().into_boxed_str()); + gensym + } + + pub fn get(&self, name: Symbol) -> &str { + &self.strings[name.0 as usize] + } +} + +// In this macro, there is the requirement that the name (the number) must be monotonically +// increasing by one in the special identifiers, starting at 0; the same holds for the keywords, +// except starting from the next number instead of zero. +macro_rules! declare_keywords {( + $( ($index: expr, $konst: ident, $string: expr) )* +) => { + pub mod keywords { + use ast; + #[derive(Clone, Copy, PartialEq, Eq)] + pub struct Keyword { + ident: ast::Ident, + } + impl Keyword { + #[inline] pub fn ident(self) -> ast::Ident { self.ident } + #[inline] pub fn name(self) -> ast::Name { self.ident.name } + } + $( + #[allow(non_upper_case_globals)] + pub const $konst: Keyword = Keyword { + ident: ast::Ident::with_empty_ctxt(ast::Name($index)) + }; + )* + } + + impl Interner { + fn fresh() -> Self { + Interner::prefill(&[$($string,)*]) + } + } +}} + +// NB: leaving holes in the ident table is bad! a different ident will get +// interned with the id from the hole, but it will be between the min and max +// of the reserved words, and thus tagged as "reserved". +// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`, +// this should be rarely necessary though if the keywords are kept in alphabetic order. +declare_keywords! { + // Invalid identifier + (0, Invalid, "") + + // Strict keywords used in the language. + (1, As, "as") + (2, Box, "box") + (3, Break, "break") + (4, Const, "const") + (5, Continue, "continue") + (6, Crate, "crate") + (7, Else, "else") + (8, Enum, "enum") + (9, Extern, "extern") + (10, False, "false") + (11, Fn, "fn") + (12, For, "for") + (13, If, "if") + (14, Impl, "impl") + (15, In, "in") + (16, Let, "let") + (17, Loop, "loop") + (18, Match, "match") + (19, Mod, "mod") + (20, Move, "move") + (21, Mut, "mut") + (22, Pub, "pub") + (23, Ref, "ref") + (24, Return, "return") + (25, SelfValue, "self") + (26, SelfType, "Self") + (27, Static, "static") + (28, Struct, "struct") + (29, Super, "super") + (30, Trait, "trait") + (31, True, "true") + (32, Type, "type") + (33, Unsafe, "unsafe") + (34, Use, "use") + (35, Where, "where") + (36, While, "while") + + // Keywords reserved for future use. + (37, Abstract, "abstract") + (38, Alignof, "alignof") + (39, Become, "become") + (40, Do, "do") + (41, Final, "final") + (42, Macro, "macro") + (43, Offsetof, "offsetof") + (44, Override, "override") + (45, Priv, "priv") + (46, Proc, "proc") + (47, Pure, "pure") + (48, Sizeof, "sizeof") + (49, Typeof, "typeof") + (50, Unsized, "unsized") + (51, Virtual, "virtual") + (52, Yield, "yield") + + // Weak keywords, have special meaning only in specific contexts. + (53, Default, "default") + (54, StaticLifetime, "'static") + (55, Union, "union") +} + +// If an interner exists in TLS, return it. Otherwise, prepare a fresh one. +fn with_interner T>(f: F) -> T { + thread_local!(static INTERNER: RefCell = { + RefCell::new(Interner::fresh()) + }); + INTERNER.with(|interner| f(&mut *interner.borrow_mut())) +} + +/// Represents a string stored in the thread-local interner. Because the +/// interner lives for the life of the thread, this can be safely treated as an +/// immortal string, as long as it never crosses between threads. +/// +/// FIXME(pcwalton): You must be careful about what you do in the destructors +/// of objects stored in TLS, because they may run after the interner is +/// destroyed. In particular, they must not access string contents. This can +/// be fixed in the future by just leaking all strings until thread death +/// somehow. +#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)] +pub struct InternedString { + string: &'static str, +} + +impl !Send for InternedString { } + +impl ::std::ops::Deref for InternedString { + type Target = str; + fn deref(&self) -> &str { self.string } +} + +impl fmt::Debug for InternedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.string, f) + } +} + +impl fmt::Display for InternedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.string, f) + } +} + +impl Decodable for InternedString { + fn decode(d: &mut D) -> Result { + Ok(Symbol::intern(&d.read_str()?).as_str()) + } +} + +impl Encodable for InternedString { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_str(self.string) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ast::Name; + + #[test] + fn interner_tests() { + let mut i: Interner = Interner::new(); + // first one is zero: + assert_eq!(i.intern("dog"), Name(0)); + // re-use gets the same entry: + assert_eq!(i.intern ("dog"), Name(0)); + // different string gets a different #: + assert_eq!(i.intern("cat"), Name(1)); + assert_eq!(i.intern("cat"), Name(1)); + // dog is still at zero + assert_eq!(i.intern("dog"), Name(0)); + // gensym gets 3 + assert_eq!(i.gensym("zebra"), Name(2)); + // gensym of same string gets new number : + assert_eq!(i.gensym("zebra"), Name(3)); + // gensym of *existing* string gets new number: + assert_eq!(i.gensym("dog"), Name(4)); + } +} diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 59a7e75d1255..4de3baf7d14f 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -34,21 +34,21 @@ use ext::expand::ExpansionConfig; use fold::Folder; use util::move_map::MoveMap; use fold; -use parse::token::{intern, keywords, InternedString}; use parse::{token, ParseSess}; use print::pprust; -use ast; +use ast::{self, Ident}; use ptr::P; +use symbol::{self, Symbol, keywords}; use util::small_vector::SmallVector; enum ShouldPanic { No, - Yes(Option), + Yes(Option), } struct Test { span: Span, - path: Vec , + path: Vec , bench: bool, ignore: bool, should_panic: ShouldPanic @@ -57,14 +57,14 @@ struct Test { struct TestCtxt<'a> { sess: &'a ParseSess, span_diagnostic: &'a errors::Handler, - path: Vec, + path: Vec, ext_cx: ExtCtxt<'a>, testfns: Vec, - reexport_test_harness_main: Option, + reexport_test_harness_main: Option, is_test_crate: bool, // top-level re-export submodule, filled out after folding is finished - toplevel_reexport: Option, + toplevel_reexport: Option, } // Traverse the crate, collecting all the test functions, eliding any @@ -91,10 +91,10 @@ pub fn modify_for_testing(sess: &ParseSess, struct TestHarnessGenerator<'a> { cx: TestCtxt<'a>, - tests: Vec, + tests: Vec, // submodule name, gensym'd identifier for re-exports - tested_submods: Vec<(ast::Ident, ast::Ident)>, + tested_submods: Vec<(Ident, Ident)>, } impl<'a> fold::Folder for TestHarnessGenerator<'a> { @@ -191,8 +191,8 @@ impl fold::Folder for EntryPointCleaner { EntryPointType::MainAttr | EntryPointType::Start => folded.map(|ast::Item {id, ident, attrs, node, vis, span}| { - let allow_str = InternedString::new("allow"); - let dead_code_str = InternedString::new("dead_code"); + let allow_str = Symbol::intern("allow"); + let dead_code_str = Symbol::intern("dead_code"); let word_vec = vec![attr::mk_list_word_item(dead_code_str)]; let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec); let allow_dead_code = attr::mk_attr_outer(attr::mk_attr_id(), @@ -222,15 +222,18 @@ impl fold::Folder for EntryPointCleaner { fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac } } -fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec, - tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P, ast::Ident) { - let super_ = token::str_to_ident("super"); +fn mk_reexport_mod(cx: &mut TestCtxt, + parent: ast::NodeId, + tests: Vec, + tested_submods: Vec<(Ident, Ident)>) + -> (P, Ident) { + let super_ = Ident::from_str("super"); // Generate imports with `#[allow(private_in_public)]` to work around issue #36768. let allow_private_in_public = cx.ext_cx.attribute(DUMMY_SP, cx.ext_cx.meta_list( DUMMY_SP, - InternedString::new("allow"), - vec![cx.ext_cx.meta_list_item_word(DUMMY_SP, InternedString::new("private_in_public"))], + Symbol::intern("allow"), + vec![cx.ext_cx.meta_list_item_word(DUMMY_SP, Symbol::intern("private_in_public"))], )); let items = tests.into_iter().map(|r| { cx.ext_cx.item_use_simple(DUMMY_SP, ast::Visibility::Public, @@ -247,7 +250,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec, + reexport_test_harness_main: Option, krate: ast::Crate, sd: &errors::Handler) -> ast::Crate { // Remove the entry points @@ -286,7 +289,7 @@ fn generate_test_harness(sess: &ParseSess, cx.ext_cx.bt_push(ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { - format: MacroAttribute(intern("test")), + format: MacroAttribute(Symbol::intern("test")), span: None, allow_internal_unstable: false, } @@ -306,7 +309,7 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span { let info = ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { - format: MacroAttribute(intern("test")), + format: MacroAttribute(Symbol::intern("test")), span: None, allow_internal_unstable: true, } @@ -456,7 +459,7 @@ mod __test { */ fn mk_std(cx: &TestCtxt) -> P { - let id_test = token::str_to_ident("test"); + let id_test = Ident::from_str("test"); let (vi, vis, ident) = if cx.is_test_crate { (ast::ItemKind::Use( P(nospan(ast::ViewPathSimple(id_test, @@ -487,16 +490,17 @@ fn mk_main(cx: &mut TestCtxt) -> P { let ecx = &cx.ext_cx; // test::test_main_static - let test_main_path = ecx.path(sp, vec![token::str_to_ident("test"), - token::str_to_ident("test_main_static")]); + let test_main_path = + ecx.path(sp, vec![Ident::from_str("test"), Ident::from_str("test_main_static")]); + // test::test_main_static(...) let test_main_path_expr = ecx.expr_path(test_main_path); - let tests_ident_expr = ecx.expr_ident(sp, token::str_to_ident("TESTS")); + let tests_ident_expr = ecx.expr_ident(sp, Ident::from_str("TESTS")); let call_test_main = ecx.expr_call(sp, test_main_path_expr, vec![tests_ident_expr]); let call_test_main = ecx.stmt_expr(call_test_main); // #![main] - let main_meta = ecx.meta_word(sp, token::intern_and_get_ident("main")); + let main_meta = ecx.meta_word(sp, Symbol::intern("main")); let main_attr = ecx.attribute(sp, main_meta); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); @@ -506,7 +510,7 @@ fn mk_main(cx: &mut TestCtxt) -> P { dummy_spanned(ast::Constness::NotConst), ::abi::Abi::Rust, ast::Generics::default(), main_body); let main = P(ast::Item { - ident: token::str_to_ident("main"), + ident: Ident::from_str("main"), attrs: vec![main_attr], id: ast::DUMMY_NODE_ID, node: main, @@ -533,7 +537,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P, Option>) { items: vec![import, mainfn, tests], }; let item_ = ast::ItemKind::Mod(testmod); - let mod_ident = token::gensym_ident("__test"); + let mod_ident = Ident::with_empty_ctxt(Symbol::gensym("__test")); let mut expander = cx.ext_cx.monotonic_expander(); let item = expander.fold_item(P(ast::Item { @@ -544,13 +548,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P, Option>) { vis: ast::Visibility::Public, span: DUMMY_SP, })).pop().unwrap(); - let reexport = cx.reexport_test_harness_main.as_ref().map(|s| { + let reexport = cx.reexport_test_harness_main.map(|s| { // building `use = __test::main` - let reexport_ident = token::str_to_ident(&s); + let reexport_ident = Ident::with_empty_ctxt(s); let use_path = nospan(ast::ViewPathSimple(reexport_ident, - path_node(vec![mod_ident, token::str_to_ident("main")]))); + path_node(vec![mod_ident, Ident::from_str("main")]))); expander.fold_item(P(ast::Item { id: ast::DUMMY_NODE_ID, @@ -571,7 +575,7 @@ fn nospan(t: T) -> codemap::Spanned { codemap::Spanned { node: t, span: DUMMY_SP } } -fn path_node(ids: Vec ) -> ast::Path { +fn path_node(ids: Vec) -> ast::Path { ast::Path { span: DUMMY_SP, global: false, @@ -582,7 +586,7 @@ fn path_node(ids: Vec ) -> ast::Path { } } -fn path_name_i(idents: &[ast::Ident]) -> String { +fn path_name_i(idents: &[Ident]) -> String { // FIXME: Bad copies (#2543 -- same for everything else that says "bad") idents.iter().map(|i| i.to_string()).collect::>().join("::") } @@ -614,7 +618,7 @@ fn mk_tests(cx: &TestCtxt) -> P { fn is_test_crate(krate: &ast::Crate) -> bool { match attr::find_crate_name(&krate.attrs) { - Some(ref s) if "test" == &s[..] => true, + Some(s) if "test" == &*s.as_str() => true, _ => false } } @@ -660,7 +664,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // path to the #[test] function: "foo::bar::baz" let path_string = path_name_i(&path[..]); - let name_expr = ecx.expr_str(span, token::intern_and_get_ident(&path_string[..])); + let name_expr = ecx.expr_str(span, Symbol::intern(&path_string)); // self::test::StaticTestName($name_expr) let name_expr = ecx.expr_call(span, @@ -673,10 +677,10 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { }; let fail_expr = match test.should_panic { ShouldPanic::No => ecx.expr_path(should_panic_path("No")), - ShouldPanic::Yes(ref msg) => { - match *msg { - Some(ref msg) => { - let msg = ecx.expr_str(span, msg.clone()); + ShouldPanic::Yes(msg) => { + match msg { + Some(msg) => { + let msg = ecx.expr_str(span, msg); let path = should_panic_path("YesWithMessage"); ecx.expr_call(span, ecx.expr_path(path), vec![msg]) } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 9ef6c07e489d..0d5dcaf339fe 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -34,6 +34,7 @@ use parse::lexer; use parse; use parse::token::{self, Token, Lit, Nonterminal}; use print::pprust; +use symbol::Symbol; use std::fmt; use std::iter::*; @@ -173,10 +174,10 @@ impl TokenTree { TokenTree::Delimited(sp, Rc::new(Delimited { delim: token::Bracket, open_span: sp, - tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"))), + tts: vec![TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"))), TokenTree::Token(sp, token::Eq), TokenTree::Token(sp, token::Literal( - token::StrRaw(token::intern(&stripped), num_of_hashes), None))], + token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))], close_span: sp, })) } @@ -295,7 +296,7 @@ impl TokenTree { pub fn maybe_str(&self) -> Option { match *self { TokenTree::Token(sp, Token::Literal(Lit::Str_(s), _)) => { - let l = LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())), + let l = LitKind::Str(Symbol::intern(&parse::str_lit(&s.as_str())), ast::StrStyle::Cooked); Some(Spanned { node: l, @@ -303,7 +304,7 @@ impl TokenTree { }) } TokenTree::Token(sp, Token::Literal(Lit::StrRaw(s, n), _)) => { - let l = LitKind::Str(token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())), + let l = LitKind::Str(Symbol::intern(&parse::raw_str_lit(&s.as_str())), ast::StrStyle::Raw(n)); Some(Spanned { node: l, @@ -871,8 +872,9 @@ impl Index for InternalTS { #[cfg(test)] mod tests { use super::*; + use syntax::ast::Ident; use syntax_pos::{Span, BytePos, NO_EXPANSION, DUMMY_SP}; - use parse::token::{self, str_to_ident, Token}; + use parse::token::{self, Token}; use util::parser_testing::string_to_tts; use std::rc::Rc; @@ -967,15 +969,17 @@ mod tests { let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string())) .slice(2..3); let test_eqs = TokenStream::from_tts(vec![TokenTree::Token(sp(5,8), - token::Ident(str_to_ident("bar")))]); + token::Ident(Ident::from_str("bar")))]); assert_eq!(test_res, test_eqs) } #[test] fn test_is_empty() { let test0 = TokenStream::from_tts(Vec::new()); - let test1 = TokenStream::from_tts(vec![TokenTree::Token(sp(0, 1), - Token::Ident(str_to_ident("a")))]); + let test1 = TokenStream::from_tts( + vec![TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a")))] + ); + let test2 = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string())); assert_eq!(test0.is_empty(), true); @@ -1035,20 +1039,20 @@ mod tests { assert_eq!(test0, None); let test1_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4), - token::Ident(str_to_ident("bar"))), + token::Ident(Ident::from_str("bar"))), TokenTree::Token(sp(4, 6), token::ModSep), TokenTree::Token(sp(6, 9), - token::Ident(str_to_ident("baz")))]); + token::Ident(Ident::from_str("baz")))]); assert_eq!(test1, Some(test1_expected)); let test2_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4), - token::Ident(str_to_ident("foo"))), + token::Ident(Ident::from_str("foo"))), TokenTree::Token(sp(4, 5), token::Comma), TokenTree::Token(sp(5, 8), - token::Ident(str_to_ident("bar"))), + token::Ident(Ident::from_str("bar"))), TokenTree::Token(sp(8, 9), token::Comma), TokenTree::Token(sp(9, 12), - token::Ident(str_to_ident("baz")))]); + token::Ident(Ident::from_str("baz")))]); assert_eq!(test2, Some(test2_expected)); assert_eq!(test3, None); @@ -1069,7 +1073,7 @@ mod tests { assert_eq!(test0, None); assert_eq!(test1, None); - assert_eq!(test2, Some(str_to_ident("foo"))); + assert_eq!(test2, Some(Ident::from_str("foo"))); assert_eq!(test3, None); assert_eq!(test4, None); } @@ -1079,9 +1083,9 @@ mod tests { let test0 = as_paren_delimited_stream(string_to_tts("foo,bar,".to_string())); let test1 = as_paren_delimited_stream(string_to_tts("baz(foo,bar)".to_string())); - let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("foo"))), + let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(Ident::from_str("foo"))), TokenTree::Token(sp(3, 4), token::Comma), - TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("bar"))), + TokenTree::Token(sp(4, 7), token::Ident(Ident::from_str("bar"))), TokenTree::Token(sp(7, 8), token::Comma)]; let test0_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(0, 8), Rc::new(Delimited { @@ -1094,11 +1098,11 @@ mod tests { assert_eq!(test0, test0_stream); - let test1_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("foo"))), + let test1_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(Ident::from_str("foo"))), TokenTree::Token(sp(7, 8), token::Comma), - TokenTree::Token(sp(8, 11), token::Ident(str_to_ident("bar")))]; + TokenTree::Token(sp(8, 11), token::Ident(Ident::from_str("bar")))]; - let test1_parse = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("baz"))), + let test1_parse = vec![TokenTree::Token(sp(0, 3), token::Ident(Ident::from_str("baz"))), TokenTree::Delimited(sp(3, 12), Rc::new(Delimited { delim: token::DelimToken::Paren, diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs deleted file mode 100644 index f56c6cedcd18..000000000000 --- a/src/libsyntax/util/interner.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2012 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. - -//! An "interner" is a data structure that associates values with usize tags and -//! allows bidirectional lookup; i.e. given a value, one can easily find the -//! type, and vice versa. - -use ast::Name; - -use std::collections::HashMap; -use std::rc::Rc; - -#[derive(Default)] -pub struct Interner { - names: HashMap, Name>, - strings: Vec>, -} - -/// When traits can extend traits, we should extend index to get [] -impl Interner { - pub fn new() -> Self { - Interner::default() - } - - pub fn prefill(init: &[&str]) -> Self { - let mut this = Interner::new(); - for &string in init { - this.intern(string); - } - this - } - - pub fn intern(&mut self, string: &str) -> Name { - if let Some(&name) = self.names.get(string) { - return name; - } - - let name = Name(self.strings.len() as u32); - let string = Rc::__from_str(string); - self.strings.push(string.clone()); - self.names.insert(string, name); - name - } - - pub fn gensym(&mut self, string: &str) -> Name { - let gensym = Name(self.strings.len() as u32); - // leave out of `names` to avoid colliding - self.strings.push(Rc::__from_str(string)); - gensym - } - - /// Create a gensym with the same name as an existing entry. - pub fn gensym_copy(&mut self, name: Name) -> Name { - let gensym = Name(self.strings.len() as u32); - // leave out of `names` to avoid colliding - let string = self.strings[name.0 as usize].clone(); - self.strings.push(string); - gensym - } - - pub fn get(&self, name: Name) -> Rc { - self.strings[name.0 as usize].clone() - } - - pub fn find(&self, string: &str) -> Option { - self.names.get(string).cloned() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use ast::Name; - - #[test] - fn interner_tests() { - let mut i: Interner = Interner::new(); - // first one is zero: - assert_eq!(i.intern("dog"), Name(0)); - // re-use gets the same entry: - assert_eq!(i.intern ("dog"), Name(0)); - // different string gets a different #: - assert_eq!(i.intern("cat"), Name(1)); - assert_eq!(i.intern("cat"), Name(1)); - // dog is still at zero - assert_eq!(i.intern("dog"), Name(0)); - // gensym gets 3 - assert_eq!(i.gensym("zebra"), Name(2)); - // gensym of same string gets new number : - assert_eq!(i.gensym("zebra"), Name(3)); - // gensym of *existing* string gets new number: - assert_eq!(i.gensym("dog"), Name(4)); - // gensym tests again with gensym_copy: - assert_eq!(i.gensym_copy(Name(2)), Name(5)); - assert_eq!(&*i.get(Name(5)), "zebra"); - assert_eq!(i.gensym_copy(Name(2)), Name(6)); - assert_eq!(&*i.get(Name(6)), "zebra"); - assert_eq!(&*i.get(Name(0)), "dog"); - assert_eq!(&*i.get(Name(1)), "cat"); - assert_eq!(&*i.get(Name(2)), "zebra"); - assert_eq!(&*i.get(Name(3)), "zebra"); - assert_eq!(&*i.get(Name(4)), "dog"); - } -} diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index e0796c34e57e..a6fff2d70746 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast::Name; use std::cmp; -use parse::token::InternedString; +use symbol::Symbol; /// To find the Levenshtein distance between two strings pub fn lev_distance(a: &str, b: &str) -> usize { @@ -48,14 +47,14 @@ pub fn lev_distance(a: &str, b: &str) -> usize { /// to one-third of the given word pub fn find_best_match_for_name<'a, T>(iter_names: T, lookup: &str, - dist: Option) -> Option - where T: Iterator { + dist: Option) -> Option + where T: Iterator { let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d); iter_names - .filter_map(|name| { + .filter_map(|&name| { let dist = lev_distance(lookup, &name.as_str()); match dist <= max_dist { // filter the unwanted cases - true => Some((name.as_str(), dist)), + true => Some((name, dist)), false => None, } }) diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index df4eb1c9ed7d..ce24fe1eb61e 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -7,7 +7,8 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use parse::token::{Token, BinOpToken, keywords}; +use parse::token::{Token, BinOpToken}; +use symbol::keywords; use ast::BinOpKind; /// Associative operator with precedence. diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index 76d3f2a063c1..e703dc6b4191 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ast; +use ast::{self, Ident}; use parse::{ParseSess,PResult,filemap_to_tts}; use parse::{lexer, new_parser_from_source_str}; use parse::parser::Parser; -use parse::token; use ptr::P; use tokenstream; use std::iter::Peekable; @@ -78,9 +77,9 @@ pub fn string_to_pat(source_str: String) -> P { }) } -/// Convert a vector of strings to a vector of ast::Ident's -pub fn strs_to_idents(ids: Vec<&str> ) -> Vec { - ids.iter().map(|u| token::str_to_ident(*u)).collect() +/// Convert a vector of strings to a vector of Ident's +pub fn strs_to_idents(ids: Vec<&str> ) -> Vec { + ids.iter().map(|u| Ident::from_str(*u)).collect() } /// Does the given string match the pattern? whitespace in the first string diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7c1ff617ab64..da36225fb329 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -746,7 +746,11 @@ pub fn walk_expr(visitor: &mut V, expression: &Expr) { } visitor.visit_path(path, expression.id) } - ExprKind::Break(ref opt_sp_ident) | ExprKind::Continue(ref opt_sp_ident) => { + ExprKind::Break(ref opt_sp_ident, ref opt_expr) => { + walk_opt_sp_ident(visitor, opt_sp_ident); + walk_list!(visitor, visit_expr, opt_expr); + } + ExprKind::Continue(ref opt_sp_ident) => { walk_opt_sp_ident(visitor, opt_sp_ident); } ExprKind::Ret(ref optional_expression) => { diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index e4d0cb740460..a5e083f926a0 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -17,9 +17,9 @@ use syntax::codemap; use syntax::ext::base; use syntax::ext::base::*; use syntax::feature_gate; -use syntax::parse::token::intern; use syntax::parse::{self, token}; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax::ast::AsmDialect; use syntax_pos::Span; use syntax::tokenstream; @@ -73,7 +73,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, }) .unwrap_or(tts.len()); let mut p = cx.new_parser_from_tts(&tts[first_colon..]); - let mut asm = token::InternedString::new(""); + let mut asm = Symbol::intern(""); let mut asm_str_style = None; let mut outputs = Vec::new(); let mut inputs = Vec::new(); @@ -135,11 +135,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, // It's the opposite of '=&' which means that the memory // cannot be shared with any other operand (usually when // a register is clobbered early.) - let mut ch = constraint.chars(); + let constraint_str = constraint.as_str(); + let mut ch = constraint_str.chars(); let output = match ch.next() { Some('=') => None, Some('+') => { - Some(token::intern_and_get_ident(&format!("={}", ch.as_str()))) + Some(Symbol::intern(&format!("={}", ch.as_str()))) } _ => { cx.span_err(span, "output operand constraint lacks '=' or '+'"); @@ -148,9 +149,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, }; let is_rw = output.is_some(); - let is_indirect = constraint.contains("*"); + let is_indirect = constraint_str.contains("*"); outputs.push(ast::InlineAsmOutput { - constraint: output.unwrap_or(constraint.clone()), + constraint: output.unwrap_or(constraint), expr: out, is_rw: is_rw, is_indirect: is_indirect, @@ -166,9 +167,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, let (constraint, _str_style) = panictry!(p.parse_str()); - if constraint.starts_with("=") { + if constraint.as_str().starts_with("=") { cx.span_err(p.prev_span, "input operand constraint contains '='"); - } else if constraint.starts_with("+") { + } else if constraint.as_str().starts_with("+") { cx.span_err(p.prev_span, "input operand constraint contains '+'"); } @@ -190,7 +191,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.prev_span, "expected a clobber, found an option"); - } else if s.starts_with("{") || s.ends_with("}") { + } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") { cx.span_err(p.prev_span, "clobber should not be surrounded by braces"); } @@ -242,7 +243,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, let expn_id = cx.codemap().record_expansion(codemap::ExpnInfo { call_site: sp, callee: codemap::NameAndSpan { - format: codemap::MacroBang(intern("asm")), + format: codemap::MacroBang(Symbol::intern("asm")), span: None, allow_internal_unstable: false, }, @@ -251,7 +252,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { - asm: token::intern_and_get_ident(&asm), + asm: asm, asm_str_style: asm_str_style.unwrap(), outputs: outputs, inputs: inputs, diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 02b44f2d012e..bfe18dc4060c 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -11,7 +11,7 @@ use syntax::ast; use syntax::ext::base; use syntax::ext::build::AstBuilder; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax_pos; use syntax::tokenstream; @@ -33,7 +33,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) | ast::LitKind::FloatUnsuffixed(ref s) => { - accumulator.push_str(&s); + accumulator.push_str(&s.as_str()); } ast::LitKind::Char(c) => { accumulator.push(c); @@ -57,5 +57,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } } } - base::MacEager::expr(cx.expr_str(sp, token::intern_and_get_ident(&accumulator[..]))) + base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) } diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index e56c6e2229a7..b26e33eb384d 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -13,7 +13,6 @@ use syntax::ext::base::*; use syntax::ext::base; use syntax::feature_gate; use syntax::parse::token; -use syntax::parse::token::str_to_ident; use syntax::ptr::P; use syntax_pos::Span; use syntax::tokenstream::TokenTree; @@ -51,7 +50,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, } } } - let res = str_to_ident(&res_str); + let res = ast::Ident::from_str(&res_str); struct Result { ident: ast::Ident, diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index d7bc2a6faeeb..d14b59d6c70e 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -15,8 +15,8 @@ use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::{keywords, InternedString}; use syntax::ptr::P; +use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; pub fn expand_deriving_clone(cx: &mut ExtCtxt, @@ -74,7 +74,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"), } - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { span: span, diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index fa0fb2492c55..6ab5987a159c 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -14,8 +14,8 @@ use deriving::generic::ty::*; use syntax::ast::{self, Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_eq(cx: &mut ExtCtxt, @@ -23,9 +23,9 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { - let inline = cx.meta_word(span, InternedString::new("inline")); - let hidden = cx.meta_list_item_word(span, InternedString::new("hidden")); - let doc = cx.meta_list(span, InternedString::new("doc"), vec![hidden]); + let inline = cx.meta_word(span, Symbol::intern("inline")); + let hidden = cx.meta_list_item_word(span, Symbol::intern("hidden")); + let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]); let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)]; let trait_def = TraitDef { span: span, diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 6b2e36e63b65..9fc3d997585d 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -14,8 +14,8 @@ use deriving::generic::ty::*; use syntax::ast::{self, Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_ord(cx: &mut ExtCtxt, @@ -23,7 +23,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { span: span, diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index c46d4b34173f..f2a050ce971e 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -14,8 +14,8 @@ use deriving::generic::ty::*; use syntax::ast::{BinOpKind, Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, @@ -64,7 +64,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, macro_rules! md { ($name:expr, $f:ident) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; MethodDef { name: $name, diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 597ff306b3dd..ce4d549d696f 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -16,8 +16,8 @@ use deriving::generic::ty::*; use syntax::ast::{self, BinOpKind, Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, @@ -27,7 +27,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, push: &mut FnMut(Annotatable)) { macro_rules! md { ($name:expr, $op:expr, $equal:expr) => { { - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; MethodDef { name: $name, @@ -51,7 +51,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, vec![Box::new(ordering_ty)], true)); - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let partial_cmp_def = MethodDef { diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index e101757ad232..1076a6a6d63a 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -17,10 +17,9 @@ use syntax::attr::{mark_used, mark_known}; use syntax::codemap::Span; use syntax::ext::base::*; use syntax::fold::Folder; -use syntax::parse::token::InternedString; use syntax::visit::Visitor; -struct MarkAttrs<'a>(&'a [InternedString]); +struct MarkAttrs<'a>(&'a [ast::Name]); impl<'a> Visitor for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { @@ -33,13 +32,11 @@ impl<'a> Visitor for MarkAttrs<'a> { pub struct CustomDerive { inner: fn(TokenStream) -> TokenStream, - attrs: Vec, + attrs: Vec, } impl CustomDerive { - pub fn new(inner: fn(TokenStream) -> TokenStream, - attrs: Vec) - -> CustomDerive { + pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec) -> CustomDerive { CustomDerive { inner: inner, attrs: attrs } } } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index f367fed9cc2c..a767716466cb 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -11,11 +11,10 @@ use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast; +use syntax::ast::{self, Ident}; use syntax::ast::{Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token; use syntax::ptr::P; use syntax_pos::{DUMMY_SP, Span}; @@ -69,9 +68,8 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P P P P P P unreachable!(), }; - let expr = cx.expr_method_call(span, builder_expr, token::str_to_ident("finish"), vec![]); + let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]); stmts.push(cx.stmt_expr(expr)); let block = cx.block(span, stmts); diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index dc1f7b4e6201..e2634c60dcaa 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -18,9 +18,8 @@ use syntax::ast; use syntax::ast::{Expr, MetaItem, Mutability}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; -use syntax::parse::token; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt, @@ -131,7 +130,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, cx.expr_method_call(trait_span, decoder, cx.ident_of("read_struct"), - vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()), + vec![cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, nfields), cx.lambda1(trait_span, result, blkarg)]) } @@ -143,7 +142,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, let rvariant_arg = cx.ident_of("read_enum_variant_arg"); for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() { - variants.push(cx.expr_str(v_span, ident.name.as_str())); + variants.push(cx.expr_str(v_span, ident.name)); let path = cx.path(trait_span, vec![substr.type_ident, ident]); let decoded = decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| { @@ -175,7 +174,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, cx.expr_method_call(trait_span, decoder, cx.ident_of("read_enum"), - vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()), + vec![cx.expr_str(trait_span, substr.type_ident.name), cx.lambda1(trait_span, result, blkarg)]) } _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"), @@ -191,7 +190,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, fields: &StaticFields, mut getarg: F) -> P - where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P + where F: FnMut(&mut ExtCtxt, Span, Symbol, usize) -> P { match *fields { Unnamed(ref fields, is_tuple) => { @@ -202,10 +201,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, let fields = fields.iter() .enumerate() .map(|(i, &span)| { - getarg(cx, - span, - token::intern_and_get_ident(&format!("_field{}", i)), - i) + getarg(cx, span, Symbol::intern(&format!("_field{}", i)), i) }) .collect(); @@ -217,7 +213,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, let fields = fields.iter() .enumerate() .map(|(i, &(ident, span))| { - let arg = getarg(cx, span, ident.name.as_str(), i); + let arg = getarg(cx, span, ident.name, i); cx.field_imm(span, ident, arg) }) .collect(); diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index b15fd2b49a65..69391f48c228 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -14,8 +14,8 @@ use deriving::generic::ty::*; use syntax::ast::{Expr, MetaItem}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token::InternedString; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_default(cx: &mut ExtCtxt, @@ -23,7 +23,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, mitem: &MetaItem, item: &Annotatable, push: &mut FnMut(Annotatable)) { - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { span: span, diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index ebbddc6e4808..092738ab8a03 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -95,8 +95,8 @@ use deriving::generic::ty::*; use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; -use syntax::parse::token; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt, @@ -192,8 +192,8 @@ fn encodable_substructure(cx: &mut ExtCtxt, let mut stmts = Vec::new(); for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { let name = match name { - Some(id) => id.name.as_str(), - None => token::intern_and_get_ident(&format!("_field{}", i)), + Some(id) => id.name, + None => Symbol::intern(&format!("_field{}", i)), }; let self_ref = cx.expr_addr_of(span, self_.clone()); let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]); @@ -226,7 +226,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, cx.expr_method_call(trait_span, encoder, cx.ident_of("emit_struct"), - vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()), + vec![cx.expr_str(trait_span, substr.type_ident.name), cx.expr_usize(trait_span, fields.len()), blk]) } @@ -265,7 +265,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, } let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); - let name = cx.expr_str(trait_span, variant.node.name.name.as_str()); + let name = cx.expr_str(trait_span, variant.node.name.name); let call = cx.expr_method_call(trait_span, blkencoder, cx.ident_of("emit_enum_variant"), @@ -277,8 +277,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, let ret = cx.expr_method_call(trait_span, encoder, cx.ident_of("emit_enum"), - vec![cx.expr_str(trait_span, - substr.type_ident.name.as_str()), + vec![cx.expr_str(trait_span ,substr.type_ident.name), blk]); cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index e6b63be3efc0..63cd7678321e 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -198,8 +198,8 @@ use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::codemap::{self, dummy_spanned, respan}; use syntax::util::move_map::MoveMap; -use syntax::parse::token::{InternedString, keywords}; use syntax::ptr::P; +use syntax::symbol::{Symbol, keywords}; use syntax_pos::{DUMMY_SP, Span}; use errors::Handler; @@ -442,7 +442,7 @@ impl<'a> TraitDef<'a> { attrs.extend(item.attrs .iter() .filter(|a| { - match &a.name()[..] { + match &*a.name().as_str() { "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true, _ => false, } @@ -639,15 +639,15 @@ impl<'a> TraitDef<'a> { let attr = cx.attribute(self.span, cx.meta_word(self.span, - InternedString::new("automatically_derived"))); + Symbol::intern("automatically_derived"))); // Just mark it now since we know that it'll end up used downstream attr::mark_used(&attr); let opt_trait_ref = Some(trait_ref); - let unused_qual = cx.attribute(self.span, - cx.meta_list(self.span, - InternedString::new("allow"), - vec![cx.meta_list_item_word(self.span, - InternedString::new("unused_qualifications"))])); + let unused_qual = { + let word = cx.meta_list_item_word(self.span, Symbol::intern("unused_qualifications")); + cx.attribute(self.span, cx.meta_list(self.span, Symbol::intern("allow"), vec![word])) + }; + let mut a = vec![attr, unused_qual]; a.extend(self.attributes.iter().cloned()); diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index b1d473820f77..535d7de19e34 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -16,8 +16,8 @@ use syntax::codemap; use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension}; use syntax::ext::build::AstBuilder; use syntax::feature_gate::{self, emit_feature_err}; -use syntax::parse::token::{intern, intern_and_get_ident}; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; macro_rules! pathvec { @@ -80,7 +80,7 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span { expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { call_site: span, callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(intern(attr_name)), + format: codemap::MacroAttribute(Symbol::intern(attr_name)), span: Some(span), allow_internal_unstable: true, }, @@ -105,9 +105,10 @@ pub fn expand_derive(cx: &mut ExtCtxt, } }; + let derive = Symbol::intern("derive"); let mut derive_attrs = Vec::new(); item = item.map_attrs(|attrs| { - let partition = attrs.into_iter().partition(|attr| &attr.name() == "derive"); + let partition = attrs.into_iter().partition(|attr| attr.name() == derive); derive_attrs = partition.0; partition.1 }); @@ -115,7 +116,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, // Expand `#[derive]`s after other attribute macro invocations. if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() { return vec![Annotatable::Item(item.map_attrs(|mut attrs| { - attrs.push(cx.attribute(span, P(mitem.clone()))); + attrs.push(cx.attribute(span, mitem.clone())); attrs.extend(derive_attrs); attrs }))]; @@ -135,7 +136,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, let mut traits = get_traits(mitem, cx); for derive_attr in derive_attrs { - traits.extend(get_traits(&derive_attr.node.value, cx)); + traits.extend(get_traits(&derive_attr.value, cx)); } // First, weed out malformed #[derive] @@ -158,9 +159,8 @@ pub fn expand_derive(cx: &mut ExtCtxt, let tword = titem.word().unwrap(); let tname = tword.name(); - if is_builtin_trait(&tname) || { - let derive_mode = - ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(intern(&tname))); + if is_builtin_trait(tname) || { + let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname)); cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false } }).unwrap_or(false) @@ -176,7 +176,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, feature_gate::EXPLAIN_CUSTOM_DERIVE); } else { cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - let name = intern_and_get_ident(&format!("derive_{}", tname)); + let name = Symbol::intern(&format!("derive_{}", tname)); let mitem = cx.meta_word(titem.span, name); new_attributes.push(cx.attribute(mitem.span, mitem)); } @@ -186,9 +186,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, item = item.map(|mut i| { i.attrs.extend(new_attributes); if traits.len() > 0 { - let list = cx.meta_list(mitem.span, - intern_and_get_ident("derive"), - traits); + let list = cx.meta_list(mitem.span, derive, traits); i.attrs.push(cx.attribute(mitem.span, list)); } i @@ -217,7 +215,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, let macros_11_derive = traits.iter() .cloned() .enumerate() - .filter(|&(_, ref name)| !is_builtin_trait(&name.name().unwrap())) + .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap())) .next(); if let Some((i, titem)) = macros_11_derive { if !cx.ecfg.features.unwrap().proc_macro { @@ -226,24 +224,20 @@ pub fn expand_derive(cx: &mut ExtCtxt, emit_feature_err(cx.parse_sess, "proc_macro", titem.span, issue, msg); } - let tname = ast::Ident::with_empty_ctxt(intern(&titem.name().unwrap())); + let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); let path = ast::Path::from_ident(titem.span, tname); let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); traits.remove(i); if traits.len() > 0 { item = item.map(|mut i| { - let list = cx.meta_list(mitem.span, - intern_and_get_ident("derive"), - traits); + let list = cx.meta_list(mitem.span, derive, traits); i.attrs.push(cx.attribute(mitem.span, list)); i }); } let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap()); - let mitem = cx.meta_list(titem.span, - intern_and_get_ident("derive"), - vec![titem]); + let mitem = cx.meta_list(titem.span, derive, vec![titem]); let item = Annotatable::Item(item); if let SyntaxExtension::CustomDerive(ref ext) = *ext { return ext.expand(cx, mitem.span, &mitem, item); @@ -257,9 +251,10 @@ pub fn expand_derive(cx: &mut ExtCtxt, // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted) // `#[structural_match]` attribute. - if traits.iter().filter_map(|t| t.name()).any(|t| t == "PartialEq") && - traits.iter().filter_map(|t| t.name()).any(|t| t == "Eq") { - let structural_match = intern_and_get_ident("structural_match"); + let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq")); + if traits.iter().any(|t| t.name() == Some(partial_eq)) && + traits.iter().any(|t| t.name() == Some(eq)) { + let structural_match = Symbol::intern("structural_match"); let span = allow_unstable(cx, span, "derive(PartialEq, Eq)"); let meta = cx.meta_word(span, structural_match); item = item.map(|mut i| { @@ -272,9 +267,10 @@ pub fn expand_derive(cx: &mut ExtCtxt, // the same as the copy implementation. // // Add a marker attribute here picked up during #[derive(Clone)] - if traits.iter().filter_map(|t| t.name()).any(|t| t == "Clone") && - traits.iter().filter_map(|t| t.name()).any(|t| t == "Copy") { - let marker = intern_and_get_ident("rustc_copy_clone_marker"); + let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone")); + if traits.iter().any(|t| t.name() == Some(clone)) && + traits.iter().any(|t| t.name() == Some(copy)) { + let marker = Symbol::intern("rustc_copy_clone_marker"); let span = allow_unstable(cx, span, "derive(Copy, Clone)"); let meta = cx.meta_word(span, marker); item = item.map(|mut i| { @@ -286,14 +282,14 @@ pub fn expand_derive(cx: &mut ExtCtxt, let mut items = Vec::new(); for titem in traits.iter() { let tname = titem.word().unwrap().name(); - let name = intern_and_get_ident(&format!("derive({})", tname)); + let name = Symbol::intern(&format!("derive({})", tname)); let mitem = cx.meta_word(titem.span, name); let span = Span { expn_id: cx.codemap().record_expansion(codemap::ExpnInfo { call_site: titem.span, callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(intern(&format!("derive({})", tname))), + format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))), span: Some(titem.span), allow_internal_unstable: true, }, @@ -302,7 +298,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, }; let my_item = Annotatable::Item(item); - expand_builtin(&tname, cx, span, &mitem, &my_item, &mut |a| { + expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| { items.push(a); }); item = my_item.expect_item(); @@ -314,8 +310,8 @@ pub fn expand_derive(cx: &mut ExtCtxt, macro_rules! derive_traits { ($( $name:expr => $func:path, )+) => { - pub fn is_builtin_trait(name: &str) -> bool { - match name { + pub fn is_builtin_trait(name: ast::Name) -> bool { + match &*name.as_str() { $( $name )|+ => true, _ => false, } @@ -412,7 +408,7 @@ fn call_intrinsic(cx: &ExtCtxt, span.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo { call_site: span, callee: codemap::NameAndSpan { - format: codemap::MacroAttribute(intern("derive")), + format: codemap::MacroAttribute(Symbol::intern("derive")), span: Some(span), allow_internal_unstable: true, }, diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 5c081b98962e..ecf0a8f377ea 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -17,7 +17,7 @@ use syntax::ast; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax_pos::Span; use syntax::tokenstream; @@ -32,7 +32,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, Some(v) => v, }; - let e = match env::var(&var[..]) { + let e = match env::var(&*var.as_str()) { Err(..) => { cx.expr_path(cx.path_all(sp, true, @@ -49,7 +49,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, Ok(s) => { cx.expr_call_global(sp, cx.std_path(&["option", "Option", "Some"]), - vec![cx.expr_str(sp, token::intern_and_get_ident(&s[..]))]) + vec![cx.expr_str(sp, Symbol::intern(&s))]) } }; MacEager::expr(e) @@ -73,7 +73,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, Some((v, _style)) => v, }; let msg = match exprs.next() { - None => token::intern_and_get_ident(&format!("environment variable `{}` not defined", var)), + None => Symbol::intern(&format!("environment variable `{}` not defined", var)), Some(second) => { match expr_to_string(cx, second, "expected string literal") { None => return DummyResult::expr(sp), @@ -87,12 +87,12 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, return DummyResult::expr(sp); } - let e = match env::var(&var[..]) { + let e = match env::var(&*var.as_str()) { Err(_) => { - cx.span_err(sp, &msg); + cx.span_err(sp, &msg.as_str()); cx.expr_usize(sp, 0) } - Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s)), + Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; MacEager::expr(e) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 6eba8baf5b82..d2afa08cadaf 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -17,8 +17,9 @@ use syntax::ast; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; -use syntax::parse::token::{self, keywords}; +use syntax::parse::token; use syntax::ptr::P; +use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, DUMMY_SP}; use syntax::tokenstream; @@ -369,7 +370,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Translate the accumulated string literals to a literal expression fn trans_literal_string(&mut self) -> P { let sp = self.fmtsp; - let s = token::intern_and_get_ident(&self.literal); + let s = Symbol::intern(&self.literal); self.literal.clear(); self.ecx.expr_str(sp, s) } @@ -727,7 +728,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, fmtsp: fmt.span, }; - let mut parser = parse::Parser::new(&fmt.node.0); + let fmt_str = &*fmt.node.0.as_str(); + let mut parser = parse::Parser::new(fmt_str); let mut pieces = vec![]; loop { @@ -808,7 +810,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, // Decide if we want to look for foreign formatting directives. if args_used < args_unused { use super::format_foreign as foreign; - let fmt_str = &fmt.node.0[..]; // The set of foreign substitutions we've explained. This prevents spamming the user // with `%d should be written as {}` over and over again. diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 1ebac19b4f02..e83fd55cd714 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -53,7 +53,7 @@ use std::rc::Rc; use syntax::ast; use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension}; use syntax::ext::tt::macro_rules::MacroRulesExpander; -use syntax::parse::token::intern; +use syntax::symbol::Symbol; pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, user_exts: Vec, @@ -62,11 +62,11 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext)); }; - register(intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false)); + register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false)); macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( - register(intern(stringify!($name)), + register(Symbol::intern(stringify!($name)), NormalTT(Box::new($f as MacroExpanderFn), None, false)); )* } } @@ -112,9 +112,10 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver, } // format_args uses `unstable` things internally. - register(intern("format_args"), NormalTT(Box::new(format::expand_format_args), None, true)); + register(Symbol::intern("format_args"), + NormalTT(Box::new(format::expand_format_args), None, true)); - register(intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); + register(Symbol::intern("derive"), MultiModifier(Box::new(deriving::expand_derive))); for (name, ext) in user_exts { register(name, ext); diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 36fd6408b4f3..bbdbda701ae8 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -17,20 +17,20 @@ use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::ext::expand::ExpansionConfig; use syntax::parse::ParseSess; -use syntax::parse::token::{self, InternedString}; use syntax::feature_gate::Features; use syntax::fold::Folder; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; use syntax::visit::{self, Visitor}; use deriving; struct CustomDerive { - trait_name: InternedString, + trait_name: ast::Name, function_name: Ident, span: Span, - attrs: Vec, + attrs: Vec, } struct CollectCustomDerives<'a> { @@ -183,7 +183,7 @@ impl<'a> Visitor for CollectCustomDerives<'a> { self.handler.span_err(trait_attr.span(), "must only be one word"); } - if deriving::is_builtin_trait(&trait_name) { + if deriving::is_builtin_trait(trait_name) { self.handler.span_err(trait_attr.span(), "cannot override a built-in #[derive] mode"); } @@ -271,29 +271,29 @@ fn mk_registrar(cx: &mut ExtCtxt, let eid = cx.codemap().record_expansion(ExpnInfo { call_site: DUMMY_SP, callee: NameAndSpan { - format: MacroAttribute(token::intern("proc_macro")), + format: MacroAttribute(Symbol::intern("proc_macro")), span: None, allow_internal_unstable: true, } }); let span = Span { expn_id: eid, ..DUMMY_SP }; - let proc_macro = token::str_to_ident("proc_macro"); + let proc_macro = Ident::from_str("proc_macro"); let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None)); - let __internal = token::str_to_ident("__internal"); - let registry = token::str_to_ident("Registry"); - let registrar = token::str_to_ident("registrar"); - let register_custom_derive = token::str_to_ident("register_custom_derive"); + let __internal = Ident::from_str("__internal"); + let registry = Ident::from_str("Registry"); + let registrar = Ident::from_str("registrar"); + let register_custom_derive = Ident::from_str("register_custom_derive"); let stmts = custom_derives.iter().map(|cd| { let path = cx.path_global(cd.span, vec![cd.function_name]); - let trait_name = cx.expr_str(cd.span, cd.trait_name.clone()); + let trait_name = cx.expr_str(cd.span, cd.trait_name); let attrs = cx.expr_vec_slice( span, - cd.attrs.iter().map(|s| cx.expr_str(cd.span, s.clone())).collect::>() + cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::>() ); (path, trait_name, attrs) }).map(|(path, trait_name, attrs)| { @@ -316,15 +316,14 @@ fn mk_registrar(cx: &mut ExtCtxt, cx.ty(span, ast::TyKind::Tup(Vec::new())), cx.block(span, stmts)); - let derive_registrar = token::intern_and_get_ident("rustc_derive_registrar"); - let derive_registrar = cx.meta_word(span, derive_registrar); + let derive_registrar = cx.meta_word(span, Symbol::intern("rustc_derive_registrar")); let derive_registrar = cx.attribute(span, derive_registrar); let func = func.map(|mut i| { i.attrs.push(derive_registrar); i.vis = ast::Visibility::Public; i }); - let ident = ast::Ident::with_empty_ctxt(token::gensym("registrar")); + let ident = ast::Ident::with_empty_ctxt(Symbol::gensym("registrar")); let module = cx.item_mod(span, span, ident, Vec::new(), vec![krate, func]).map(|mut i| { i.vis = ast::Visibility::Public; i diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 9578af681007..48be8e0c53c2 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -11,7 +11,7 @@ use syntax::ext::base::ExtCtxt; use syntax::ext::base; use syntax::feature_gate; -use syntax::parse::token::keywords; +use syntax::symbol::keywords; use syntax_pos::Span; use syntax::tokenstream::TokenTree; diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index a5ba1d219c36..70f7ee3004dd 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -22,6 +22,9 @@ #include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#if LLVM_VERSION_GE(4, 0) +#include "llvm/Transforms/IPO/AlwaysInliner.h" +#endif #include "llvm-c/Transforms/PassManagerBuilder.h" @@ -539,7 +542,11 @@ LLVMRustPrintPasses() { extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) { +#if LLVM_VERSION_GE(4, 0) + unwrap(PMB)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes); +#else unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes); +#endif } extern "C" void diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 7f0c7e2e5c9f..b035e134e37d 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -155,13 +155,10 @@ from_rust(LLVMRustAttribute kind) { } } -extern "C" LLVMAttributeRef LLVMRustCreateAttribute(LLVMContextRef C, LLVMRustAttribute Kind, uint64_t Val) { - return wrap(Attribute::get(*unwrap(C), from_rust(Kind), Val)); -} - -extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, LLVMAttributeRef attr) { +extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, LLVMRustAttribute attr) { CallSite Call = CallSite(unwrap(Instr)); - AttrBuilder B(unwrap(attr)); + Attribute Attr = Attribute::get(Call->getContext(), from_rust(attr)); + AttrBuilder B(Attr); Call.setAttributes( Call.getAttributes().addAttributes(Call->getContext(), index, AttributeSet::get(Call->getContext(), @@ -183,10 +180,11 @@ extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr, extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned index, - LLVMAttributeRef attr) + LLVMRustAttribute attr) { Function *A = unwrap(Fn); - AttrBuilder B(unwrap(attr)); + Attribute Attr = Attribute::get(A->getContext(), from_rust(attr)); + AttrBuilder B(Attr); A->addAttributes(index, AttributeSet::get(A->getContext(), index, B)); } @@ -212,11 +210,12 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn, extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, unsigned index, - LLVMAttributeRef attr) + LLVMRustAttribute attr) { Function *F = unwrap(Fn); const AttributeSet PAL = F->getAttributes(); - AttrBuilder B(unwrap(attr)); + Attribute Attr = Attribute::get(F->getContext(), from_rust(attr)); + AttrBuilder B(Attr); const AttributeSet PALnew = PAL.removeAttributes(F->getContext(), index, AttributeSet::get(F->getContext(), index, B)); diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs index 8ea131da338c..8647797270f9 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs @@ -36,7 +36,7 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name.as_str() == "lintme" { + if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } } diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs index 409f9dbf03c5..dc88bfc40595 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs @@ -19,8 +19,9 @@ extern crate rustc_plugin; use syntax::ast::{self, Item, MetaItem, ItemKind}; use syntax::ext::base::*; -use syntax::parse::{self, token}; +use syntax::parse; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax::tokenstream::TokenTree; use syntax_pos::Span; use rustc_plugin::Registry; @@ -34,11 +35,11 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("make_a_1", expand_make_a_1); reg.register_macro("identity", expand_identity); reg.register_syntax_extension( - token::intern("into_multi_foo"), + Symbol::intern("into_multi_foo"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiModifier(Box::new(expand_into_foo_multi))); reg.register_syntax_extension( - token::intern("duplicate"), + Symbol::intern("duplicate"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_duplicate))); } @@ -102,9 +103,9 @@ fn expand_duplicate(cx: &mut ExtCtxt, push: &mut FnMut(Annotatable)) { let copy_name = match mi.node { - ast::MetaItemKind::List(_, ref xs) => { + ast::MetaItemKind::List(ref xs) => { if let Some(word) = xs[0].word() { - token::str_to_ident(&word.name()) + ast::Ident::with_empty_ctxt(word.name()) } else { cx.span_err(mi.span, "Expected word"); return; diff --git a/src/test/compile-fail-fulldeps/qquote.rs b/src/test/compile-fail-fulldeps/qquote.rs index 4a7033d44b87..8acab3369e48 100644 --- a/src/test/compile-fail-fulldeps/qquote.rs +++ b/src/test/compile-fail-fulldeps/qquote.rs @@ -16,8 +16,8 @@ extern crate syntax; extern crate syntax_pos; use syntax::ast; -use syntax::parse; use syntax::print::pprust; +use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; fn main() { @@ -30,7 +30,7 @@ fn main() { cx.bt_push(syntax::codemap::ExpnInfo { call_site: DUMMY_SP, callee: syntax::codemap::NameAndSpan { - format: syntax::codemap::MacroBang(parse::token::intern("")), + format: syntax::codemap::MacroBang(Symbol::intern("")), allow_internal_unstable: false, span: None, } diff --git a/src/test/compile-fail/E0088.rs b/src/test/compile-fail/E0088.rs index 0b235aa240c3..9ec096032241 100644 --- a/src/test/compile-fail/E0088.rs +++ b/src/test/compile-fail/E0088.rs @@ -9,7 +9,12 @@ // except according to those terms. fn f() {} +fn g<'a>() {} fn main() { f::<'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameter + + g::<'static, 'static>(); //~ ERROR E0088 + //~^ unexpected lifetime parameters } diff --git a/src/test/compile-fail/auxiliary/namespace-mix-old.rs b/src/test/compile-fail/auxiliary/namespace-mix-old.rs deleted file mode 100644 index 29b139d771b0..000000000000 --- a/src/test/compile-fail/auxiliary/namespace-mix-old.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: Remove when `item_like_imports` is stabilized. - -pub mod c { - pub struct S {} - pub struct TS(); - pub struct US; - pub enum E { - V {}, - TV(), - UV, - } - - pub struct Item; -} - -pub mod proxy { - pub use c::*; - pub use c::E::*; -} - -pub mod xm1 { - pub use ::proxy::*; - pub type S = ::c::Item; -} -pub mod xm2 { - pub use ::proxy::*; - pub const S: ::c::Item = ::c::Item; -} - -pub mod xm3 { - pub use ::proxy::*; - pub type TS = ::c::Item; -} -pub mod xm4 { - pub use ::proxy::*; - pub const TS: ::c::Item = ::c::Item; -} - -pub mod xm5 { - pub use ::proxy::*; - pub type US = ::c::Item; -} -pub mod xm6 { - pub use ::proxy::*; - pub const US: ::c::Item = ::c::Item; -} - -pub mod xm7 { - pub use ::proxy::*; - pub type V = ::c::Item; -} -pub mod xm8 { - pub use ::proxy::*; - pub const V: ::c::Item = ::c::Item; -} - -pub mod xm9 { - pub use ::proxy::*; - pub type TV = ::c::Item; -} -pub mod xmA { - pub use ::proxy::*; - pub const TV: ::c::Item = ::c::Item; -} - -pub mod xmB { - pub use ::proxy::*; - pub type UV = ::c::Item; -} -pub mod xmC { - pub use ::proxy::*; - pub const UV: ::c::Item = ::c::Item; -} diff --git a/src/test/compile-fail/auxiliary/namespace-mix-new.rs b/src/test/compile-fail/auxiliary/namespace-mix.rs similarity index 97% rename from src/test/compile-fail/auxiliary/namespace-mix-new.rs rename to src/test/compile-fail/auxiliary/namespace-mix.rs index d42c0ee1a4da..d82e9bb70228 100644 --- a/src/test/compile-fail/auxiliary/namespace-mix-new.rs +++ b/src/test/compile-fail/auxiliary/namespace-mix.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(item_like_imports)] - pub mod c { pub struct S {} pub struct TS(); diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/auxiliary/rmeta_meta.rs similarity index 52% rename from src/test/compile-fail/import-shadow-6.rs rename to src/test/compile-fail/auxiliary/rmeta_meta.rs index fa3b75c70f0b..7bd1a96f452d 100644 --- a/src/test/compile-fail/import-shadow-6.rs +++ b/src/test/compile-fail/auxiliary/rmeta_meta.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,23 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that import shadowing using globs causes errors +// no-prefer-dynamic -#![no_implicit_prelude] +#![crate_type="metadata"] -use qux::*; -use foo::*; //~ERROR a type named `Baz` has already been imported in this module - -mod foo { - pub type Baz = isize; +pub struct Foo { + pub field: i32, } - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/auxiliary/rmeta_rlib.rs b/src/test/compile-fail/auxiliary/rmeta_rlib.rs new file mode 100644 index 000000000000..6096c4df05bb --- /dev/null +++ b/src/test/compile-fail/auxiliary/rmeta_rlib.rs @@ -0,0 +1,15 @@ +// 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. + +#![crate_type="rlib"] + +pub struct Foo { + pub field: i32, +} diff --git a/src/test/compile-fail/issue-12612.rs b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs similarity index 58% rename from src/test/compile-fail/issue-12612.rs rename to src/test/compile-fail/directory_ownership/backcompat-warnings.rs index c6f76ca78874..75e3426a3993 100644 --- a/src/test/compile-fail/issue-12612.rs +++ b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,15 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:issue_12612_1.rs +// error-pattern: cannot declare a new module at this location +// error-pattern: will become a hard error +// error-pattern: compilation successful -extern crate issue_12612_1 as foo; +#![feature(rustc_attrs)] -use foo::bar; - -mod test { - use bar::foo; //~ ERROR unresolved import `bar::foo` [E0432] - //~^ Maybe a missing `extern crate bar;`? -} +#[path="mod_file_not_owning_aux3.rs"] +mod foo; +#[rustc_error] fn main() {} diff --git a/src/test/compile-fail/macro-expanded-mod.rs b/src/test/compile-fail/directory_ownership/macro-expanded-mod.rs similarity index 100% rename from src/test/compile-fail/macro-expanded-mod.rs rename to src/test/compile-fail/directory_ownership/macro-expanded-mod.rs diff --git a/src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs b/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/bar.rs similarity index 100% rename from src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs rename to src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/bar.rs diff --git a/src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs b/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/mod.rs similarity index 100% rename from src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs rename to src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/mod.rs diff --git a/src/test/compile-fail/mod_file_not_owning.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning.rs similarity index 94% rename from src/test/compile-fail/mod_file_not_owning.rs rename to src/test/compile-fail/directory_ownership/mod_file_not_owning.rs index 7dcff6e6644f..adbcedd91f20 100644 --- a/src/test/compile-fail/mod_file_not_owning.rs +++ b/src/test/compile-fail/directory_ownership/mod_file_not_owning.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - // error-pattern: cannot declare a new module at this location mod mod_file_not_owning_aux1; diff --git a/src/test/compile-fail/mod_file_not_owning_aux1.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs similarity index 87% rename from src/test/compile-fail/mod_file_not_owning_aux1.rs rename to src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs index 2d522be6dc5d..4ac94a92e376 100644 --- a/src/test/compile-fail/mod_file_not_owning_aux1.rs +++ b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs @@ -10,4 +10,7 @@ // ignore-test this is not a test -mod mod_file_not_owning_aux2; +macro_rules! m { + () => { mod mod_file_not_owning_aux2; } +} +m!(); diff --git a/src/test/compile-fail/mod_file_not_owning_aux2.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux2.rs similarity index 100% rename from src/test/compile-fail/mod_file_not_owning_aux2.rs rename to src/test/compile-fail/directory_ownership/mod_file_not_owning_aux2.rs diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs new file mode 100644 index 000000000000..3a164fd55d92 --- /dev/null +++ b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs @@ -0,0 +1,13 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-test this is not a test + +mod mod_file_not_owning_aux2; diff --git a/src/test/compile-fail/non-inline-mod-restriction.rs b/src/test/compile-fail/directory_ownership/non-inline-mod-restriction.rs similarity index 100% rename from src/test/compile-fail/non-inline-mod-restriction.rs rename to src/test/compile-fail/directory_ownership/non-inline-mod-restriction.rs diff --git a/src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs b/src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs new file mode 100644 index 000000000000..854f790befcf --- /dev/null +++ b/src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs @@ -0,0 +1,15 @@ +// 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. + +// error-pattern: cannot declare a new module at this location + +// This is not a directory owner since the file name is not "mod.rs". +#[path = "mod_file_not_owning_aux1.rs"] +mod foo; diff --git a/src/test/compile-fail/feature-gate-loop-break-value.rs b/src/test/compile-fail/feature-gate-loop-break-value.rs new file mode 100644 index 000000000000..1632c40d59fd --- /dev/null +++ b/src/test/compile-fail/feature-gate-loop-break-value.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() { + loop { + break 123; //~ ERROR `break` with a value is experimental + } +} diff --git a/src/test/compile-fail/glob-cycles.rs b/src/test/compile-fail/glob-cycles.rs index 077ae19b4cbd..8f1b8ec91db3 100644 --- a/src/test/compile-fail/glob-cycles.rs +++ b/src/test/compile-fail/glob-cycles.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_attrs)] + mod foo { pub use bar::*; - pub use main as f; //~ ERROR has already been imported + pub use main as f; } mod bar { @@ -18,9 +20,10 @@ mod bar { } pub use foo::*; -pub use baz::*; //~ ERROR has already been imported +pub use baz::*; mod baz { pub use super::*; } -pub fn main() {} +#[rustc_error] +pub fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/import-shadow-5.rs b/src/test/compile-fail/import-shadow-5.rs deleted file mode 100644 index dc300bc7baa7..000000000000 --- a/src/test/compile-fail/import-shadow-5.rs +++ /dev/null @@ -1,30 +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. - -// Test that import shadowing using globs causes errors - -#![no_implicit_prelude] - -use foo::Baz; -use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module - -mod foo { - pub type Baz = isize; -} - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/import-shadow-7.rs b/src/test/compile-fail/import-shadow-7.rs deleted file mode 100644 index 34aba15b3922..000000000000 --- a/src/test/compile-fail/import-shadow-7.rs +++ /dev/null @@ -1,30 +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. - -// Test that import shadowing using globs causes errors - -#![no_implicit_prelude] - -use foo::*; -use qux::*; //~ERROR a type named `Baz` has already been imported in this module - -mod foo { - pub type Baz = isize; -} - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/import.rs b/src/test/compile-fail/import.rs index 1ca1c060410a..81a5334ed7ab 100644 --- a/src/test/compile-fail/import.rs +++ b/src/test/compile-fail/import.rs @@ -20,6 +20,6 @@ mod zed { } fn main() { - zed::foo(); //~ ERROR unresolved name + zed::foo(); //~ ERROR `foo` is private bar(); } diff --git a/src/test/compile-fail/imports/duplicate.rs b/src/test/compile-fail/imports/duplicate.rs index faf85a523e8f..8dd69d8c24c8 100644 --- a/src/test/compile-fail/imports/duplicate.rs +++ b/src/test/compile-fail/imports/duplicate.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(item_like_imports)] - mod a { pub fn foo() {} } diff --git a/src/test/compile-fail/imports/reexports.rs b/src/test/compile-fail/imports/reexports.rs index fc46b23351ad..65e6e8d01b05 100644 --- a/src/test/compile-fail/imports/reexports.rs +++ b/src/test/compile-fail/imports/reexports.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(item_like_imports)] - mod a { fn foo() {} mod foo {} diff --git a/src/test/compile-fail/imports/unused.rs b/src/test/compile-fail/imports/unused.rs index 4ec9987df420..05ecc781af30 100644 --- a/src/test/compile-fail/imports/unused.rs +++ b/src/test/compile-fail/imports/unused.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(pub_restricted, item_like_imports)] +#![feature(pub_restricted)] #![deny(unused)] mod foo { diff --git a/src/test/compile-fail/issue-32797.rs b/src/test/compile-fail/issue-32797.rs index af75783a710b..2c54ed3e857e 100644 --- a/src/test/compile-fail/issue-32797.rs +++ b/src/test/compile-fail/issue-32797.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(rustc_attrs)] + pub use bar::*; mod bar { pub use super::*; } -pub use baz::*; //~ ERROR already been imported +pub use baz::*; mod baz { pub use main as f; } -pub fn main() {} +#[rustc_error] +pub fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/issue-32833.rs b/src/test/compile-fail/issue-32833.rs index d610e8b48379..41383e93603d 100644 --- a/src/test/compile-fail/issue-32833.rs +++ b/src/test/compile-fail/issue-32833.rs @@ -11,8 +11,7 @@ use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432] //~^ no `Foo` in `bar` mod bar { - use Foo; //~ ERROR unresolved import `Foo` [E0432] - //~^ no `Foo` in the root + use Foo; } fn main() {} diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs new file mode 100644 index 000000000000..d4f295974869 --- /dev/null +++ b/src/test/compile-fail/loop-break-value.rs @@ -0,0 +1,101 @@ +// 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. + +#![feature(loop_break_value)] +#![feature(never_type)] + +fn main() { + let val: ! = loop { break break; }; + //~^ ERROR mismatched types + + loop { + if true { + break "asdf"; + } else { + break 123; //~ ERROR mismatched types + } + }; + + let _: i32 = loop { + break "asdf"; //~ ERROR mismatched types + }; + + let _: i32 = 'outer_loop: loop { + loop { + break 'outer_loop "nope"; //~ ERROR mismatched types + break "ok"; + }; + }; + + 'while_loop: while true { + break; + break (); //~ ERROR `break` with value from a `while` loop + loop { + break 'while_loop 123; + //~^ ERROR `break` with value from a `while` loop + //~| ERROR mismatched types + break 456; + break 789; + }; + } + + 'while_let_loop: while let Some(_) = Some(()) { + if break () { //~ ERROR `break` with value from a `while let` loop + break; + break None; + //~^ ERROR `break` with value from a `while let` loop + //~| ERROR mismatched types + } + loop { + break 'while_let_loop "nope"; + //~^ ERROR `break` with value from a `while let` loop + //~| ERROR mismatched types + break 33; + }; + } + + 'for_loop: for _ in &[1,2,3] { + break (); //~ ERROR `break` with value from a `for` loop + break [()]; + //~^ ERROR `break` with value from a `for` loop + //~| ERROR mismatched types + loop { + break Some(3); + break 'for_loop Some(17); + //~^ ERROR `break` with value from a `for` loop + //~| ERROR mismatched types + }; + } + + let _: i32 = 'a: loop { + let _: () = 'b: loop { + break ('c: loop { + break; + break 'c 123; //~ ERROR mismatched types + }); + break 'a 123; + }; + }; + + loop { + break (break, break); //~ ERROR mismatched types + }; + + loop { + break; + break 2; //~ ERROR mismatched types + }; + + loop { + break 2; + break; //~ ERROR mismatched types + break 4; + }; +} diff --git a/src/test/compile-fail/namespace-mix-old.rs b/src/test/compile-fail/namespace-mix-old.rs deleted file mode 100644 index 8cd82050814a..000000000000 --- a/src/test/compile-fail/namespace-mix-old.rs +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: Remove when `item_like_imports` is stabilized. - -// aux-build:namespace-mix-old.rs - -extern crate namespace_mix_old; -use namespace_mix_old::{xm1, xm2, xm3, xm4, xm5, xm6, xm7, xm8, xm9, xmA, xmB, xmC}; - -mod c { - pub struct S {} - pub struct TS(); - pub struct US; - pub enum E { - V {}, - TV(), - UV, - } - - pub struct Item; -} - -mod proxy { - pub use c::*; - pub use c::E::*; -} - -// Use something emitting the type argument name, e.g. unsatisfied bound. -trait Impossible {} -fn check(_: T) {} - -mod m1 { - pub use ::proxy::*; - pub type S = ::c::Item; -} -mod m2 { - pub use ::proxy::*; - pub const S: ::c::Item = ::c::Item; -} - -fn f12() { - check(m1::S{}); //~ ERROR c::Item - check(m1::S); //~ ERROR unresolved name - check(m2::S{}); //~ ERROR c::S - check(m2::S); //~ ERROR c::Item -} -fn xf12() { - check(xm1::S{}); //~ ERROR c::Item - check(xm1::S); //~ ERROR unresolved name - check(xm2::S{}); //~ ERROR c::S - check(xm2::S); //~ ERROR c::Item -} - -mod m3 { - pub use ::proxy::*; - pub type TS = ::c::Item; -} -mod m4 { - pub use ::proxy::*; - pub const TS: ::c::Item = ::c::Item; -} - -fn f34() { - check(m3::TS{}); //~ ERROR c::Item - check(m3::TS); //~ ERROR c::TS - check(m4::TS{}); //~ ERROR c::TS - check(m4::TS); //~ ERROR c::Item -} -fn xf34() { - check(xm3::TS{}); //~ ERROR c::Item - check(xm3::TS); //~ ERROR c::TS - check(xm4::TS{}); //~ ERROR c::TS - check(xm4::TS); //~ ERROR c::Item -} - -mod m5 { - pub use ::proxy::*; - pub type US = ::c::Item; -} -mod m6 { - pub use ::proxy::*; - pub const US: ::c::Item = ::c::Item; -} - -fn f56() { - check(m5::US{}); //~ ERROR c::Item - check(m5::US); //~ ERROR c::US - check(m6::US{}); //~ ERROR c::US - check(m6::US); //~ ERROR c::Item -} -fn xf56() { - check(xm5::US{}); //~ ERROR c::Item - check(xm5::US); //~ ERROR c::US - check(xm6::US{}); //~ ERROR c::US - check(xm6::US); //~ ERROR c::Item -} - -mod m7 { - pub use ::proxy::*; - pub type V = ::c::Item; -} -mod m8 { - pub use ::proxy::*; - pub const V: ::c::Item = ::c::Item; -} - -fn f78() { - check(m7::V{}); //~ ERROR c::Item - check(m7::V); //~ ERROR name of a struct or struct variant - check(m8::V{}); //~ ERROR c::E - check(m8::V); //~ ERROR c::Item -} -fn xf78() { - check(xm7::V{}); //~ ERROR c::Item - check(xm7::V); //~ ERROR name of a struct or struct variant - check(xm8::V{}); //~ ERROR c::E - check(xm8::V); //~ ERROR c::Item -} - -mod m9 { - pub use ::proxy::*; - pub type TV = ::c::Item; -} -mod mA { - pub use ::proxy::*; - pub const TV: ::c::Item = ::c::Item; -} - -fn f9A() { - check(m9::TV{}); //~ ERROR c::Item - check(m9::TV); //~ ERROR c::E - check(mA::TV{}); //~ ERROR c::E - check(mA::TV); //~ ERROR c::Item -} -fn xf9A() { - check(xm9::TV{}); //~ ERROR c::Item - check(xm9::TV); //~ ERROR c::E - check(xmA::TV{}); //~ ERROR c::E - check(xmA::TV); //~ ERROR c::Item -} - -mod mB { - pub use ::proxy::*; - pub type UV = ::c::Item; -} -mod mC { - pub use ::proxy::*; - pub const UV: ::c::Item = ::c::Item; -} - -fn fBC() { - check(mB::UV{}); //~ ERROR c::Item - check(mB::UV); //~ ERROR c::E - check(mC::UV{}); //~ ERROR c::E - check(mC::UV); //~ ERROR c::Item -} -fn xfBC() { - check(xmB::UV{}); //~ ERROR c::Item - check(xmB::UV); //~ ERROR c::E - check(xmC::UV{}); //~ ERROR c::E - check(xmC::UV); //~ ERROR c::Item -} - -fn main() {} diff --git a/src/test/compile-fail/namespace-mix-new.rs b/src/test/compile-fail/namespace-mix.rs similarity index 96% rename from src/test/compile-fail/namespace-mix-new.rs rename to src/test/compile-fail/namespace-mix.rs index 59592e3d737d..cb7894b726f4 100644 --- a/src/test/compile-fail/namespace-mix-new.rs +++ b/src/test/compile-fail/namespace-mix.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:namespace-mix-new.rs +// aux-build:namespace-mix.rs -#![feature(item_like_imports)] - -extern crate namespace_mix_new; -use namespace_mix_new::*; +extern crate namespace_mix; +use namespace_mix::*; mod c { pub struct S {} diff --git a/src/test/compile-fail/privacy2.rs b/src/test/compile-fail/privacy2.rs index 376e95312b8f..113dd2879406 100644 --- a/src/test/compile-fail/privacy2.rs +++ b/src/test/compile-fail/privacy2.rs @@ -31,8 +31,7 @@ fn test1() { fn test2() { use bar::glob::foo; - //~^ ERROR unresolved import `bar::glob::foo` [E0432] - //~| no `foo` in `bar::glob` + //~^ ERROR `foo` is private } #[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } diff --git a/src/test/compile-fail/rmeta-lib-pass.rs b/src/test/compile-fail/rmeta-lib-pass.rs new file mode 100644 index 000000000000..f2ac37a2ce9f --- /dev/null +++ b/src/test/compile-fail/rmeta-lib-pass.rs @@ -0,0 +1,25 @@ +// 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:rmeta_rlib.rs +// no-prefer-dynamic +// must-compile-successfully + +// Check that building a metadata crate works with a dependent, rlib crate. +// This is a cfail test since there is no executable to run. + +#![crate_type="metadata"] + +extern crate rmeta_rlib; +use rmeta_rlib::Foo; + +pub fn main() { + let _ = Foo { field: 42 }; +} diff --git a/src/test/compile-fail/rmeta-pass.rs b/src/test/compile-fail/rmeta-pass.rs new file mode 100644 index 000000000000..2c0b6f77c1e0 --- /dev/null +++ b/src/test/compile-fail/rmeta-pass.rs @@ -0,0 +1,26 @@ +// 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:rmeta_meta.rs +// no-prefer-dynamic +// must-compile-successfully + +// Check that building a metadata crate works with a dependent, metadata-only +// crate. +// This is a cfail test since there is no executable to run. + +#![crate_type="metadata"] + +extern crate rmeta_meta; +use rmeta_meta::Foo; + +pub fn main() { + let _ = Foo { field: 42 }; +} diff --git a/src/test/compile-fail/import-shadow-2.rs b/src/test/compile-fail/rmeta.rs similarity index 53% rename from src/test/compile-fail/import-shadow-2.rs rename to src/test/compile-fail/rmeta.rs index 0c107cf27f59..e81e0541096d 100644 --- a/src/test/compile-fail/import-shadow-2.rs +++ b/src/test/compile-fail/rmeta.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,23 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that import shadowing using globs causes errors +// no-prefer-dynamic -#![no_implicit_prelude] +// Check that building a metadata crate finds an error. -use foo::*; -use foo::*; //~ERROR a type named `Baz` has already been imported in this module +#![crate_type="metadata"] -mod foo { - pub type Baz = isize; +fn main() { + let _ = Foo; //~ ERROR unresolved name `Foo` } - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/import-shadow-3.rs b/src/test/compile-fail/rmeta_lib.rs similarity index 51% rename from src/test/compile-fail/import-shadow-3.rs rename to src/test/compile-fail/rmeta_lib.rs index bf90973c2857..3b7d1f3cc904 100644 --- a/src/test/compile-fail/import-shadow-3.rs +++ b/src/test/compile-fail/rmeta_lib.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,23 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that import shadowing using globs causes errors +// aux-build:rmeta_meta.rs +// no-prefer-dynamic +// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available -#![no_implicit_prelude] +// Check that building a non-metadata crate fails if a dependent crate is +// metadata-only. -use foo::Baz; -use bar::*; //~ERROR a type named `Baz` has already been imported in this module +extern crate rmeta_meta; +use rmeta_meta::Foo; -mod foo { - pub type Baz = isize; +fn main() { + let _ = Foo { field: 42 }; } - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/import-shadow-4.rs b/src/test/compile-fail/rmeta_meta_main.rs similarity index 51% rename from src/test/compile-fail/import-shadow-4.rs rename to src/test/compile-fail/rmeta_meta_main.rs index f21fdaae47ba..1c922c281397 100644 --- a/src/test/compile-fail/import-shadow-4.rs +++ b/src/test/compile-fail/rmeta_meta_main.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,23 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that import shadowing using globs causes errors +// aux-build:rmeta_meta.rs +// no-prefer-dynamic -#![no_implicit_prelude] +// Check that building a metadata crate finds an error with a dependent, +// metadata-only crate. -use foo::*; -use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module +#![crate_type="metadata"] -mod foo { - pub type Baz = isize; +extern crate rmeta_meta; +use rmeta_meta::Foo; + +fn main() { + let _ = Foo { field2: 42 }; //~ ERROR struct `rmeta_meta::Foo` has no field named `field2` } - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {} diff --git a/src/test/compile-fail/shadowed-use-visibility.rs b/src/test/compile-fail/shadowed-use-visibility.rs index 1bf7f3933849..e7e57a73de02 100644 --- a/src/test/compile-fail/shadowed-use-visibility.rs +++ b/src/test/compile-fail/shadowed-use-visibility.rs @@ -16,11 +16,11 @@ mod foo { } mod bar { - use foo::bar::f as g; //~ ERROR unresolved import + use foo::bar::f as g; //~ ERROR module `bar` is private use foo as f; pub use foo::*; } -use bar::f::f; //~ ERROR unresolved import +use bar::f::f; //~ ERROR module `f` is private fn main() {} diff --git a/src/test/compile-fail/variant-namespacing.rs b/src/test/compile-fail/variant-namespacing.rs index 3d8e2daaa15b..44e9260770e0 100644 --- a/src/test/compile-fail/variant-namespacing.rs +++ b/src/test/compile-fail/variant-namespacing.rs @@ -31,11 +31,11 @@ const XTuple: u8 = 0; const XUnit: u8 = 0; extern crate variant_namespacing; -pub use variant_namespacing::XE::*; +pub use variant_namespacing::XE::{XStruct, XTuple, XUnit}; //~^ ERROR `XStruct` has already been defined //~| ERROR `XTuple` has already been defined //~| ERROR `XUnit` has already been defined -pub use E::*; +pub use E::{Struct, Tuple, Unit}; //~^ ERROR `Struct` has already been defined //~| ERROR `Tuple` has already been defined //~| ERROR `Unit` has already been defined diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs new file mode 100644 index 000000000000..261eb38a51ae --- /dev/null +++ b/src/test/incremental/change_add_field/struct_point.rs @@ -0,0 +1,164 @@ +// 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. + +// Test where we change a type definition by adding a field. Fns with +// this type in their signature are recompiled, as are their callers. +// Fns with that type used only in their body are also recompiled, but +// their callers are not. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![feature(static_in_const)] +#![allow(dead_code)] + +// These are expected to require translation. +#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_with_type_in_sig", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-call_fn_with_type_in_sig", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_with_type_in_body", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="rpass2")] + +#![rustc_partition_reused(module="struct_point-call_fn_with_type_in_body", cfg="rpass2")] + +mod point { + #[cfg(rpass1)] + pub struct Point { + pub x: f32, + pub y: f32, + } + + #[cfg(rpass2)] + pub struct Point { + pub x: f32, + pub y: f32, + pub z: f32, + } + + impl Point { + pub fn origin() -> Point { + #[cfg(rpass1)] + return Point { x: 0.0, y: 0.0 }; + + #[cfg(rpass2)] + return Point { x: 0.0, y: 0.0, z: 0.0 }; + } + + pub fn total(&self) -> f32 { + #[cfg(rpass1)] + return self.x + self.y; + + #[cfg(rpass2)] + return self.x + self.y + self.z; + } + + pub fn x(&self) -> f32 { + self.x + } + } +} + +/// A fn that has the changed type in its signature; must currently be +/// rebuilt. +/// +/// You could imagine that, in the future, if the change were +/// sufficiently "private", we might not need to type-check again. +/// Rebuilding is probably always necessary since the layout may be +/// affected. +mod fn_with_type_in_sig { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn boop(p: Option<&Point>) -> f32 { + p.map(|p| p.total()).unwrap_or(0.0) + } +} + +/// Call a fn that has the changed type in its signature; this +/// currently must also be rebuilt. +/// +/// You could imagine that, in the future, if the change were +/// sufficiently "private", we might not need to type-check again. +/// Rebuilding is probably always necessary since the layout may be +/// affected. +mod call_fn_with_type_in_sig { + use fn_with_type_in_sig; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn bip() -> f32 { + fn_with_type_in_sig::boop(None) + } +} + +/// A fn that uses the changed type, but only in its body, not its +/// signature. +/// +/// You could imagine that, in the future, if the change were +/// sufficiently "private", we might not need to type-check again. +/// Rebuilding is probably always necessary since the layout may be +/// affected. +mod fn_with_type_in_body { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn boop() -> f32 { + Point::origin().total() + } +} + +/// A fn X that calls a fn Y, where Y uses the changed type in its +/// body. In this case, the effects of the change should be contained +/// to Y; X should not have to be rebuilt, nor should it need to be +/// typechecked again. +mod call_fn_with_type_in_body { + use fn_with_type_in_body; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn bip() -> f32 { + fn_with_type_in_body::boop() + } +} + +/// A fn item that makes an instance of `Point` but does not invoke methods +mod fn_make_struct { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn make_origin(p: Point) -> Point { + Point { ..p } + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_read_field { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn get_x(p: Point) -> f32 { + p.x + } +} + +/// A fn item that writes to a field of `Point` but does not invoke methods +mod fn_write_field { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn inc_x(p: &mut Point) { + p.x += 1.0; + } +} + +fn main() { +} diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs new file mode 100644 index 000000000000..665eafb4f4ee --- /dev/null +++ b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs @@ -0,0 +1,105 @@ +// 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. + +// Test where we change the body of a public, inherent method. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![allow(dead_code)] + +#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")] + +// FIXME(#35078) -- this gets recompiled because we don't separate sig from body +#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="rpass2")] + +#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] + +mod point { + pub struct Point { + pub x: f32, + pub y: f32, + } + + impl Point { + pub fn distance_from_origin(&self) -> f32 { + #[cfg(rpass1)] + return self.x * self.x + self.y * self.y; + + #[cfg(rpass2)] + return (self.x * self.x + self.y * self.y).sqrt(); + } + + pub fn x(&self) -> f32 { + self.x + } + } +} + +/// A fn item that calls the method on `Point` which changed +mod fn_calls_changed_method { + use point::Point; + + // FIXME(#35078) -- this gets recompiled because we don't separate sig from body + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let p = Point { x: 2.0, y: 2.0 }; + p.distance_from_origin(); + } +} + +/// A fn item that calls a method on `Point` which did not change +mod fn_calls_another_method { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let p = Point { x: 2.0, y: 2.0 }; + p.x(); + } +} + +/// A fn item that makes an instance of `Point` but does not invoke methods +mod fn_make_struct { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn make_origin() -> Point { + Point { x: 2.0, y: 2.0 } + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_read_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn get_x(p: Point) -> f32 { + p.x + } +} + +/// A fn item that writes to a field of `Point` but does not invoke methods +mod fn_write_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn inc_x(p: &mut Point) { + p.x += 1.0; + } +} + +fn main() { +} diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs new file mode 100644 index 000000000000..54e06e16998c --- /dev/null +++ b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs @@ -0,0 +1,113 @@ +// 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. + +// Test where we change the *signature* of a public, inherent method. + +// revisions:rpass1 rpass2 +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] +#![feature(static_in_const)] +#![allow(dead_code)] + +// These are expected to require translation. +#![rustc_partition_translated(module="struct_point-point", cfg="rpass2")] +#![rustc_partition_translated(module="struct_point-fn_calls_changed_method", cfg="rpass2")] + +#![rustc_partition_reused(module="struct_point-fn_calls_another_method", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] + +mod point { + pub struct Point { + pub x: f32, + pub y: f32, + } + + impl Point { + #[cfg(rpass1)] + pub fn distance_from_point(&self, p: Option) -> f32 { + let p = p.unwrap_or(Point { x: 0.0, y: 0.0 }); + let x_diff = self.x - p.x; + let y_diff = self.y - p.y; + return x_diff * x_diff + y_diff * y_diff; + } + + #[cfg(rpass2)] + pub fn distance_from_point(&self, p: Option<&Point>) -> f32 { + const ORIGIN: &Point = &Point { x: 0.0, y: 0.0 }; + let p = p.unwrap_or(ORIGIN); + let x_diff = self.x - p.x; + let y_diff = self.y - p.y; + return x_diff * x_diff + y_diff * y_diff; + } + + pub fn x(&self) -> f32 { + self.x + } + } +} + +/// A fn item that calls the method that was changed +mod fn_calls_changed_method { + use point::Point; + + #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let p = Point { x: 2.0, y: 2.0 }; + p.distance_from_point(None); + } +} + +/// A fn item that calls a method that was not changed +mod fn_calls_another_method { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn check() { + let p = Point { x: 2.0, y: 2.0 }; + p.x(); + } +} + +/// A fn item that makes an instance of `Point` but does not invoke methods +mod fn_make_struct { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn make_origin() -> Point { + Point { x: 2.0, y: 2.0 } + } +} + +/// A fn item that reads fields from `Point` but does not invoke methods +mod fn_read_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn get_x(p: Point) -> f32 { + p.x + } +} + +/// A fn item that writes to a field of `Point` but does not invoke methods +mod fn_write_field { + use point::Point; + + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] + pub fn inc_x(p: &mut Point) { + p.x += 1.0; + } +} + +fn main() { +} diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs new file mode 100644 index 000000000000..7a8502f7caab --- /dev/null +++ b/src/test/incremental/hashes/for_loops.rs @@ -0,0 +1,306 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `for` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_body() { + let mut _x = 0; + for _ in 0..1 { + _x = 2; + break; + } +} + + + +// Change iteration variable name ---------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_name() { + let mut _x = 0; + for _i in 0..1 { + _x = 1; + break; + } +} + +#[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")] +fn change_iteration_variable_name() { + let mut _x = 0; + for _a in 0..1 { + _x = 1; + break; + } +} + + + +// Change iteration variable pattern ------------------------------------------- +#[cfg(cfail1)] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for _i in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[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")] +fn change_iteration_variable_pattern() { + let mut _x = 0; + for &_i in &[0, 1, 2] { + _x = 1; + break; + } +} + + + +// Change iterable ------------------------------------------------------------- +#[cfg(cfail1)] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 2] { + _x = 1; + break; + } +} + +#[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")] +fn change_iterable() { + let mut _x = 0; + for _ in &[0, 1, 3] { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + } +} + +#[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")] +fn add_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'inner; + } + } +} + +#[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")] +fn change_break_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue; + } +} + +#[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")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: for _ in 0..1 { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'inner; + } + } +} + +#[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")] +fn change_continue_label() { + let mut _x = 0; + 'outer: for _ in 0..1 { + 'inner: for _ in 0..1 { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + continue; + } +} + +#[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")] +fn change_continue_to_break() { + let mut _x = 0; + for _ in 0..1 { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs new file mode 100644 index 000000000000..eaa5f68b98c4 --- /dev/null +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -0,0 +1,231 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `loop` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_body() { + let mut _x = 0; + loop { + _x = 2; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + } +} + +#[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")] +fn add_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: loop { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'inner; + } + } +} + +#[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")] +fn change_break_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue; + } +} + +#[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")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: loop { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'inner; + } + } +} + +#[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")] +fn change_continue_label() { + let mut _x = 0; + 'outer: loop { + 'inner: loop { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + continue; + } +} + +#[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")] +fn change_continue_to_break() { + let mut _x = 0; + loop { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs new file mode 100644 index 000000000000..405645bd1b84 --- /dev/null +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -0,0 +1,256 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while let` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_condition() { + let mut _x = 0; + while let Some(1u32) = None { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + } +} + +#[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")] +fn add_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'inner; + } + } +} + +#[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")] +fn change_break_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[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")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while let Some(0u32) = None { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'inner; + } + } +} + +#[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")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while let Some(0u32) = None { + 'inner: while let Some(0u32) = None { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + continue; + } +} + +#[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")] +fn change_continue_to_break() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs new file mode 100644 index 000000000000..f16611ee463e --- /dev/null +++ b/src/test/incremental/hashes/while_loops.rs @@ -0,0 +1,256 @@ +// 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. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for `while` loops. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_body() { + let mut _x = 0; + while true { + _x = 2; + break; + } +} + + + +// Change loop body ------------------------------------------------------------ +#[cfg(cfail1)] +fn change_loop_condition() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[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")] +fn change_loop_condition() { + let mut _x = 0; + while false { + _x = 1; + break; + } +} + + + +// Add break ------------------------------------------------------------------- +#[cfg(cfail1)] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + } +} + +#[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")] +fn add_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + + + +// Add loop label -------------------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + + + +// Add loop label to break ----------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break; + } +} + +#[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")] +fn add_loop_label_to_break() { + let mut _x = 0; + 'label: while true { + _x = 1; + break 'label; + } +} + + + +// Change break label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'inner; + } + } +} + +#[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")] +fn change_break_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + break 'outer; + } + } +} + + + +// Add loop label to continue -------------------------------------------------- +#[cfg(cfail1)] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue; + } +} + +#[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")] +fn add_loop_label_to_continue() { + let mut _x = 0; + 'label: while true { + _x = 1; + continue 'label; + } +} + + + +// Change continue label ---------------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'inner; + } + } +} + +#[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")] +fn change_continue_label() { + let mut _x = 0; + 'outer: while true { + 'inner: while true { + _x = 1; + continue 'outer; + } + } +} + + + +// Change continue to break ---------------------------------------------------- +#[cfg(cfail1)] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + continue; + } +} + +#[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")] +fn change_continue_to_break() { + let mut _x = 0; + while true { + _x = 1; + break; + } +} diff --git a/src/test/parse-fail/attr-bad-meta.rs b/src/test/parse-fail/attr-bad-meta.rs index 7def91da5eca..092adbf29e34 100644 --- a/src/test/parse-fail/attr-bad-meta.rs +++ b/src/test/parse-fail/attr-bad-meta.rs @@ -10,7 +10,7 @@ // compile-flags: -Z parse-only -// error-pattern:expected `]` +// error-pattern:expected one of `=` or `]` // asterisk is bogus #[attr*] diff --git a/src/test/parse-fail/circular_modules_hello.rs b/src/test/parse-fail/circular_modules_hello.rs index 4de817dbd9ca..94770aa875b4 100644 --- a/src/test/parse-fail/circular_modules_hello.rs +++ b/src/test/parse-fail/circular_modules_hello.rs @@ -12,6 +12,7 @@ // ignore-test: this is an auxiliary file for circular-modules-main.rs +#[path = "circular_modules_main.rs"] mod circular_modules_main; pub fn say_hello() { diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs index d2a16ac75070..d692bb519c14 100644 --- a/src/test/run-fail-fulldeps/qquote.rs +++ b/src/test/run-fail-fulldeps/qquote.rs @@ -19,8 +19,8 @@ extern crate syntax_pos; use syntax::ast; use syntax::codemap; -use syntax::parse; use syntax::print::pprust; +use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; fn main() { @@ -33,7 +33,7 @@ fn main() { cx.bt_push(syntax::codemap::ExpnInfo { call_site: DUMMY_SP, callee: syntax::codemap::NameAndSpan { - format: syntax::codemap::MacroBang(parse::token::intern("")), + format: syntax::codemap::MacroBang(Symbol::intern("")), allow_internal_unstable: false, span: None, } diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index ed127b017b6a..0336fe277c51 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -25,6 +25,7 @@ use rustc_driver::driver::{compile_input, CompileController, anon_src}; use rustc_metadata::cstore::CStore; use rustc_errors::registry::Registry; +use std::collections::HashSet; use std::path::PathBuf; use std::rc::Rc; @@ -65,7 +66,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) { fn compile(code: String, output: PathBuf, sysroot: PathBuf) { let (sess, cstore) = basic_sess(sysroot); - let cfg = build_configuration(&sess, vec![]); + let cfg = build_configuration(&sess, HashSet::new()); let control = CompileController::basic(); let input = Input::Str { name: anon_src(), input: code }; compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control); diff --git a/src/test/run-make/issue-37893/Makefile b/src/test/run-make/issue-37893/Makefile new file mode 100644 index 000000000000..27b69baf9778 --- /dev/null +++ b/src/test/run-make/issue-37893/Makefile @@ -0,0 +1,4 @@ +-include ../tools.mk + +all: + $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs diff --git a/src/test/run-make/issue-37893/a.rs b/src/test/run-make/issue-37893/a.rs new file mode 100644 index 000000000000..3dff45388c75 --- /dev/null +++ b/src/test/run-make/issue-37893/a.rs @@ -0,0 +1,13 @@ +// 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. + +#![feature(proc_macro)] +#![allow(unused)] +#![crate_type = "proc-macro"] diff --git a/src/test/compile-fail/auxiliary/issue_12612_1.rs b/src/test/run-make/issue-37893/b.rs similarity index 77% rename from src/test/compile-fail/auxiliary/issue_12612_1.rs rename to src/test/run-make/issue-37893/b.rs index a0234c1185a9..82f48f6d8d66 100644 --- a/src/test/compile-fail/auxiliary/issue_12612_1.rs +++ b/src/test/run-make/issue-37893/b.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,6 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub mod bar { - pub fn foo() {} -} +#![crate_type = "lib"] +#[macro_use] extern crate a; diff --git a/src/test/run-make/issue-37893/c.rs b/src/test/run-make/issue-37893/c.rs new file mode 100644 index 000000000000..eee55cc23696 --- /dev/null +++ b/src/test/run-make/issue-37893/c.rs @@ -0,0 +1,13 @@ +// 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. + +#![crate_type = "staticlib"] +extern crate b; +extern crate a; diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs index 48919fe876a2..664bb9da89a5 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs @@ -20,10 +20,10 @@ extern crate syntax; use proc_macro_tokens::build::ident_eq; +use syntax::ast::Ident; use syntax::ext::base::{ExtCtxt, MacResult}; use syntax::ext::proc_macro_shim::build_block_emitter; use syntax::tokenstream::{TokenTree, TokenStream}; -use syntax::parse::token::str_to_ident; use syntax::codemap::Span; use rustc_plugin::Registry; @@ -57,7 +57,7 @@ fn cond_rec(input: TokenStream) -> TokenStream { let test: TokenStream = clause.slice(0..1); let rhs: TokenStream = clause.slice_from(1..); - if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() { + if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() { qquote!({unquote(rhs)}) } else { qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } }) diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs index 0ea4cec75cdd..31a5f5968bab 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs @@ -26,7 +26,7 @@ use syntax::ast::Ident; use syntax::codemap::{DUMMY_SP, Span}; use syntax::ext::proc_macro_shim::build_block_emitter; use syntax::ext::base::{ExtCtxt, MacResult}; -use syntax::parse::token::{self, Token, DelimToken, keywords, str_to_ident}; +use syntax::parse::token::{self, Token, DelimToken}; use syntax::tokenstream::{TokenTree, TokenStream}; #[plugin_registrar] @@ -58,7 +58,7 @@ fn cond_rec(input: TokenStream) -> TokenStream { let test: TokenStream = clause.slice(0..1); let rhs: TokenStream = clause.slice_from(1..); - if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() { + if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() { qquote!({unquote(rhs)}) } else { qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } }) diff --git a/src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs index 169c96b43852..6a2d159a4bdd 100644 --- a/src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs @@ -52,7 +52,7 @@ fn cond_rec(input: TokenStream) -> TokenStream { let test: TokenStream = clause.slice(0..1); let rhs: TokenStream = clause.slice_from(1..); - if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() { + if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() { qquote!({unquote(rhs)}) } else { qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } }) diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs index e750d1fb1e3e..63dbd4d5bed0 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs @@ -10,7 +10,7 @@ // force-host -#![feature(plugin_registrar, rustc_private, item_like_imports)] +#![feature(plugin_registrar, rustc_private)] extern crate syntax; extern crate syntax_ext; @@ -25,12 +25,12 @@ use syntax::ast::*; use syntax::codemap::Span; use syntax::ext::base::*; use syntax::ext::build::AstBuilder; -use syntax::parse::token::{intern, InternedString}; +use syntax::symbol::Symbol; use syntax::ptr::P; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension(intern("derive_CustomPartialEq"), + reg.register_syntax_extension(Symbol::intern("derive_CustomPartialEq"), MultiDecorator(Box::new(expand_deriving_partial_eq))); } @@ -52,7 +52,7 @@ fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, it substr) } - let inline = cx.meta_word(span, InternedString::new("inline")); + let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let methods = vec![MethodDef { name: "eq", diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs index 6b688b006bd4..07f7d6bad7bf 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs @@ -23,7 +23,7 @@ extern crate rustc_plugin; use syntax::ast; use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax_ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure}; use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self}; use syntax_pos::Span; @@ -32,7 +32,7 @@ use rustc_plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension( - token::intern("derive_TotalSum"), + Symbol::intern("derive_TotalSum"), MultiDecorator(box expand)); } @@ -66,7 +66,7 @@ fn expand(cx: &mut ExtCtxt, |cx, span, subexpr, field, _| { cx.expr_binary(span, ast::BinOpKind::Add, subexpr, cx.expr_method_call(span, field, - token::str_to_ident("total_sum"), vec![])) + ast::Ident::from_str("total_sum"), vec![])) }, zero, box |cx, span, _, _| { cx.span_bug(span, "wtf??"); }, diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs index 6b58fee15758..50b16a0e26fb 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs @@ -23,7 +23,7 @@ extern crate rustc_plugin; use syntax::ast; use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable}; use syntax::ext::build::AstBuilder; -use syntax::parse::token; +use syntax::symbol::Symbol; use syntax::ptr::P; use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure}; use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching}; @@ -34,7 +34,7 @@ use rustc_plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension( - token::intern("derive_TotalSum"), + Symbol::intern("derive_TotalSum"), MultiDecorator(box expand)); } diff --git a/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs index 8ea131da338c..8647797270f9 100644 --- a/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs @@ -36,7 +36,7 @@ impl LintPass for Pass { impl EarlyLintPass for Pass { fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { - if it.ident.name.as_str() == "lintme" { + if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } } diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs index 7257444ee870..29cc6b7db947 100644 --- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs @@ -23,6 +23,7 @@ use syntax::ext::base::*; use syntax::ext::quote::rt::ToTokens; use syntax::parse::{self, token}; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax::tokenstream::TokenTree; use syntax_pos::Span; use rustc_plugin::Registry; @@ -36,15 +37,15 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_macro("make_a_1", expand_make_a_1); reg.register_macro("identity", expand_identity); reg.register_syntax_extension( - token::intern("into_multi_foo"), + Symbol::intern("into_multi_foo"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiModifier(Box::new(expand_into_foo_multi))); reg.register_syntax_extension( - token::intern("duplicate"), + Symbol::intern("duplicate"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_duplicate))); reg.register_syntax_extension( - token::intern("caller"), + Symbol::intern("caller"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. MultiDecorator(Box::new(expand_caller))); } @@ -108,9 +109,9 @@ fn expand_duplicate(cx: &mut ExtCtxt, it: &Annotatable, push: &mut FnMut(Annotatable)) { let copy_name = match mi.node { - ast::MetaItemKind::List(_, ref xs) => { + ast::MetaItemKind::List(ref xs) => { if let Some(word) = xs[0].word() { - token::str_to_ident(&word.name()) + ast::Ident::with_empty_ctxt(word.name()) } else { cx.span_err(mi.span, "Expected word"); return; @@ -179,7 +180,7 @@ fn expand_caller(cx: &mut ExtCtxt, } let fn_name = match list[0].name() { - Some(name) => token::str_to_ident(&name), + Some(name) => ast::Ident::with_empty_ctxt(name), None => cx.span_fatal(list[0].span(), "First parameter must be an ident.") }; diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs index f21c914a76c9..ba2af77cdb29 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin_args.rs @@ -22,9 +22,9 @@ use std::borrow::ToOwned; use syntax::ast; use syntax::ext::build::AstBuilder; use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager, NormalTT}; -use syntax::parse::token; use syntax::print::pprust; use syntax::ptr::P; +use syntax::symbol::Symbol; use syntax_pos::Span; use syntax::tokenstream; use rustc_plugin::Registry; @@ -40,15 +40,14 @@ impl TTMacroExpander for Expander { _: &[tokenstream::TokenTree]) -> Box { let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i)) .collect::>().join(", "); - let interned = token::intern_and_get_ident(&args[..]); - MacEager::expr(ecx.expr_str(sp, interned)) + MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args))) } } #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { let args = reg.args().to_owned(); - reg.register_syntax_extension(token::intern("plugin_args"), + reg.register_syntax_extension(Symbol::intern("plugin_args"), // FIXME (#22405): Replace `Box::new` with `box` here when/if possible. NormalTT(Box::new(Expander { args: args, }), None, false)); } diff --git a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs index 9fce19f46f65..f97fb04aadf6 100644 --- a/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs +++ b/src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs @@ -18,18 +18,19 @@ use proc_macro_tokens::prelude::*; use rustc_plugin::Registry; use syntax::ext::base::SyntaxExtension; use syntax::ext::proc_macro_shim::prelude::*; +use syntax::symbol::Symbol; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension(token::intern("attr_tru"), + reg.register_syntax_extension(Symbol::intern("attr_tru"), SyntaxExtension::AttrProcMacro(Box::new(attr_tru))); - reg.register_syntax_extension(token::intern("attr_identity"), + reg.register_syntax_extension(Symbol::intern("attr_identity"), SyntaxExtension::AttrProcMacro(Box::new(attr_identity))); - reg.register_syntax_extension(token::intern("tru"), + reg.register_syntax_extension(Symbol::intern("tru"), SyntaxExtension::ProcMacro(Box::new(tru))); - reg.register_syntax_extension(token::intern("ret_tru"), + reg.register_syntax_extension(Symbol::intern("ret_tru"), SyntaxExtension::ProcMacro(Box::new(ret_tru))); - reg.register_syntax_extension(token::intern("identity"), + reg.register_syntax_extension(Symbol::intern("identity"), SyntaxExtension::ProcMacro(Box::new(identity))); } diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 6ac0d5ad1a3b..2b3857048f36 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -18,8 +18,8 @@ extern crate syntax_pos; extern crate rustc; extern crate rustc_plugin; -use syntax::parse::token::{str_to_ident, NtExpr, NtPat}; -use syntax::ast::{Pat}; +use syntax::parse::token::{NtExpr, NtPat}; +use syntax::ast::{Ident, Pat}; use syntax::tokenstream::{TokenTree}; use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; @@ -44,12 +44,12 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) } }; - let matched_nt = match *map[&str_to_ident("matched")] { + let matched_nt = match *map[&Ident::from_str("matched")] { MatchedNonterminal(ref nt) => nt.clone(), _ => unreachable!(), }; - let mac_expr = match (&*matched_nt, &*map[&str_to_ident("pat")]) { + let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) { (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { let pats: Vec> = pats.iter().map(|pat_nt| { match **pat_nt { diff --git a/src/test/run-pass-fulldeps/macro-quote-1.rs b/src/test/run-pass-fulldeps/macro-quote-1.rs index 914da3f74677..948b20c14771 100644 --- a/src/test/run-pass-fulldeps/macro-quote-1.rs +++ b/src/test/run-pass-fulldeps/macro-quote-1.rs @@ -18,9 +18,6 @@ extern crate proc_macro_tokens; use proc_macro_tokens::prelude::*; extern crate syntax; -use syntax::ast::Ident; -use syntax::codemap::DUMMY_SP; -use syntax::parse::token::{self, Token, keywords, str_to_ident}; fn main() { let lex_true = lex("true"); diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 7c0c24163fe6..b4ed57192ccf 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -16,7 +16,7 @@ extern crate syntax; extern crate syntax_pos; use syntax::print::pprust::*; -use syntax::parse::token::intern; +use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; fn main() { @@ -29,7 +29,7 @@ fn main() { cx.bt_push(syntax::codemap::ExpnInfo { call_site: DUMMY_SP, callee: syntax::codemap::NameAndSpan { - format: syntax::codemap::MacroBang(intern("")), + format: syntax::codemap::MacroBang(Symbol::intern("")), allow_internal_unstable: false, span: None, } @@ -97,7 +97,7 @@ fn main() { // quote_meta_item! let meta = quote_meta_item!(cx, cfg(foo = "bar")); - check!(meta_item_to_string, meta, *quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#); + check!(meta_item_to_string, meta, quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#); let attr = quote_attr!(cx, #![$meta]); check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#); diff --git a/src/test/run-pass/auxiliary/rmeta_rlib.rs b/src/test/run-pass/auxiliary/rmeta_rlib.rs new file mode 100644 index 000000000000..28c11315fa1c --- /dev/null +++ b/src/test/run-pass/auxiliary/rmeta_rlib.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type="rlib"] +#![crate_name="rmeta_aux"] + +pub struct Foo { + pub field: i32, +} diff --git a/src/test/run-pass/auxiliary/rmeta_rmeta.rs b/src/test/run-pass/auxiliary/rmeta_rmeta.rs new file mode 100644 index 000000000000..394845b66f3d --- /dev/null +++ b/src/test/run-pass/auxiliary/rmeta_rmeta.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type="metadata"] +#![crate_name="rmeta_aux"] + +pub struct Foo { + pub field2: i32, +} diff --git a/src/test/run-pass/imports.rs b/src/test/run-pass/imports.rs index 195b99c9788e..f845a2ee5716 100644 --- a/src/test/run-pass/imports.rs +++ b/src/test/run-pass/imports.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(item_like_imports)] #![allow(unused)] // Like other items, private imports can be imported and used non-lexically in paths. diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs new file mode 100644 index 000000000000..6a5e051c0c73 --- /dev/null +++ b/src/test/run-pass/loop-break-value.rs @@ -0,0 +1,133 @@ +// 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. + +#![feature(loop_break_value)] +#![feature(never_type)] + +#[allow(unused)] +fn never_returns() { + loop { + break loop {}; + } +} + +pub fn main() { + let value = 'outer: loop { + if 1 == 1 { + break 13; + } else { + let _never: ! = loop { + break loop { + break 'outer panic!(); + } + }; + } + }; + assert_eq!(value, 13); + + let x = [1, 3u32, 5]; + let y = [17]; + let z = []; + let coerced: &[_] = loop { + match 2 { + 1 => break &x, + 2 => break &y, + 3 => break &z, + _ => (), + } + }; + assert_eq!(coerced, &[17u32]); + + let trait_unified = loop { + break if true { + break Default::default() + } else { + break [13, 14] + }; + }; + assert_eq!(trait_unified, [0, 0]); + + let trait_unified_2 = loop { + if false { + break [String::from("Hello")] + } else { + break Default::default() + }; + }; + assert_eq!(trait_unified_2, [""]); + + let trait_unified_3 = loop { + break if false { + break [String::from("Hello")] + } else { + ["Yes".into()] + }; + }; + assert_eq!(trait_unified_3, ["Yes"]); + + let regular_break = loop { + if true { + break; + } else { + break break Default::default(); + } + }; + assert_eq!(regular_break, ()); + + let regular_break_2 = loop { + if true { + break Default::default(); + } else { + break; + } + }; + assert_eq!(regular_break_2, ()); + + let regular_break_3 = loop { + break if true { + Default::default() + } else { + break; + } + }; + assert_eq!(regular_break_3, ()); + + let regular_break_4 = loop { + break (); + break; + }; + assert_eq!(regular_break_4, ()); + + let regular_break_5 = loop { + break; + break (); + }; + assert_eq!(regular_break_5, ()); + + let nested_break_value = 'outer2: loop { + let _a: u32 = 'inner: loop { + if true { + break 'outer2 "hello"; + } else { + break 'inner 17; + } + }; + panic!(); + }; + assert_eq!(nested_break_value, "hello"); + + let break_from_while_cond = loop { + while break { + panic!(); + } + break 123; + }; + assert_eq!(break_from_while_cond, 123); +} diff --git a/src/test/compile-fail/import-shadow-1.rs b/src/test/run-pass/rmeta.rs similarity index 52% rename from src/test/compile-fail/import-shadow-1.rs rename to src/test/run-pass/rmeta.rs index 503fa4eca527..11684d8663af 100644 --- a/src/test/compile-fail/import-shadow-1.rs +++ b/src/test/run-pass/rmeta.rs @@ -1,4 +1,4 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,23 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that import shadowing using globs causes errors +// Test that using rlibs and rmeta dep crates work together. Specifically, that +// there can be both an rmeta and an rlib file and rustc will prefer the rlib. -#![no_implicit_prelude] +// aux-build:rmeta_rmeta.rs +// aux-build:rmeta_rlib.rs -use foo::*; -use bar::*; //~ERROR a type named `Baz` has already been imported in this module +extern crate rmeta_aux; +use rmeta_aux::Foo; -mod foo { - pub type Baz = isize; +pub fn main() { + let _ = Foo { field: 42 }; } - -mod bar { - pub type Baz = isize; -} - -mod qux { - pub use bar::Baz; -} - -fn main() {}