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
dependencies = [
"build_helper 0.1.0",
"gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_bitflags 0.0.0",
]
[[package]]
"log 0.0.0",
"rustc 0.0.0",
"rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
"rustc_const_eval 0.0.0",
"rustc_const_math 0.0.0",
"rustc_data_structures 0.0.0",
-Subproject commit 3bc0272cab9fdcfc2ef4df9625ec3c9d5909db79
+Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
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.
[**The Rust Reference**][ref]. While Rust does not have a
specification, the reference tries to describe its working in
-detail. It tends to be out of date.
+detail. It is accurate, but not necessarily complete.
[**Standard Library API Reference**][api]. Documentation for the
standard library.
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
# 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:
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:
subprocess.run(["curl", "-O", f], check=True)
return open(os.path.basename(f))
+Codepoint = namedtuple('Codepoint', 'value class_')
+
+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/notes/tn36/Categories.txt")
+ file = get_file("http://www.unicode.org/Public/UNIDATA/UnicodeData.txt")
- dictionary = {int(line.split()[0], 16): line.split()[1] for line in file}
+ codepoints = get_codepoints(file)
CUTOFF=0x10000
singletons0 = []
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:
#![cfg_attr(not(test), feature(char_escape_debug))]
#![feature(core_intrinsics)]
#![feature(dropck_parametricity)]
+#![feature(exact_size_is_empty)]
#![feature(fmt_internals)]
#![feature(fused)]
#![feature(heap_api)]
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for IntoIter<T> {}
+impl<T> ExactSizeIterator for IntoIter<T> {
+ fn is_empty(&self) -> bool {
+ self.ptr == self.end
+ }
+}
#[unstable(feature = "fused", issue = "35602")]
impl<T> FusedIterator for IntoIter<T> {}
#[stable(feature = "drain", since = "1.6.0")]
-impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
+impl<'a, T> ExactSizeIterator for Drain<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.iter.is_empty()
+ }
+}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for Drain<'a, T> {}
#![feature(const_fn)]
#![feature(dedup_by)]
#![feature(enumset)]
+#![feature(exact_size_is_empty)]
#![feature(pattern)]
#![feature(rand)]
#![feature(repeat_str)]
assert_eq!(it.next(), jt.next());
}
+#[test]
+fn test_iter_is_empty() {
+ let xs = [1, 2, 5, 10, 11];
+ for i in 0..xs.len() {
+ for j in i..xs.len() {
+ assert_eq!(xs[i..j].iter().is_empty(), xs[i..j].is_empty());
+ }
+ }
+}
+
#[test]
fn test_mut_iterator() {
let mut xs = [1, 2, 3, 4, 5];
pos += 1;
}
assert_eq!(pos, v.len());
+ assert_eq!(s.chars().count(), v.len());
}
#[test]
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";
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";
// 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 {
} 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 {
0x38b,
0x38d,
0x3a2,
+ 0x530,
0x557,
0x558,
0x560,
0x588,
+ 0x58b,
+ 0x58c,
0x590,
0x61c,
0x61d,
0x83f,
0x85c,
0x85d,
- 0x8a1,
- 0x8ff,
- 0x978,
- 0x980,
+ 0x8b5,
+ 0x8e2,
0x984,
0x98d,
0x98e,
0xc0d,
0xc11,
0xc29,
- 0xc34,
0xc45,
0xc49,
0xc57,
0xc64,
0xc65,
- 0xc80,
- 0xc81,
0xc84,
0xc8d,
0xc91,
0xdbf,
0xdd5,
0xdd7,
+ 0xdf0,
+ 0xdf1,
0xe83,
0xe85,
0xe86,
0x1317,
0x135b,
0x135c,
+ 0x13f6,
+ 0x13f7,
+ 0x13fe,
+ 0x13ff,
0x1680,
0x170d,
0x176d,
0x17df,
0x180e,
0x180f,
+ 0x191f,
0x196e,
0x196f,
0x1a1c,
0x1a5f,
0x1a7d,
0x1a7e,
+ 0x1aae,
+ 0x1aaf,
+ 0x1cf7,
0x1f16,
0x1f17,
0x1f1e,
0x2072,
0x2073,
0x208f,
- 0x2700,
+ 0x23ff,
+ 0x2b74,
+ 0x2b75,
+ 0x2b96,
+ 0x2b97,
+ 0x2bc9,
0x2c2f,
0x2c5f,
0x2d26,
0x318f,
0x321f,
0x32ff,
- 0xa78f,
+ 0xa7af,
+ 0xa8fe,
+ 0xa8ff,
0xa9ce,
+ 0xa9ff,
0xaa4e,
0xaa4f,
0xaa5a,
0xab0f,
0xab10,
0xab27,
+ 0xab2f,
0xabee,
0xabef,
0xfa6e,
0x3e,
0x4e,
0x4f,
- 0x31f,
+ 0x18f,
0x39e,
0x49e,
0x49f,
0x83d,
0x83e,
0x856,
+ 0x8f3,
+ 0x9d0,
+ 0x9d1,
0xa04,
0xa14,
0xa18,
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,
0xd6a7,
0xd7cc,
0xd7cd,
+ 0xdaa0,
+ 0xe007,
+ 0xe019,
+ 0xe01a,
+ 0xe022,
+ 0xe025,
+ 0xe8c5,
+ 0xe8c6,
0xee04,
0xee20,
0xee23,
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,
0xa5f, 0x7,
0xa76, 0xb,
0xad1, 0xf,
- 0xaf2, 0xf,
+ 0xaf2, 0x7,
+ 0xafa, 0x7,
0xb4e, 0x8,
0xb58, 0x4,
0xb78, 0xa,
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,
0x10c8, 0x5,
0x137d, 0x3,
0x139a, 0x6,
- 0x13f5, 0xb,
0x169d, 0x3,
- 0x16f1, 0xf,
+ 0x16f9, 0x7,
0x1715, 0xb,
0x1737, 0x9,
0x1754, 0xc,
0x1878, 0x8,
0x18ab, 0x5,
0x18f6, 0xa,
- 0x191d, 0x3,
0x192c, 0x4,
0x193c, 0x4,
0x1941, 0x3,
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,
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,
0xfd40, 0x10,
0xfdc8, 0x28,
0xfe1a, 0x6,
- 0xfe27, 0x9,
0xfe6c, 0x4,
0xfefd, 0x4,
0xffbf, 0x3,
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,
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,
];
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Peekable<I: Iterator> {
iter: I,
- peeked: Option<I::Item>,
+ /// Remember a peeked value, even if it was None.
+ peeked: Option<Option<I::Item>>,
}
+// 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<I: Iterator> Iterator for Peekable<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<I::Item> {
- 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<I::Item> {
- 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<I::Item> {
- self.iter.last().or(self.peeked)
+ fn last(mut self) -> Option<I::Item> {
+ 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<usize>) {
+ 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)
}
}
#[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()
}
}
iterator!{struct Iter -> *const T, &'a T}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.ptr == self.end
+ }
+}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
iterator!{struct IterMut -> *mut T, &'a mut T}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+ fn is_empty(&self) -> bool {
+ self.ptr == self.end
+ }
+}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
})
}
+ #[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<usize>) {
let len = self.iter.len();
// `isize::MAX` (that's well below `usize::MAX`).
((len + 3) / 4, Some(len))
}
+
+ #[inline]
+ fn last(mut self) -> Option<char> {
+ // No need to go through the entire string.
+ self.next_back()
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
}
}
+ #[inline]
+ fn count(self) -> usize {
+ self.iter.count()
+ }
+
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
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")]
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');
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<T>(data: &[T]) -> CycleIter<T> {
+ CycleIter {
+ index: 0,
+ data: data,
+ }
+}
+
+impl<'a, T> Iterator for CycleIter<'a, T> {
+ type Item = &'a T;
+ fn next(&mut self) -> Option<Self::Item> {
+ 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]
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::*;
use std::{i16, f64};
use super::super::*;
-use core::num::flt2dec::*;
use core::num::flt2dec::strategy::grisu::*;
#[test]
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};
// ____________________________________________________________________________________________
} // 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)));
};
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));
// 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]));
/// 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_
}
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};
// ____________________________________________________________________________________________
build_paren_delimited(build_vec(build_token_tt(t))))
}
- pub fn emit_lit(l: token::Lit, n: Option<ast::Name>) -> TokenStream {
+ pub fn emit_lit(l: Lit, n: Option<ast::Name>) -> 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"),
};
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!"),
}
}
/// 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()
}
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;
/// 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()[..]))
}
// ____________________________________________________________________________________________
expr_exit
}
- hir::ExprLoop(ref body, _) => {
+ hir::ExprLoop(ref body, _, _) => {
//
// [pred]
// |
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()
}
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) |
}
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) => {
}
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])
}
None => continue,
};
- let (message, label) = match &*name {
+ let (message, label) = match &*name.as_str() {
"C" => {
conflicting_reprs += 1;
if target != Target::Struct &&
}
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),
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);
}
}
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) => {
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;
}
fn str_to_ident(&self, s: &'static str) -> Name {
- token::gensym(s)
+ Symbol::gensym(s)
}
fn with_parent_def<T, F>(&mut self, parent_id: NodeId, f: F) -> T
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)),
}
}
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))
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,
}
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(),
})
// 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 {
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),
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,
}
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);
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)),
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) => {
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"),
}
})
}
- 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)
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(),
})
}
- fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
- P(hir::Expr {
+ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
+ hir::Expr {
id: e.id,
node: match e.node {
// Issue #22181:
//
// 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`
// 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");
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| {
// let placer = <placer_expr> ;
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)
};
// 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)
// 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,
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],
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) => {
}
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
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![],
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)
}
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<Expr>)]) -> P<hir::Expr> {
+ fields: &[(&str, &P<Expr>)]) -> hir::Expr {
let struct_path = this.std_path(ast_expr.span,
&iter::once(&"ops").chain(path)
.map(|s| *s)
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();
});
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(),
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::<Vec<_>>(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::<Vec<_>>(ex.attrs.into());
+ ex.attrs = attrs;
+ return ex;
}
// Desugar ExprIfLet
// `<pat> => <body>`
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 <else_opt_if_cond> => <else_opt_if_body>,]`
- 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 {
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))
}
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,
// `<pat> => <body>`
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)
};
// `match <sub_expr> { ... }`
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,
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
// `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,
&["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
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());
}
// { Carrier::translate( { <expr> } ) }
let discr = {
// expand <expr>
- 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,
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)
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)
},
span: e.span,
attrs: e.attrs.clone(),
- })
+ }
}
fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
},
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,
}
}
}
fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
- 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<hir::Expr>, args: hir::HirVec<P<hir::Expr>>)
- -> P<hir::Expr> {
+ fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr>)
+ -> hir::Expr {
self.expr(span, hir::ExprCall(e, args), ThinVec::new())
}
- fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P<hir::Expr> {
+ 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());
expr
}
- fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
+ fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
}
fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
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
}
arg: P<hir::Expr>,
arms: hir::HirVec<hir::Arm>,
source: hir::MatchSource)
- -> P<hir::Expr> {
+ -> hir::Expr {
self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
}
- fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
+ fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> hir::Expr {
self.expr(b.span, hir::ExprBlock(b), attrs)
}
- fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>) -> P<hir::Expr> {
- self.expr(sp, hir::ExprTup(exprs), ThinVec::new())
+ fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr> {
+ P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
}
fn expr_struct(&mut self,
e: Option<P<hir::Expr>>,
attrs: ThinVec<Attribute>) -> P<hir::Expr> {
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<Attribute>) -> P<hir::Expr> {
- P(hir::Expr {
+ fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> 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<hir::Expr>)
}
}
- fn block_expr(&mut self, expr: P<hir::Expr>) -> P<hir::Block> {
+ fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {
self.block_all(expr.span, hir::HirVec::new(), Some(expr))
}
fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<P<hir::Expr>>)
- -> P<hir::Block> {
- 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<hir::Pat>) -> P<hir::Pat> {
fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
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;
}
span: Span,
rule: hir::BlockCheckMode,
attrs: ThinVec<Attribute>)
- -> P<hir::Expr> {
+ -> hir::Expr {
let id = self.next_id();
let block = P(hir::Block {
rules: rule,
span: Span,
rule: hir::BlockCheckMode,
attrs: ThinVec<Attribute>)
- -> P<hir::Expr> {
+ -> hir::Expr {
let id = self.next_id();
let block = P(hir::Block {
rules: rule,
// 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;
// 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;
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> {
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()));
}
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));
}
}
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;
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,
}
pub fn deterministic_hash_to<H: Hasher>(&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);
}
}
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 |
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) |
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}}")
- }
-
- Misc => {
- InternedString::new("{{?}}")
- }
-
- ClosureExpr => {
- InternedString::new("{{closure}}")
- }
-
- StructCtor => {
- InternedString::new("{{constructor}}")
- }
-
- Initializer => {
- InternedString::new("{{initializer}}")
- }
+ InlinedRoot(_) => "{{inlined-root}}",
+
+ Impl => "{{impl}}",
+ Misc => "{{?}}",
+ ClosureExpr => "{{closure}}",
+ StructCtor => "{{constructor}}",
+ Initializer => "{{initializer}}",
+ ImplTrait => "{{impl-Trait}}",
+ };
- ImplTrait => {
- InternedString::new("{{impl-Trait}}")
- }
- }
+ Symbol::intern(s).as_str()
}
pub fn to_string(&self) -> String {
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);
// 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)
}
}
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;
/// A `box x` expression.
ExprBox(P<Expr>),
/// An array (`[a, b, c, d]`)
- ExprArray(HirVec<P<Expr>>),
+ ExprArray(HirVec<Expr>),
/// 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<Expr>, HirVec<P<Expr>>),
+ ExprCall(P<Expr>, HirVec<Expr>),
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
///
/// The `Spanned<Name>` is the identifier for the method name.
///
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
- ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<P<Expr>>),
+ ExprMethodCall(Spanned<Name>, HirVec<P<Ty>>, HirVec<Expr>),
/// A tuple (`(a, b, c ,d)`)
- ExprTup(HirVec<P<Expr>>),
+ ExprTup(HirVec<Expr>),
/// A binary operation (For example: `a + b`, `a * b`)
ExprBinary(BinOp, P<Expr>, P<Expr>),
/// A unary operation (For example: `!x`, `*x`)
/// Conditionless loop (can be exited with break, continue, or return)
///
/// `'label: loop { block }`
- ExprLoop(P<Block>, Option<Spanned<Name>>),
+ ExprLoop(P<Block>, Option<Spanned<Name>>, 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<Expr>, HirVec<Arm>, MatchSource),
/// A referencing operation (`&a` or `&mut a`)
ExprAddrOf(Mutability, P<Expr>),
/// A `break`, with an optional label to break
- ExprBreak(Option<Spanned<Name>>),
+ ExprBreak(Option<Spanned<Name>>, Option<P<Expr>>),
/// A `continue`, with an optional label
ExprAgain(Option<Spanned<Name>>),
/// A `return`, with an optional value to be returned
ExprRet(Option<P<Expr>>),
/// Inline assembly (from `asm!`), with its outputs and inputs.
- ExprInlineAsm(P<InlineAsm>, HirVec<P<Expr>>, HirVec<P<Expr>>),
+ ExprInlineAsm(P<InlineAsm>, HirVec<Expr>, HirVec<Expr>),
/// A struct or struct-like variant literal expression.
///
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,
#[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<InlineAsmOutput>,
- pub inputs: HirVec<InternedString>,
- pub clobbers: HirVec<InternedString>,
+ pub inputs: HirVec<Symbol>,
+ pub clobbers: HirVec<Symbol>,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect,
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;
self.end()
}
- pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> 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)
}
}
- fn print_call_post(&mut self, args: &[P<hir::Expr>]) -> io::Result<()> {
+ fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
self.popen()?;
self.commasep_exprs(Inconsistent, args)?;
self.pclose()
Ok(())
}
- fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> 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()
}
Ok(())
}
- fn print_expr_tup(&mut self, exprs: &[P<hir::Expr>]) -> 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<hir::Expr>]) -> 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)
}
fn print_expr_method_call(&mut self,
name: Spanned<ast::Name>,
tys: &[P<hir::Ty>],
- args: &[P<hir::Expr>])
+ args: &[hir::Expr])
-> io::Result<()> {
let base_args = &args[1..];
self.print_expr(&args[0])?;
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)?;
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)?;
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(":")?;
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")?;
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])?;
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()?;
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(())
})?;
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;
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);
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;
}
#![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)]
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"
}
"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)]
LIFETIME_UNDERSCORE,
SAFE_EXTERN_STATICS,
PATTERNS_IN_FNS_WITHOUT_BODY,
- EXTRA_REQUIREMENT_IN_IMPL
+ EXTRA_REQUIREMENT_IN_IMPL,
+ LEGACY_DIRECTORY_OWNERSHIP
)
}
}
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};
/// 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<Result<(InternedString, Level, Span), Span>> {
+pub fn gather_attrs(attrs: &[ast::Attribute]) -> Vec<Result<(ast::Name, Level, Span), Span>> {
let mut out = vec![];
for attr in attrs {
let r = gather_attr(attr);
out
}
-pub fn gather_attr(attr: &ast::Attribute)
- -> Vec<Result<(InternedString, Level, Span), Span>> {
+pub fn gather_attr(attr: &ast::Attribute) -> Vec<Result<(ast::Name, Level, Span), Span>> {
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 {
};
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
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))
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,
// 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;
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;
#[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)]
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<PathBuf> {
+ 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,
#[derive(Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct NativeLibrary {
pub kind: NativeLibraryKind,
- pub name: String,
- pub cfg: Option<P<ast::MetaItem>>,
+ pub name: Symbol,
+ pub cfg: Option<ast::MetaItem>,
}
/// The data we save and restore about an inlined item or method. This is not
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate>;
/// 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<DefId>;
fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>;
fn reachable_ids(&self, cnum: CrateNum) -> Vec<DefId>;
// utility functions
fn metadata_filename(&self) -> &str;
fn metadata_section_name(&self, target: &Target) -> &str;
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option<PathBuf>)>;
+ 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<CrateNum>;
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
bug!("panic_strategy")
}
fn extern_crate(&self, cnum: CrateNum) -> Option<ExternCrate> { 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<DefId>
{ bug!("plugin_registrar_fn") }
fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
// 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<PathBuf>)>
+ 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<CrateNum> { None }
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,
_ => (),
}
}
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,
// 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.
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;
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
self.delegate.consume(consume_id, consume_span, cmt, mode);
}
- fn consume_exprs(&mut self, exprs: &[P<hir::Expr>]) {
+ fn consume_exprs(&mut self, exprs: &[hir::Expr]) {
for expr in exprs {
self.consume_expr(&expr);
}
self.consume_exprs(inputs);
}
- hir::ExprBreak(..) |
hir::ExprAgain(..) |
hir::ExprLit(..) => {}
- hir::ExprLoop(ref blk, _) => {
+ hir::ExprLoop(ref blk, _, _) => {
self.walk_block(&blk);
}
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);
}
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) {
use util::nodemap::FxHashMap;
use syntax::ast;
-use syntax::parse::token::InternedString;
+use syntax::symbol::Symbol;
use hir::itemlikevisit::ItemLikeVisitor;
use hir;
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))
let span = self.ast_map.span(item.id);
span_err!(self.session, span, E0522,
"definition of an unknown language item: `{}`.",
- &value[..]);
+ value);
}
}
}
}
}
-pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
+pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
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),
_ => {}
}
}
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;
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(..) |
self.define_bindings_in_pat(&local.pat, succ)
}
- fn propagate_through_exprs(&mut self, exprs: &[P<Expr>], 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)
// 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)
}
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);
// 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")
}
}
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")
}
}
// 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) => {
} else {
succ
};
- let succ = self.propagate_through_exprs(&args[..], succ);
+ let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(&f, succ)
}
} 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() => {
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,
}
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;
}
terminating(then.id);
}
- hir::ExprLoop(ref body, _) => {
+ hir::ExprLoop(ref body, _, _) => {
terminating(body.id);
}
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;
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,
}
}
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};
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 {
// 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::<u64>(), stab_v.parse()) {
match dep_v.cmp(&stab_v) {
Ordering::Less => {
/// 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<InternedString, attr::StabilityLevel> {
+ -> FxHashMap<Symbol, attr::StabilityLevel> {
let _task = tcx.dep_graph.in_task(DepNode::StabilityCheck);
let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
struct Checker<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- active_features: FxHashSet<InternedString>,
- used_features: FxHashMap<InternedString, attr::StabilityLevel>,
+ active_features: FxHashSet<Symbol>,
+ used_features: FxHashMap<Symbol, attr::StabilityLevel>,
// Within a block where feature gate checking can be skipped.
in_skip_block: u32,
}
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);
}
}
// 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));
/// 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<InternedString,
+ lib_features_used: &FxHashMap<Symbol,
attr::StabilityLevel>) {
let ref declared_lib_features = sess.features.borrow().declared_lib_features;
- let mut remaining_lib_features: FxHashMap<InternedString, Span>
+ let mut remaining_lib_features: FxHashMap<Symbol, Span>
= declared_lib_features.clone().into_iter().collect();
fn format_stable_since_msg(version: &str) -> String {
}
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,
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 */ )
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;
verify(sess, items);
}
-pub fn link_name(attrs: &[ast::Attribute]) -> Option<InternedString> {
+pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> {
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
}
config::CrateTypeCdylib |
config::CrateTypeExecutable |
config::CrateTypeStaticlib => true,
- config::CrateTypeRlib => false,
+ config::CrateTypeRlib |
+ config::CrateTypeMetadata => false,
}
});
if !needs_check {
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)
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ty::AdtKind;
+use ty::layout::{Align, Size};
+
+use rustc_data_structures::fx::{FxHashSet};
+
+use std::cmp::{self, Ordering};
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct VariantInfo {
+ pub name: Option<String>,
+ pub kind: SizeKind,
+ pub size: u64,
+ pub align: u64,
+ pub fields: Vec<FieldInfo>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum SizeKind { Exact, Min }
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct FieldInfo {
+ pub name: String,
+ pub offset: u64,
+ pub size: u64,
+ pub align: u64,
+}
+
+impl From<AdtKind> for DataTypeKind {
+ fn from(kind: AdtKind) -> Self {
+ match kind {
+ AdtKind::Struct => DataTypeKind::Struct,
+ AdtKind::Enum => DataTypeKind::Enum,
+ AdtKind::Union => DataTypeKind::Union,
+ }
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum DataTypeKind {
+ Struct,
+ Union,
+ Enum,
+ Closure,
+}
+
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub struct TypeSizeInfo {
+ pub kind: DataTypeKind,
+ pub type_description: String,
+ pub align: u64,
+ pub overall_size: u64,
+ pub opt_discr_size: Option<u64>,
+ pub variants: Vec<VariantInfo>,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub struct CodeStats {
+ type_sizes: FxHashSet<TypeSizeInfo>,
+}
+
+impl CodeStats {
+ pub fn new() -> Self { CodeStats { type_sizes: FxHashSet() } }
+
+ pub fn record_type_size<S: ToString>(&mut self,
+ kind: DataTypeKind,
+ type_desc: S,
+ align: Align,
+ overall_size: Size,
+ opt_discr_size: Option<Size>,
+ variants: Vec<VariantInfo>) {
+ let info = TypeSizeInfo {
+ kind: kind,
+ type_description: type_desc.to_string(),
+ align: align.abi(),
+ overall_size: overall_size.bytes(),
+ opt_discr_size: opt_discr_size.map(|s| s.bytes()),
+ variants: variants,
+ };
+ self.type_sizes.insert(info);
+ }
+
+ pub fn print_type_sizes(&self) {
+ let mut sorted: Vec<_> = self.type_sizes.iter().collect();
+
+ // Primary sort: large-to-small.
+ // Secondary sort: description (dictionary order)
+ sorted.sort_by(|info1, info2| {
+ // (reversing cmp order to get large-to-small ordering)
+ match info2.overall_size.cmp(&info1.overall_size) {
+ Ordering::Equal => info1.type_description.cmp(&info2.type_description),
+ other => other,
+ }
+ });
+
+ for info in &sorted {
+ println!("print-type-size type: `{}`: {} bytes, alignment: {} bytes",
+ info.type_description, info.overall_size, info.align);
+ let indent = " ";
+
+ let discr_size = if let Some(discr_size) = info.opt_discr_size {
+ println!("print-type-size {}discriminant: {} bytes",
+ indent, discr_size);
+ discr_size
+ } else {
+ 0
+ };
+
+ // We start this at discr_size (rather than 0) because
+ // things like C-enums do not have variants but we still
+ // want the max_variant_size at the end of the loop below
+ // to reflect the presence of the discriminant.
+ let mut max_variant_size = discr_size;
+
+ let struct_like = match info.kind {
+ DataTypeKind::Struct | DataTypeKind::Closure => true,
+ DataTypeKind::Enum | DataTypeKind::Union => false,
+ };
+ for (i, variant_info) in info.variants.iter().enumerate() {
+ let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
+ let indent = if !struct_like {
+ let name = match name.as_ref() {
+ Some(name) => format!("{}", name),
+ None => format!("{}", i),
+ };
+ println!("print-type-size {}variant `{}`: {} bytes",
+ indent, name, size - discr_size);
+ " "
+ } else {
+ assert!(i < 1);
+ " "
+ };
+ max_variant_size = cmp::max(max_variant_size, size);
+
+ let mut min_offset = discr_size;
+ for field in fields {
+ let FieldInfo { ref name, offset, size, align } = *field;
+
+ // Include field alignment in output only if it caused padding injection
+ if min_offset != offset {
+ let pad = offset - min_offset;
+ println!("print-type-size {}padding: {} bytes",
+ indent, pad);
+ println!("print-type-size {}field `.{}`: {} bytes, alignment: {} bytes",
+ indent, name, size, align);
+ } else {
+ println!("print-type-size {}field `.{}`: {} bytes",
+ indent, name, size);
+ }
+
+ min_offset = offset + size;
+ }
+ }
+
+ assert!(max_variant_size <= info.overall_size,
+ "max_variant_size {} !<= {} overall_size",
+ max_variant_size, info.overall_size);
+ if max_variant_size < info.overall_size {
+ println!("print-type-size {}end padding: {} bytes",
+ indent, info.overall_size - max_variant_size);
+ }
+ }
+ }
+}
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};
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;
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 {
}
}
+#[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.
CrateTypeStaticlib,
CrateTypeCdylib,
CrateTypeProcMacro,
+ CrateTypeMetadata,
}
#[derive(Clone, Hash)]
"keep the AST after lowering it to HIR"),
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
"show spans for compiler debugging (expr|pat|ty)"),
+ print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
+ "print layout information for each type encountered"),
print_trans_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
"print the result of the translation item collection pass"),
mir_opt_level: Option<usize> = (None, parse_opt_uint, [TRACKED],
}
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;
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 {
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::<Vec<_>>();
- 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 {
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 \
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::<ast::CrateConfig>()
}
"cdylib" => CrateTypeCdylib,
"bin" => CrateTypeExecutable,
"proc-macro" => CrateTypeProcMacro,
+ "metadata" => CrateTypeMetadata,
_ => {
return Err(format!("unknown crate type: `{}`",
part));
CrateTypeStaticlib => "staticlib".fmt(f),
CrateTypeCdylib => "cdylib".fmt(f),
CrateTypeProcMacro => "proc-macro".fmt(f),
+ CrateTypeMetadata => "metadata".fmt(f),
}
}
}
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<OptGroup> {
super::rustc_optgroups().into_iter()
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
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());
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
+pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
+
use dep_graph::DepGraph;
use hir::def_id::{CrateNum, DefIndex};
use hir::svh::Svh;
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};
use std::time::Duration;
use libc::c_int;
+mod code_stats;
pub mod config;
pub mod filesearch;
pub mod search_paths;
// 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<token::InternedString>,
+ pub crate_disambiguator: RefCell<Symbol>,
pub features: RefCell<feature_gate::Features>,
/// The maximum recursion limit for potentially infinitely recursive
/// Some measurements that are being gathered during compilation.
pub perf_stats: PerfStats,
+ /// Data about code being compiled, gathered during compilation.
+ pub code_stats: RefCell<CodeStats>,
+
next_node_id: Cell<ast::NodeId>,
}
}
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<MultiSpan>>(&'a self,
sp: S,
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)),
incr_comp_hashes_count: Cell::new(0),
incr_comp_bytes_hashed: Cell::new(0),
symbol_hash_time: Cell::new(Duration::from_secs(0)),
- }
+ },
+ code_stats: RefCell::new(CodeStats::new()),
};
init_llvm(&sess);
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::<FxHashMap<String, String>>();
- let parser = Parser::new(&istring);
+ let parser = Parser::new(istring);
let mut errored = false;
let err: String = parser.filter_map(|p| {
match p {
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};
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
});
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;
/// 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,
/// Map from function to the `#[derive]` mode that it's defining. Only used
/// by `proc-macro` crates.
- pub derive_macros: RefCell<NodeMap<token::InternedString>>,
+ pub derive_macros: RefCell<NodeMap<Symbol>>,
}
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 {
}
}
- 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 {
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),
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;
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());
}
}
}
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;
}
cur_path.push(self.sess.cstore.def_key(cur_def)
.disambiguated_data.data.get_opt_name().unwrap_or_else(||
- token::intern("<unnamed>")));
+ Symbol::intern("<unnamed>")));
match visible_parent_map.get(&cur_def) {
Some(&def) => cur_def = def,
None => return false,
self.offsets.push(offset);
+ debug!("Struct::extend offset: {:?} field: {:?} {:?}", offset, field, field.size(dl));
offset = offset.checked_add(field.size(dl), dl)
.map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?;
}
+ debug!("Struct::extend min_size: {:?}", offset);
+
self.min_size = offset;
Ok(())
index, scapegoat);
}
+ debug!("Union::extend field: {:?} {:?}", field, field.size(dl));
+
if !self.packed {
self.align = self.align.max(field.align(dl));
}
self.min_size = cmp::max(self.min_size, field.size(dl));
}
+ debug!("Union::extend min-size: {:?}", self.min_size);
+
Ok(())
}
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
use util::nodemap::NodeSet;
-use util::nodemap::FxHashMap;
+use util::nodemap::{FxHashMap, FxHashSet};
use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
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;
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
use hir;
use hir::itemlikevisit::ItemLikeVisitor;
impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
+impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> {
+ #[inline]
+ pub fn is_uninhabited_recurse(&'tcx self,
+ visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ block: Option<NodeId>,
+ cx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>) -> bool {
+ if !visited.insert((self.did, substs)) {
+ return false;
+ };
+ self.variants.iter().all(|v| {
+ v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union())
+ })
+ }
+}
+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Union, Enum }
self.variants.iter().flat_map(VariantDefData::fields_iter)
}
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.variants.is_empty()
- }
-
#[inline]
pub fn is_univariant(&self) -> bool {
self.variants.len() == 1
}
}
+impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> {
+ #[inline]
+ pub fn is_uninhabited_recurse(&'tcx self,
+ visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ block: Option<NodeId>,
+ cx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>,
+ is_union: bool) -> bool {
+ if is_union {
+ self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
+ } else {
+ self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, cx, substs))
+ }
+ }
+}
+
impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
pub fn new(did: DefId,
name: Name,
}
}
+impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> {
+ #[inline]
+ pub fn is_uninhabited_recurse(&'tcx self,
+ visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ block: Option<NodeId>,
+ tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ substs: &'tcx Substs<'tcx>) -> bool {
+ block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) &&
+ self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
+ }
+}
+
/// Records the substitutions used to translate the polytype for an
/// item into the monotype of an item reference.
#[derive(Clone, RustcEncodable, RustcDecodable)]
/// Iterator that walks the immediate children of `self`. Hence
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
/// (but not `i32`, like `walk`).
- pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+ pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
walk::walk_shallow(self)
}
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.
/// 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<Span, InternedString> {
+ pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
if impl_did.is_local() {
let node_id = self.map.as_local_node_id(impl_did).unwrap();
Ok(self.map.span(node_id))
use std::fmt;
use std::ops;
use syntax::abi;
-use syntax::ast::{self, Name};
-use syntax::parse::token::{keywords, InternedString};
+use syntax::ast::{self, Name, NodeId};
+use syntax::symbol::{keywords, InternedString};
+use util::nodemap::FxHashSet;
use serialize;
}
}
- pub fn is_uninhabited(&self, _cx: TyCtxt) -> bool {
- // FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
- // more complete.
+ /// Checks whether a type is uninhabited.
+ /// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`.
+ pub fn is_uninhabited(&self, block: Option<NodeId>, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+ let mut visited = FxHashSet::default();
+ self.is_uninhabited_recurse(&mut visited, block, cx)
+ }
+
+ pub fn is_uninhabited_recurse(&self,
+ visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ block: Option<NodeId>,
+ cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
match self.sty {
- TyAdt(def, _) => def.is_empty(),
+ TyAdt(def, substs) => {
+ def.is_uninhabited_recurse(visited, block, cx, substs)
+ },
- // FIXME(canndrew): There's no reason why these can't be uncommented, they're tested
- // and they don't break anything. But I'm keeping my changes small for now.
- //TyNever => true,
- //TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)),
+ TyNever => true,
+ TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, block, cx)),
+ TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, block, cx),
+ TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, block, cx),
- // FIXME(canndrew): this line breaks core::fmt
- //TyRef(_, ref tm) => tm.ty.is_uninhabited(cx),
_ => false,
}
}
//! WARNING: this does not keep track of the region depth.
use ty::{self, Ty};
-use std::iter::Iterator;
-use std::vec::IntoIter;
+use rustc_data_structures::small_vec::SmallVec;
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+
+// The TypeWalker's stack is hot enough that it's worth going to some effort to
+// avoid heap allocations.
+pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8];
+pub type TypeWalkerStack<'tcx> = SmallVec<TypeWalkerArray<'tcx>>;
pub struct TypeWalker<'tcx> {
- stack: Vec<Ty<'tcx>>,
+ stack: TypeWalkerStack<'tcx>,
last_subtree: usize,
}
impl<'tcx> TypeWalker<'tcx> {
pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
- TypeWalker { stack: vec![ty], last_subtree: 1, }
+ TypeWalker { stack: SmallVec::one(ty), last_subtree: 1, }
}
/// Skips the subtree of types corresponding to the last type
}
}
-pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
- let mut stack = vec![];
+pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
+ let mut stack = SmallVec::new();
push_subtypes(&mut stack, ty);
stack.into_iter()
}
// known to be significant to any code, but it seems like the
// natural order one would expect (basically, the order of the
// types as they are written).
-fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
+fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
match parent_ty.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
}
}
-fn push_sig_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, sig: &ty::PolyFnSig<'tcx>) {
+fn push_sig_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, sig: &ty::PolyFnSig<'tcx>) {
stack.push(sig.0.output);
stack.extend(sig.0.inputs.iter().cloned().rev());
}
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";
Indenter { _cannot_construct_outside_of_this_module: () }
}
-struct LoopQueryVisitor<P> where P: FnMut(&hir::Expr_) -> bool {
- p: P,
- flag: bool,
-}
-
-impl<'v, P> Visitor<'v> for LoopQueryVisitor<P> 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<P>(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<P> where P: FnMut(&hir::Expr) -> bool {
- p: P,
- flag: bool,
-}
-
-impl<'v, P> Visitor<'v> for BlockQueryVisitor<P> 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<P>(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;
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 {
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,
{
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));
}
}
use borrowck::BorrowckCtxt;
use syntax::ast::{self, MetaItem};
-use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP};
use rustc::hir;
use self::dataflow::{DefinitelyInitializedLvals};
use self::gather_moves::{MoveData, MovePathIndex, LookupResult};
-fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<P<MetaItem>> {
+fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
for attr in attrs {
if attr.check_name("rustc_mir") {
let items = attr.meta_item_list();
// Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = self.tcx.tables().node_id_to_type(scrut.id);
if inlined_arms.is_empty() {
- if !pat_ty.is_uninhabited(self.tcx) {
+ if !pat_ty.is_uninhabited(Some(scrut.id), self.tcx) {
// We know the type is inhabited, so this must be wrong
let mut err = create_e0004(self.tcx.sess, span,
format!("non-exhaustive patterns: type {} \
_ => 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::<Result<_, _>>()?;
PatKind::TupleStruct(path, pats, None)
}
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)) => {
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)),
self.set_len(len + 1);
}
}
+
+ pub fn truncate(&mut self, len: usize) {
+ unsafe {
+ while len < self.len() {
+ // Decrement len before the drop_in_place(), so a panic on Drop
+ // doesn't re-drop the just-failed value.
+ let newlen = self.len() - 1;
+ self.set_len(newlen);
+ ::std::ptr::drop_in_place(self.get_unchecked_mut(newlen));
+ }
+ }
+ }
}
impl<A: Array> Deref for SmallVec<A> {
}
pub fn probe(&mut self, a_id: K) -> Option<V> {
- self.get(a_id).value.clone()
+ self.get(a_id).value
}
pub fn unsolved_variables(&mut self) -> Vec<K> {
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;
tcx.print_debug_stats();
}
- // Discard interned strings as they are no longer required.
- token::clear_ident_interner();
-
Ok((outputs, trans))
})??
};
+ if sess.opts.debugging_opts.print_type_sizes {
+ sess.code_stats.borrow().print_type_sizes();
+ }
+
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
controller_entry_point!(after_llvm,
*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);
let crate_types = sess.crate_types.borrow();
let num_crate_types = crate_types.len();
let is_proc_macro_crate = crate_types.contains(&config::CrateTypeProcMacro);
+ let is_test_crate = sess.opts.test;
syntax_ext::proc_macro_registrar::modify(&sess.parse_sess,
&mut resolver,
krate,
is_proc_macro_crate,
+ is_test_crate,
num_crate_types,
sess.diagnostic(),
&sess.features.borrow())
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",
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 {
Some(ref n) if *n == "rlib" => {
Some(config::CrateTypeRlib)
}
+ Some(ref n) if *n == "metadata" => {
+ Some(config::CrateTypeMetadata)
+ }
Some(ref n) if *n == "dylib" => {
Some(config::CrateTypeDylib)
}
}
}
}
-
-// 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();
-}
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;
}
}
-fn check_cfg(cfg: &ast::CrateConfig,
- output: ErrorOutputType) {
- let emitter: Box<Emitter> = 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 {
return Compilation::Stop;
}
- check_cfg(cfg, output);
Compilation::Continue
}
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 => {
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(()),
}
// 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
_ => &[],
};
- 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]))));
}
}
}
if crt_static {
- cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static")));
+ cfg.insert((tf, Some(Symbol::intern("crt-static"))));
}
}
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;
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,
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};
}
type Sources = Vec<(Span, DefId, DepNode<DefId>)>;
-type Targets = Vec<(Span, InternedString, ast::NodeId, DepNode<DefId>)>;
+type Targets = Vec<(Span, ast::Name, ast::NodeId, DepNode<DefId>)>;
struct IfThisChanged<'a, 'tcx:'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
impl<'a, 'tcx> IfThisChanged<'a, 'tcx> {
- fn argument(&self, attr: &ast::Attribute) -> Option<InternedString> {
+ fn argument(&self, attr: &ast::Attribute) -> Option<ast::Name> {
let mut value = None;
for list_item in attr.meta_item_list().unwrap_or_default() {
match list_item.word() {
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(
} 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(
}
};
self.then_this_would_need.push((attr.span,
- dep_node_interned.clone().unwrap(),
+ dep_node_interned.unwrap(),
node_id,
dep_node));
}
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.
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;
// 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),
#[derive(Hash)]
enum SawExprComponent<'a> {
- SawExprLoop(Option<token::InternedString>),
- SawExprField(token::InternedString),
+ SawExprLoop(Option<InternedString>),
+ SawExprField(InternedString),
SawExprTupField(usize),
- SawExprBreak(Option<token::InternedString>),
- SawExprAgain(Option<token::InternedString>),
+ SawExprBreak(Option<InternedString>),
+ SawExprAgain(Option<InternedString>),
SawExprBox,
SawExprArray,
SawExprBinary(hir::BinOp_),
SawExprUnary(hir::UnOp),
SawExprLit(ast::LitKind),
+ SawExprLitStr(InternedString, ast::StrStyle),
+ SawExprLitFloat(InternedString, Option<ast::FloatTy>),
SawExprCast,
SawExprType,
SawExprIf,
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),
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),
}
}
+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,
// 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() {
self.hash_meta_item(meta_item);
}
ast::NestedMetaItemKind::Literal(ref lit) => {
- lit.node.hash(self.st);
+ saw_lit(lit).hash(self.st);
}
}
}
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);
}
}
}
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
}
}
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()
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;
}
impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
-
fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
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(
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));
}
}
&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 {
}
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
.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[..]);
}
.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));
}
}
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));
}
}
}
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};
stability: &Option<&attr::Stability>,
deprecation: &Option<stability::DeprecationEntry>) {
// 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) {
}
}
- 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<Symbol>) {
let msg = if let Some(note) = note {
format!("use of deprecated item: {}", note)
} else {
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,
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"
}
}
}
id: LintId::of(EXTRA_REQUIREMENT_IN_IMPL),
reference: "issue #37166 <https://github.com/rust-lang/rust/issues/37166>",
},
+ FutureIncompatibleInfo {
+ id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
+ reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
+ },
]);
// Register renamed and removed lints
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,
}
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;
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]);
}
// 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;
// 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]"
[features]
static-libstdcpp = []
-[dependencies]
-rustc_bitflags = { path = "../librustc_bitflags" }
-
[build-dependencies]
build_helper = { path = "../build_helper" }
gcc = "0.3.27"
cfg.flag("-DLLVM_RUSTLLVM");
}
+ println!("cargo:rerun-if-changed=../rustllvm/PassWrapper.cpp");
+ println!("cargo:rerun-if-changed=../rustllvm/RustWrapper.cpp");
+ println!("cargo:rerun-if-changed=../rustllvm/ArchiveWrapper.cpp");
cfg.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
DllExport = 2, // Function to be accessible from DLL.
}
-bitflags! {
- #[derive(Default, Debug)]
- flags Attribute : u64 {
- const ZExt = 1 << 0,
- const SExt = 1 << 1,
- const NoReturn = 1 << 2,
- const InReg = 1 << 3,
- const StructRet = 1 << 4,
- const NoUnwind = 1 << 5,
- const NoAlias = 1 << 6,
- const ByVal = 1 << 7,
- const Nest = 1 << 8,
- const ReadNone = 1 << 9,
- const ReadOnly = 1 << 10,
- const NoInline = 1 << 11,
- const AlwaysInline = 1 << 12,
- const OptimizeForSize = 1 << 13,
- const StackProtect = 1 << 14,
- const StackProtectReq = 1 << 15,
- const NoCapture = 1 << 21,
- const NoRedZone = 1 << 22,
- const NoImplicitFloat = 1 << 23,
- const Naked = 1 << 24,
- const InlineHint = 1 << 25,
- const ReturnsTwice = 1 << 29,
- const UWTable = 1 << 30,
- const NonLazyBind = 1 << 31,
-
- // Some of these are missing from the LLVM C API, the rest are
- // present, but commented out, and preceded by the following warning:
- // FIXME: These attributes are currently not included in the C API as
- // a temporary measure until the API/ABI impact to the C API is understood
- // and the path forward agreed upon.
- const SanitizeAddress = 1 << 32,
- const MinSize = 1 << 33,
- const NoDuplicate = 1 << 34,
- const StackProtectStrong = 1 << 35,
- const SanitizeThread = 1 << 36,
- const SanitizeMemory = 1 << 37,
- const NoBuiltin = 1 << 38,
- const Returned = 1 << 39,
- const Cold = 1 << 40,
- const Builtin = 1 << 41,
- const OptimizeNone = 1 << 42,
- const InAlloca = 1 << 43,
- const NonNull = 1 << 44,
- const JumpTable = 1 << 45,
- const Convergent = 1 << 46,
- const SafeStack = 1 << 47,
- const NoRecurse = 1 << 48,
- const InaccessibleMemOnly = 1 << 49,
- const InaccessibleMemOrArgMemOnly = 1 << 50,
- }
+/// Matches LLVMRustAttribute in rustllvm.h
+/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
+/// though it is not ABI compatible (since it's a C++ enum)
+#[repr(C)]
+#[derive(Copy, Clone, Debug)]
+pub enum Attribute {
+ AlwaysInline = 0,
+ ByVal = 1,
+ Cold = 2,
+ InlineHint = 3,
+ MinSize = 4,
+ Naked = 5,
+ NoAlias = 6,
+ NoCapture = 7,
+ NoInline = 8,
+ NonNull = 9,
+ NoRedZone = 10,
+ NoReturn = 11,
+ NoUnwind = 12,
+ OptimizeForSize = 13,
+ ReadOnly = 14,
+ SExt = 15,
+ StructRet = 16,
+ UWTable = 17,
+ ZExt = 18,
}
/// LLVMIntPredicate
/// See llvm::LLVMType::getContext.
pub fn LLVMGetTypeContext(Ty: TypeRef) -> ContextRef;
+ /// See llvm::Value::getContext
+ pub fn LLVMRustGetValueContext(V: ValueRef) -> ContextRef;
+
// Operations on integer types
pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef;
pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef;
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, PA: u64);
- pub fn LLVMRustAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
+ 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: u64);
- pub fn LLVMRustRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *const c_char);
- pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_uint;
- pub fn LLVMRemoveFunctionAttr(Fn: ValueRef, val: c_uint);
+ pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute);
// Operations on parameters
pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
pub fn LLVMGetLastParam(Fn: ValueRef) -> ValueRef;
pub fn LLVMGetNextParam(Arg: ValueRef) -> ValueRef;
pub fn LLVMGetPreviousParam(Arg: ValueRef) -> ValueRef;
- pub fn LLVMAddAttribute(Arg: ValueRef, PA: c_uint);
- pub fn LLVMRemoveAttribute(Arg: ValueRef, PA: c_uint);
- pub fn LLVMGetAttribute(Arg: ValueRef) -> c_uint;
pub fn LLVMSetParamAlignment(Arg: ValueRef, align: c_uint);
// Operations on basic blocks
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, Val: u64);
+ 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)
#![feature(staged_api)]
#![feature(linked_from)]
#![feature(concat_idents)]
-#![cfg_attr(not(stage0), feature(rustc_private))]
extern crate libc;
-#[macro_use]
-#[no_link]
-extern crate rustc_bitflags;
pub use self::IntPredicate::*;
pub use self::RealPredicate::*;
}
}
-#[derive(Copy, Clone, Default, Debug)]
-pub struct Attributes {
- regular: Attribute,
- dereferenceable_bytes: u64,
-}
-
-impl Attributes {
- pub fn set(&mut self, attr: Attribute) -> &mut Self {
- self.regular = self.regular | attr;
- self
- }
-
- pub fn unset(&mut self, attr: Attribute) -> &mut Self {
- self.regular = self.regular - attr;
- self
- }
-
- pub fn set_dereferenceable(&mut self, bytes: u64) -> &mut Self {
- self.dereferenceable_bytes = bytes;
- self
- }
-
- pub fn unset_dereferenceable(&mut self) -> &mut Self {
- self.dereferenceable_bytes = 0;
- self
- }
-
- pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
- unsafe {
- self.regular.apply_llfn(idx, llfn);
- if self.dereferenceable_bytes != 0 {
- LLVMRustAddDereferenceableAttr(llfn, idx.as_uint(), self.dereferenceable_bytes);
- }
- }
- }
-
- pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
- unsafe {
- self.regular.apply_callsite(idx, callsite);
- if self.dereferenceable_bytes != 0 {
- LLVMRustAddDereferenceableCallSiteAttr(callsite,
- idx.as_uint(),
- self.dereferenceable_bytes);
- }
- }
- }
-}
-
pub fn AddFunctionAttrStringValue(llfn: ValueRef,
idx: AttributePlace,
attr: &'static str,
AttributePlace::Argument(0)
}
- fn as_uint(self) -> c_uint {
+ pub fn as_uint(self) -> c_uint {
match self {
AttributePlace::Function => !0,
AttributePlace::Argument(i) => i,
impl Attribute {
pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
- unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), self.bits()) }
+ unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
}
pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
- unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), self.bits()) }
+ unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
}
pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
- unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), self.bits()) }
+ unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) }
}
pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) {
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,
}
cstore: &'a CStore,
next_crate_num: CrateNum,
foreign_item_map: FxHashMap<String, Vec<ast::NodeId>>,
- local_crate_name: String,
+ local_crate_name: Symbol,
}
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,
}
cstore: &CStore,
span: Option<Span>,
lib: NativeLibrary) {
- if lib.name.is_empty() {
+ if lib.name.as_str().is_empty() {
match span {
Some(span) => {
struct_span_err!(sess, span, E0454,
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),
}
}
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") {
}
}
- fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
+ fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind)
-> Option<CrateNum> {
let mut ret = None;
self.cstore.iter_crate_data(|cnum, data| {
// `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() ||
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 \
fn register_crate(&mut self,
root: &Option<CratePaths>,
- ident: &str,
- name: &str,
+ ident: Symbol,
+ name: Symbol,
span: Span,
lib: Library,
dep_kind: DepKind)
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
// 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(|_| {
source: cstore::CrateSource {
dylib: dylib,
rlib: rlib,
+ rmeta: rmeta,
},
});
fn resolve_crate(&mut self,
root: &Option<CratePaths>,
- ident: &str,
- name: &str,
+ ident: Symbol,
+ name: Symbol,
hash: Option<&Svh>,
span: Span,
path_kind: PathKind,
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)
}
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();
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,
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)));
}
}
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,
});
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 {
// 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);
config::CrateTypeProcMacro |
config::CrateTypeCdylib |
config::CrateTypeStaticlib => need_lib_alloc = true,
- config::CrateTypeRlib => {}
+ config::CrateTypeRlib |
+ config::CrateTypeMetadata => {}
}
}
if !need_lib_alloc && !need_exe_alloc { return }
// * 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) =
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());
}
}
}
// 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());
}
}
};
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,
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| {
list[0].meta_item().unwrap().clone()
});
let lib = NativeLibrary {
- name: n.to_string(),
+ name: n,
kind: kind,
cfg: cfg,
};
for &(ref name, kind) in &self.sess.opts.libs {
let lib = NativeLibrary {
- name: name.clone(),
+ name: Symbol::intern(name),
kind: kind,
cfg: None,
};
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();
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
pub enum MetadataBlob {
Inflated(Bytes),
Archive(locator::ArchiveMetadata),
+ Raw(Vec<u8>),
}
/// Holds information about a syntax_pos::FileMap imported from another crate.
}
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
// positions.
pub fn do_get_used_crates(&self,
prefer: LinkagePreference)
- -> Vec<(CrateNum, Option<PathBuf>)> {
+ -> Vec<(CrateNum, LibSource)> {
let mut ordering = Vec::new();
for (&num, _) in self.metas.borrow().iter() {
self.push_dependencies_in_postorder(&mut ordering, num);
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::<Vec<_>>();
}
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);
}
}
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 {
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;
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;
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<ExternCrate>
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<DefId>
locator::meta_section_name(target)
}
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option<PathBuf>)>
+ fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
{
self.do_get_used_crates(prefer)
}
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,
}
}
}
self.raw_bytes().starts_with(METADATA_HEADER)
}
+ pub fn get_rustc_version(&self) -> String {
+ Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
+ }
+
pub fn get_root(&self) -> CrateRoot {
let slice = self.raw_bytes();
let offset = METADATA_HEADER.len();
.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()
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};
if let PatKind::Binding(_, ref path1, _) = arg.pat.node {
path1.node
} else {
- syntax::parse::token::intern("")
+ Symbol::intern("")
}
}))
}
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(),
}
let link_meta = self.link_meta;
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
// Will be filed with the root position after encoding everything.
cursor.write_all(&[0, 0, 0, 0]).unwrap();
- let root = EncodeContext {
+ let root = {
+ let mut ecx = EncodeContext {
opaque: opaque::Encoder::new(&mut cursor),
tcx: tcx,
reexports: reexports,
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
- }
- .encode_crate_root();
+ };
+
+ // Encode the rustc version string in a predictable location.
+ rustc_version().encode(&mut ecx).unwrap();
+
+ // Encode all the entries and extra information in the crate,
+ // culminating in the `CrateRoot` which points to all of it.
+ ecx.encode_crate_root()
+ };
let mut result = cursor.into_inner();
// Encode the root position.
//! 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
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;
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,
pub ident: String,
pub dylib: Option<PathBuf>,
pub rlib: Option<PathBuf>,
+ pub rmeta: Option<PathBuf>,
}
pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
#[derive(Copy, Clone, PartialEq)]
enum CrateFlavor {
Rlib,
+ Rmeta,
Dylib,
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
CrateFlavor::Rlib => "rlib",
+ CrateFlavor::Rmeta => "rmeta",
CrateFlavor::Dylib => "dylib",
})
}
impl CratePaths {
fn paths(&self) -> Vec<PathBuf> {
- 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()
}
}
// 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;
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
})
// 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,
});
}
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
}
fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
- let root = metadata.get_root();
- if let Some(is_proc_macro) = self.is_proc_macro {
- if root.macro_derive_registrar.is_some() != is_proc_macro {
- return None;
- }
- }
-
let rustc_version = rustc_version();
- if root.rustc_version != rustc_version {
+ let found_version = metadata.get_rustc_version();
+ if found_version != rustc_version {
info!("Rejecting via version: expected {} got {}",
rustc_version,
- root.rustc_version);
+ found_version);
self.rejected_via_version.push(CrateMismatch {
path: libpath.to_path_buf(),
- got: root.rustc_version,
+ got: found_version,
});
return None;
}
+ let root = metadata.get_root();
+ if let Some(is_proc_macro) = self.is_proc_macro {
+ if root.macro_derive_registrar.is_some() != is_proc_macro {
+ return None;
+ }
+ }
+
if self.should_match_name {
if self.crate_name != root.name {
info!("Rejecting via crate name");
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| {
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;
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);
}
// 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 {
Some(Library {
dylib: dylib,
rlib: rlib,
+ rmeta: rmeta,
metadata: metadata,
})
}
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);
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
};
use rustc_serialize as serialize;
use syntax::{ast, attr};
+use syntax::symbol::Symbol;
use syntax_pos::{self, Span};
use std::marker::PhantomData;
/// Metadata encoding version.
/// NB: increment this if you change the format of metadata such that
-/// the rustc version can't be found to compare with `RUSTC_VERSION`.
-pub const METADATA_VERSION: u8 = 3;
+/// the rustc version can't be found to compare with `rustc_version()`.
+pub const METADATA_VERSION: u8 = 4;
/// Metadata header which includes `METADATA_VERSION`.
/// To get older versions of rustc to ignore this metadata,
/// there are 4 zero bytes at the start, which are treated
/// as a length of 0 by old compilers.
///
-/// This header is followed by the position of the `CrateRoot`.
+/// This header is followed by the position of the `CrateRoot`,
+/// which is encoded as a 32-bit big-endian unsigned integer,
+/// and further followed by the rustc version string.
pub const METADATA_HEADER: &'static [u8; 12] =
&[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
#[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<DefIndex>,
pub macro_derive_registrar: Option<DefIndex>,
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, 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);
- }
+ // 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 });
+ }
+ );
exit_block.unit()
}
ExprKind::Call { ty, fun, args } => {
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> {
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 {
}
}
- fn break_or_continue<F>(&mut self,
- span: Span,
- label: Option<CodeExtent>,
- 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()
- }
-
}
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};
/// the current set of loops; see the `scope` module for more
/// details
- loop_scopes: Vec<scope::LoopScope>,
+ loop_scopes: Vec<scope::LoopScope<'tcx>>,
/// the vector of all scopes that we have created thus far;
/// we track this for debuginfo later
}
#[derive(Clone, Debug)]
-pub struct LoopScope {
+pub struct LoopScope<'tcx> {
/// Extent of the loop
pub extent: CodeExtent,
/// Where the body of the loop begins
/// 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> {
///
/// Returns the might_break attribute of the LoopScope used.
pub fn in_loop_scope<F>(&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();
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`
pub fn find_loop_scope(&mut self,
span: Span,
label: Option<CodeExtent>)
- -> &mut LoopScope {
+ -> &mut LoopScope<'tcx> {
let loop_scopes = &mut self.loop_scopes;
match label {
None => {
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;
},
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, _) =>
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) => {
*/
use hair::*;
-use rustc::mir::*;
use rustc::mir::transform::MirSource;
use rustc::middle::const_val::ConstVal;
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};
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) }
}
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 {
},
Break {
label: Option<CodeExtent>,
+ value: Option<ExprRef<'tcx>>,
},
Continue {
label: Option<CodeExtent>,
#![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)]
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;
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,
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,
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);
}
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() {
hir::ExprLoop(..) |
// More control flow (also not very meaningful).
- hir::ExprBreak(_) |
+ hir::ExprBreak(..) |
hir::ExprAgain(_) |
hir::ExprRet(_) |
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
}
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);
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));
}
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<F>(&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;
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"))
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),
}
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;
///
/// 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 {
/// 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));
}
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};
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};
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,
});
} 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 {
}
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 {
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();
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");
}
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());
}
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
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};
enum SuggestionType {
Macro(String),
- Function(token::InternedString),
+ Function(Symbol),
NotFound,
}
}
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);
}
}
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<ast::MacroDef>,
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(),
-> ResolveResult<Module<'a>> {
fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Module<'a>)
-> Option<Module<'a>> {
- 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)
// 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;
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)));
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));
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;
/// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option<Span>)
-> ResolveResult<ModulePrefixResult<'a>> {
- 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));
}
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 {
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,
};
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)
}
};
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)
}
}
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));
}
.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
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);
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) => {
}
} else {
// danger, shouldn't be ident?
- names.push(token::str_to_ident("<opaque>"));
+ names.push(Ident::from_str("<opaque>"));
collect_mod(names, module.parent.unwrap());
}
}
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;
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() {
}
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`");
}
fn find_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
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))
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,
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)]
module: Module<'a>,
name: Name,
ns: Namespace,
- allow_private_imports: bool,
ignore_unresolved_invocations: bool,
record_used: Option<Span>)
-> ResolveResult<&'a NameBinding<'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);
}
}
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) }
};
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,
}
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;
}
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) {
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);
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,
// 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);
}
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),
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,
_ => {}
}
resolution.borrow().binding().map(|binding| (*name, binding))
}).collect::<Vec<_>>();
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);
}
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();
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;
fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
self.tcx.expect_def_or_none(ref_id).and_then(|def| {
match def {
- Def::PrimTy(..) | Def::SelfTy(..) => None,
+ Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
def => Some(def.def_id()),
}
})
collector.visit_pat(&arg.pat);
let span_utils = self.span.clone();
for &(id, ref p, ..) in &collector.collected_paths {
- let typ = self.tcx.tables().node_types.get(&id).unwrap().to_string();
+ let typ = match self.tcx.tables().node_types.get(&id) {
+ Some(s) => s.to_string(),
+ None => continue,
+ };
// get the span only for the name of the variable (I hope the path is only ever a
// variable name, but who knows?)
let sub_span = span_utils.span_for_last_ident(p.span);
match p.node {
PatKind::Struct(ref path, ref fields, _) => {
visit::walk_path(self, path);
- let adt = self.tcx.tables().node_id_to_type(p.id).ty_adt_def().unwrap();
+ let adt = match self.tcx.tables().node_id_to_type_opt(p.id) {
+ Some(ty) => ty.ty_adt_def().unwrap(),
+ None => {
+ visit::walk_pat(self, p);
+ return;
+ }
+ };
let variant = adt.variant_of_def(self.tcx.expect_def(p.id));
for &Spanned { node: ref field, span } in fields {
}
ast::ExprKind::Struct(ref path, ref fields, ref base) => {
let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id);
- let adt = self.tcx.tables().expr_ty(&hir_expr).ty_adt_def().unwrap();
+ let adt = match self.tcx.tables().expr_ty_opt(&hir_expr) {
+ Some(ty) => ty.ty_adt_def().unwrap(),
+ None => {
+ visit::walk_expr(self, ex);
+ return;
+ }
+ };
let def = self.tcx.expect_def(hir_expr.id);
self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
}
return;
}
};
- let ty = &self.tcx.tables().expr_ty_adjusted(&hir_node).sty;
+ let ty = match self.tcx.tables().expr_ty_adjusted_opt(&hir_node) {
+ Some(ty) => &ty.sty,
+ None => {
+ visit::walk_expr(self, ex);
+ return;
+ }
+ };
match *ty {
ty::TyAdt(def, _) => {
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
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;
}
};
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,
});
}
pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
- let def = self.tcx.expect_def(id);
+ let resolution = self.tcx.expect_resolution(id);
+ if resolution.depth != 0 {
+ return None;
+ }
+ let def = resolution.base_def;
+
let sub_span = self.span_utils.span_for_last_ident(path.span);
filter!(self.span_utils, sub_span, path.span, None);
match def {
}
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');
}
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)]
log = { path = "../liblog" }
rustc = { path = "../librustc" }
rustc_back = { path = "../librustc_back" }
+rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_eval = { path = "../librustc_const_eval" }
rustc_const_math = { path = "../librustc_const_math" }
rustc_data_structures = { path = "../librustc_data_structures" }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector};
+use llvm::{self, ValueRef, Integer, Pointer, Float, Double, Struct, Array, Vector, AttributePlace};
use base;
use build::AllocaFcx;
use common::{type_is_fat_ptr, BlockAndBuilder, C_uint};
Ignore,
}
+// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
+// of this module
+pub use self::attr_impl::ArgAttribute;
+
+#[allow(non_upper_case_globals)]
+mod attr_impl {
+ // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
+ bitflags! {
+ #[derive(Default, Debug)]
+ flags ArgAttribute : u8 {
+ const ByVal = 1 << 0,
+ const NoAlias = 1 << 1,
+ const NoCapture = 1 << 2,
+ const NonNull = 1 << 3,
+ const ReadOnly = 1 << 4,
+ const SExt = 1 << 5,
+ const StructRet = 1 << 6,
+ const ZExt = 1 << 7,
+ }
+ }
+}
+
+macro_rules! for_each_kind {
+ ($flags: ident, $f: ident, $($kind: ident),+) => ({
+ $(if $flags.contains(ArgAttribute::$kind) { $f(llvm::Attribute::$kind) })+
+ })
+}
+
+impl ArgAttribute {
+ fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
+ for_each_kind!(self, f,
+ ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt)
+ }
+}
+
+/// A compact representation of LLVM attributes (at least those relevant for this module)
+/// that can be manipulated without interacting with LLVM's Attribute machinery.
+#[derive(Copy, Clone, Debug, Default)]
+pub struct ArgAttributes {
+ regular: ArgAttribute,
+ dereferenceable_bytes: u64,
+}
+
+impl ArgAttributes {
+ pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
+ self.regular = self.regular | attr;
+ self
+ }
+
+ pub fn unset(&mut self, attr: ArgAttribute) -> &mut Self {
+ self.regular = self.regular - attr;
+ self
+ }
+
+ pub fn set_dereferenceable(&mut self, bytes: u64) -> &mut Self {
+ self.dereferenceable_bytes = bytes;
+ self
+ }
+
+ pub fn unset_dereferenceable(&mut self) -> &mut Self {
+ self.dereferenceable_bytes = 0;
+ self
+ }
+
+ pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+ unsafe {
+ self.regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
+ if self.dereferenceable_bytes != 0 {
+ llvm::LLVMRustAddDereferenceableAttr(llfn,
+ idx.as_uint(),
+ self.dereferenceable_bytes);
+ }
+ }
+ }
+
+ pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+ unsafe {
+ self.regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
+ if self.dereferenceable_bytes != 0 {
+ llvm::LLVMRustAddDereferenceableCallSiteAttr(callsite,
+ idx.as_uint(),
+ self.dereferenceable_bytes);
+ }
+ }
+ }
+}
+
/// Information about how a specific C type
/// should be passed to or returned from a function
///
/// Dummy argument, which is emitted before the real argument
pub pad: Option<Type>,
/// LLVM attributes of argument
- pub attrs: llvm::Attributes
+ pub attrs: ArgAttributes
}
impl ArgType {
signedness: None,
cast: None,
pad: None,
- attrs: llvm::Attributes::default()
+ attrs: ArgAttributes::default()
}
}
assert_eq!(self.kind, ArgKind::Direct);
// Wipe old attributes, likely not valid through indirection.
- self.attrs = llvm::Attributes::default();
+ self.attrs = ArgAttributes::default();
let llarg_sz = llsize_of_alloc(ccx, self.ty);
// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
- self.attrs.set(llvm::Attribute::NoAlias)
- .set(llvm::Attribute::NoCapture)
+ self.attrs.set(ArgAttribute::NoAlias)
+ .set(ArgAttribute::NoCapture)
.set_dereferenceable(llarg_sz);
self.kind = ArgKind::Indirect;
if let Some(signed) = self.signedness {
if self.ty.int_width() < bits {
self.attrs.set(if signed {
- llvm::Attribute::SExt
+ ArgAttribute::SExt
} else {
- llvm::Attribute::ZExt
+ ArgAttribute::ZExt
});
}
}
if ty.is_bool() {
let llty = Type::i1(ccx);
let mut arg = ArgType::new(llty, llty);
- arg.attrs.set(llvm::Attribute::ZExt);
+ arg.attrs.set(ArgAttribute::ZExt);
arg
} else {
let mut arg = ArgType::new(type_of::type_of(ccx, ty),
if let ty::TyBox(_) = ret_ty.sty {
// `Box` pointer return values never alias because ownership
// is transferred
- ret.attrs.set(llvm::Attribute::NoAlias);
+ ret.attrs.set(ArgAttribute::NoAlias);
}
// We can also mark the return value as `dereferenceable` in certain cases
let rust_ptr_attrs = |ty: Ty<'tcx>, arg: &mut ArgType| match ty.sty {
// `Box` pointer parameters never alias because ownership is transferred
ty::TyBox(inner) => {
- arg.attrs.set(llvm::Attribute::NoAlias);
+ arg.attrs.set(ArgAttribute::NoAlias);
Some(inner)
}
let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
if mt.mutbl != hir::MutMutable && !interior_unsafe {
- arg.attrs.set(llvm::Attribute::NoAlias);
+ arg.attrs.set(ArgAttribute::NoAlias);
}
if mt.mutbl == hir::MutImmutable && !interior_unsafe {
- arg.attrs.set(llvm::Attribute::ReadOnly);
+ arg.attrs.set(ArgAttribute::ReadOnly);
}
// When a reference in an argument has no named lifetime, it's
// impossible for that reference to escape this function
// (returned or stored beyond the call by a closure).
if let ReLateBound(_, BrAnon(_)) = *b {
- arg.attrs.set(llvm::Attribute::NoCapture);
+ arg.attrs.set(ArgAttribute::NoCapture);
}
Some(mt.ty)
let mut info = ArgType::new(original_tys[1], sizing_tys[1]);
if let Some(inner) = rust_ptr_attrs(ty, &mut data) {
- data.attrs.set(llvm::Attribute::NonNull);
+ data.attrs.set(ArgAttribute::NonNull);
if ccx.tcx().struct_tail(inner).is_trait() {
- info.attrs.set(llvm::Attribute::NonNull);
+ info.attrs.set(ArgAttribute::NonNull);
}
}
args.push(data);
fixup(arg);
}
if self.ret.is_indirect() {
- self.ret.attrs.set(llvm::Attribute::StructRet);
+ self.ret.attrs.set(ArgAttribute::StructRet);
}
return;
}
}
if self.ret.is_indirect() {
- self.ret.attrs.set(llvm::Attribute::StructRet);
+ self.ret.attrs.set(ArgAttribute::StructRet);
}
}
// of the size.
let size = size.bytes();
let align = align.abi();
+ assert!(align <= std::u32::MAX as u64);
let discr_ty = Type::from_integer(cx, discr);
let discr_size = discr.size().bytes();
let padded_discr_size = roundup(discr_size, align as u32);
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(),
use rustc::ty::TyCtxt;
use syntax::ast;
-use syntax::parse::token::InternedString;
use {ModuleSource, ModuleTranslation};
}
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 => {
}
}
- 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() {
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;
}
Always => Attribute::AlwaysInline.apply_llfn(Function, val),
Never => Attribute::NoInline.apply_llfn(Function, val),
None => {
- let attr = Attribute::InlineHint |
- Attribute::AlwaysInline |
- Attribute::NoInline;
- attr.unapply_llfn(Function, val)
+ Attribute::InlineHint.unapply_llfn(Function, val);
+ Attribute::AlwaysInline.unapply_llfn(Function, val);
+ Attribute::NoInline.unapply_llfn(Function, val);
},
};
}
}
fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
- 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)
}
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;
use flate;
use syntax::ast;
use syntax::attr;
+use syntax::symbol::Symbol;
use syntax_pos::Span;
// RLIB LLVM-BYTECODE OBJECT LAYOUT
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);
}
"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);
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 => {
.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] {
}
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));
}
};
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());
}
}
+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
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);
}
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
// 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
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));
});
// 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!(),
}
}
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
use std::fs;
use rustc::hir::def_id::CrateNum;
+use rustc::middle::cstore::LibSource;
pub struct RPathConfig<'a> {
- pub used_crates: Vec<(CrateNum, Option<PathBuf>)>,
+ pub used_crates: Vec<(CrateNum, LibSource)>,
pub out_filename: PathBuf,
pub is_like_osx: bool,
pub has_rpath: bool,
debug!("preparing the RPATH!");
let libs = config.used_crates.clone();
- let libs = libs.into_iter().filter_map(|(_, l)| l).collect::<Vec<_>>();
+ let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
let rpaths = get_rpaths(config, &libs[..]);
flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));
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>,
}
fn push(&mut self, text: &str) {
- self.names.push(token::intern(text).as_str());
+ self.names.push(Symbol::intern(text).as_str());
}
}
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)
}
use rustc::util::common::time;
use session::config::{self, NoDebugInfo};
use rustc_incremental::IncrementalHashesMap;
-use session::Session;
+use session::{self, DataTypeKind, Session};
use abi::{self, Abi, FnType};
use adt;
use attributes;
use syntax_pos::{Span, DUMMY_SP};
use syntax::attr;
use rustc::hir;
+use rustc::ty::layout::{self, Layout};
use syntax::ast;
thread_local! {
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());
}
}
config::CrateTypeStaticlib |
config::CrateTypeCdylib => MetadataKind::None,
- config::CrateTypeRlib => MetadataKind::Uncompressed,
+ config::CrateTypeRlib |
+ config::CrateTypeMetadata => MetadataKind::Uncompressed,
config::CrateTypeDylib |
config::CrateTypeProcMacro => MetadataKind::Compressed,
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,
.collect())
});
+ if tcx.sess.opts.debugging_opts.print_type_sizes {
+ gather_type_sizes(tcx);
+ }
+
if sess.target.target.options.is_like_msvc &&
sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
create_imps(&crate_context_list);
}
}
+fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+ let layout_cache = tcx.layout_cache.borrow();
+ for (ty, layout) in layout_cache.iter() {
+
+ // (delay format until we actually need it)
+ let record = |kind, opt_discr_size, variants| {
+ let type_desc = format!("{:?}", ty);
+ let overall_size = layout.size(&tcx.data_layout);
+ let align = layout.align(&tcx.data_layout);
+ tcx.sess.code_stats.borrow_mut().record_type_size(kind,
+ type_desc,
+ align,
+ overall_size,
+ opt_discr_size,
+ variants);
+ };
+
+ let (adt_def, substs) = match ty.sty {
+ ty::TyAdt(ref adt_def, substs) => {
+ debug!("print-type-size t: `{:?}` process adt", ty);
+ (adt_def, substs)
+ }
+
+ ty::TyClosure(..) => {
+ debug!("print-type-size t: `{:?}` record closure", ty);
+ record(DataTypeKind::Closure, None, vec![]);
+ continue;
+ }
+
+ _ => {
+ debug!("print-type-size t: `{:?}` skip non-nominal", ty);
+ continue;
+ }
+ };
+
+ let adt_kind = adt_def.adt_kind();
+
+ let build_field_info = |(field_name, field_ty): (ast::Name, Ty), offset: &layout::Size| {
+ match layout_cache.get(&field_ty) {
+ None => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty),
+ Some(field_layout) => {
+ session::FieldInfo {
+ name: field_name.to_string(),
+ offset: offset.bytes(),
+ size: field_layout.size(&tcx.data_layout).bytes(),
+ align: field_layout.align(&tcx.data_layout).abi(),
+ }
+ }
+ }
+ };
+
+ let build_primitive_info = |name: ast::Name, value: &layout::Primitive| {
+ session::VariantInfo {
+ name: Some(name.to_string()),
+ kind: session::SizeKind::Exact,
+ align: value.align(&tcx.data_layout).abi(),
+ size: value.size(&tcx.data_layout).bytes(),
+ fields: vec![],
+ }
+ };
+
+ enum Fields<'a> {
+ WithDiscrim(&'a layout::Struct),
+ NoDiscrim(&'a layout::Struct),
+ }
+
+ let build_variant_info = |n: Option<ast::Name>, flds: &[(ast::Name, Ty)], layout: Fields| {
+ let (s, field_offsets) = match layout {
+ Fields::WithDiscrim(s) => (s, &s.offsets[1..]),
+ Fields::NoDiscrim(s) => (s, &s.offsets[0..]),
+ };
+ let field_info: Vec<_> = flds.iter()
+ .zip(field_offsets.iter())
+ .map(|(&field_name_ty, offset)| build_field_info(field_name_ty, offset))
+ .collect();
+
+ session::VariantInfo {
+ name: n.map(|n|n.to_string()),
+ kind: if s.sized {
+ session::SizeKind::Exact
+ } else {
+ session::SizeKind::Min
+ },
+ align: s.align.abi(),
+ size: s.min_size.bytes(),
+ fields: field_info,
+ }
+ };
+
+ match **layout {
+ Layout::StructWrappedNullablePointer { nonnull: ref variant_layout,
+ nndiscr,
+ discrfield: _ } => {
+ debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}",
+ ty, nndiscr, variant_layout);
+ let variant_def = &adt_def.variants[nndiscr as usize];
+ let fields: Vec<_> = variant_def.fields.iter()
+ .map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
+ .collect();
+ record(adt_kind.into(),
+ None,
+ vec![build_variant_info(Some(variant_def.name),
+ &fields,
+ Fields::NoDiscrim(variant_layout))]);
+ }
+ Layout::RawNullablePointer { nndiscr, value } => {
+ debug!("print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}",
+ ty, nndiscr, value);
+ let variant_def = &adt_def.variants[nndiscr as usize];
+ record(adt_kind.into(), None,
+ vec![build_primitive_info(variant_def.name, &value)]);
+ }
+ Layout::Univariant { variant: ref variant_layout, non_zero: _ } => {
+ let variant_names = || {
+ adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
+ };
+ debug!("print-type-size t: `{:?}` adt univariant {:?} variants: {:?}",
+ ty, variant_layout, variant_names());
+ assert!(adt_def.variants.len() <= 1,
+ "univariant with variants {:?}", variant_names());
+ if adt_def.variants.len() == 1 {
+ let variant_def = &adt_def.variants[0];
+ let fields: Vec<_> = variant_def.fields.iter()
+ .map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
+ .collect();
+ record(adt_kind.into(),
+ None,
+ vec![build_variant_info(Some(variant_def.name),
+ &fields,
+ Fields::NoDiscrim(variant_layout))]);
+ } else {
+ // (This case arises for *empty* enums; so give it
+ // zero variants.)
+ record(adt_kind.into(), None, vec![]);
+ }
+ }
+
+ Layout::General { ref variants, discr, .. } => {
+ debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
+ ty, adt_def.variants.len(), variants.len(), variants);
+ let variant_infos: Vec<_> = adt_def.variants.iter()
+ .zip(variants.iter())
+ .map(|(variant_def, variant_layout)| {
+ let fields: Vec<_> = variant_def.fields.iter()
+ .map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
+ .collect();
+ build_variant_info(Some(variant_def.name),
+ &fields,
+ Fields::WithDiscrim(variant_layout))
+ })
+ .collect();
+ record(adt_kind.into(), Some(discr.size()), variant_infos);
+ }
+
+ Layout::UntaggedUnion { ref variants } => {
+ debug!("print-type-size t: `{:?}` adt union variants {:?}",
+ ty, variants);
+ // layout does not currently store info about each
+ // variant...
+ record(adt_kind.into(), None, Vec::new());
+ }
+
+ Layout::CEnum { discr, .. } => {
+ debug!("print-type-size t: `{:?}` adt c-like enum", ty);
+ let variant_infos: Vec<_> = adt_def.variants.iter()
+ .map(|variant_def| {
+ build_primitive_info(variant_def.name,
+ &layout::Primitive::Int(discr))
+ })
+ .collect();
+ record(adt_kind.into(), Some(discr.size()), variant_infos);
+ }
+
+ // other cases provide little interesting (i.e. adjustable
+ // via representation tweaks) size info beyond total size.
+ Layout::Scalar { .. } |
+ Layout::Vector { .. } |
+ Layout::Array { .. } |
+ Layout::FatPointer { .. } => {
+ debug!("print-type-size t: `{:?}` adt other", ty);
+ record(adt_kind.into(), None, Vec::new())
+ }
+ }
+ }
+}
+
/// For each CGU, identify if we can reuse an existing object file (or
/// maybe other context).
fn trans_reuse_previous_work_products(tcx: TyCtxt,
#![allow(non_upper_case_globals)]
-use llvm::{Struct, Array, Attribute};
-use abi::{FnType, ArgType};
+use llvm::{Struct, Array};
+use abi::{FnType, ArgType, ArgAttribute};
use context::CrateContext;
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
if arg.ty.is_aggregate() {
arg.make_indirect(ccx);
- arg.attrs.set(Attribute::ByVal);
+ arg.attrs.set(ArgAttribute::ByVal);
}
}
// except according to those terms.
use llvm::*;
-use abi::FnType;
+use abi::{ArgAttribute, FnType};
use type_::Type;
use super::common::*;
use super::machine::*;
if arg.is_ignore() { continue; }
if arg.ty.kind() == Struct {
arg.make_indirect(ccx);
- arg.attrs.set(Attribute::ByVal);
+ arg.attrs.set(ArgAttribute::ByVal);
} else {
arg.extend_integer_width_to(32);
}
use self::RegClass::*;
use llvm::{Integer, Pointer, Float, Double};
-use llvm::{Struct, Array, Attribute, Vector};
-use abi::{self, ArgType, FnType};
+use llvm::{Struct, Array, Vector};
+use abi::{self, ArgType, ArgAttribute, FnType};
use context::CrateContext;
use type_::Type;
fn x86_64_ty<F>(ccx: &CrateContext,
arg: &mut ArgType,
is_mem_cls: F,
- ind_attr: Option<Attribute>)
+ ind_attr: Option<ArgAttribute>)
where F: FnOnce(&[RegClass]) -> bool
{
if !arg.ty.is_reg_ty() {
sse_regs -= needed_sse;
}
in_mem
- }, Some(Attribute::ByVal));
+ }, Some(ArgAttribute::ByVal));
// An integer, pointer, double or float parameter
// thus the above closure passed to `x86_64_ty` won't
-> 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"
}
}
}
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};
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()
}
}
// 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");
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 {
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};
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));
}
}
// 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<str> {
+ 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)
}
-> 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)
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);
}
};
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);
}
}
};
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()
}
}
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),
fn get_enum_discriminant_name(cx: &CrateContext,
def_id: DefId)
- -> token::InternedString {
+ -> InternedString {
cx.tcx().item_name(def_id).as_str()
}
}
-> 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
-> 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
}
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()
};
});
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()
};
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());
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};
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,
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)
}
}
(_, "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") => {
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),
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),
html_root_url = "https://doc.rust-lang.org/nightly/")]
#![cfg_attr(not(stage0), deny(warnings))]
+#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(cell_extras)]
extern crate serialize;
extern crate rustc_const_math;
extern crate rustc_const_eval;
+#[macro_use]
+#[no_link]
+extern crate rustc_bitflags;
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
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;
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| {
// 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);
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],
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;
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};
// 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());
}
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 = || {
// 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()));
}
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
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>,
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);
// 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("::");
}
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;
};
let output_binding = ConvertedBinding {
- item_name: token::intern(FN_OUTPUT_NAME),
+ item_name: Symbol::intern(FN_OUTPUT_NAME),
ty: output,
span: output_span
};
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))
use rustc::hir;
use syntax_pos::Span;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
#[derive(Copy, Clone, Debug)]
enum AutoderefKind {
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);
(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)
(None, Some(trait_did)) => {
self.lookup_method_in_trait(span,
base_expr,
- token::intern("deref"),
+ Symbol::intern("deref"),
trait_did,
base_ty,
None)
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;
pub fn check_call(&self,
call_expr: &'gcx hir::Expr,
callee_expr: &'gcx hir::Expr,
- arg_exprs: &'gcx [P<hir::Expr>],
+ arg_exprs: &'gcx [hir::Expr],
expected: Expectation<'tcx>)
-> Ty<'tcx> {
let original_callee_ty = self.check_expr(callee_expr);
-> Option<ty::MethodCallee<'tcx>> {
// 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,
fn confirm_builtin_call(&self,
call_expr: &hir::Expr,
callee_ty: Ty<'tcx>,
- arg_exprs: &'gcx [P<hir::Expr>],
+ arg_exprs: &'gcx [hir::Expr],
expected: Expectation<'tcx>)
-> Ty<'tcx> {
let error_fn_sig;
fn confirm_deferred_closure_call(&self,
call_expr: &hir::Expr,
- arg_exprs: &'gcx [P<hir::Expr>],
+ arg_exprs: &'gcx [hir::Expr],
expected: Expectation<'tcx>,
fn_sig: ty::FnSig<'tcx>)
-> Ty<'tcx> {
fn confirm_overloaded_call(&self,
call_expr: &hir::Expr,
callee_expr: &'gcx hir::Expr,
- arg_exprs: &'gcx [P<hir::Expr>],
+ arg_exprs: &'gcx [hir::Expr],
expected: Expectation<'tcx>,
method_callee: ty::MethodCallee<'tcx>)
-> Ty<'tcx> {
/// Cast of thin to fat raw ptr (eg. `*const () as *const [u8]`)
SizedUnsizedCast,
IllegalCast,
+ NeedDeref,
NeedViaPtr,
NeedViaThinPtr,
NeedViaInt,
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
match e {
+ CastError::NeedDeref => {
+ let cast_ty = fcx.ty_to_string(self.cast_ty);
+ let mut err = fcx.type_error_struct(self.cast_span,
+ |actual| {
+ format!("casting `{}` as `{}` is invalid",
+ actual,
+ cast_ty)
+ },
+ self.expr_ty);
+ err.span_label(self.expr.span,
+ &format!("cannot cast `{}` as `{}`",
+ fcx.ty_to_string(self.expr_ty),
+ cast_ty));
+ if let Ok(snippet) = fcx.sess().codemap().span_to_snippet(self.expr.span) {
+ err.span_label(self.expr.span,
+ &format!("did you mean `*{}`?", snippet));
+ }
+ err.emit();
+ }
CastError::NeedViaThinPtr |
CastError::NeedViaPtr => {
let mut err = fcx.type_error_struct(self.span,
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
- (RPtr(_), Int(_)) |
- (RPtr(_), Float) => Err(CastError::NeedViaPtr),
+ (RPtr(p), Int(_)) |
+ (RPtr(p), Float) => {
+ match p.ty.sty {
+ ty::TypeVariants::TyInt(_) |
+ ty::TypeVariants::TyUint(_) |
+ ty::TypeVariants::TyFloat(_) => {
+ Err(CastError::NeedDeref)
+ }
+ ty::TypeVariants::TyInfer(t) => {
+ match t {
+ ty::InferTy::IntVar(_) |
+ ty::InferTy::FloatVar(_) |
+ ty::InferTy::FreshIntTy(_) |
+ ty::InferTy::FreshFloatTy(_) => {
+ Err(CastError::NeedDeref)
+ }
+ _ => Err(CastError::NeedViaPtr),
+ }
+ }
+ _ => Err(CastError::NeedViaPtr),
+ }
+ }
// * -> ptr
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
use syntax::abi::Abi;
use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc::hir;
/// 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)
}
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)
};
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);
}
}
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};
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};
}
}
+#[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<LoopCtxt<'gcx, 'tcx>>,
+ by_id: NodeMap<usize>,
+}
+
+impl<'gcx, 'tcx> EnclosingLoops<'gcx, 'tcx> {
+ fn find_loop(&mut self, id: Option<ast::NodeId>) -> 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<NodeMap<Ty<'tcx>>>,
/// Whether any child nodes have any type errors.
has_errors: Cell<bool>,
+ enclosing_loops: RefCell<EnclosingLoops<'gcx, 'tcx>>,
+
inh: &'a Inherited<'a, 'gcx, '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 {
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 => {
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,
}
}
(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,
(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,
sp: Span,
method_fn_ty: Ty<'tcx>,
callee_expr: &'gcx hir::Expr,
- args_no_rcvr: &'gcx [P<hir::Expr>],
+ args_no_rcvr: &'gcx [hir::Expr],
tuple_arguments: TupleArgumentsFlag,
expected: Expectation<'tcx>)
-> Ty<'tcx> {
sp: Span,
fn_inputs: &[Ty<'tcx>],
expected_arg_tys: &[Ty<'tcx>],
- args: &'gcx [P<hir::Expr>],
+ args: &'gcx [hir::Expr],
variadic: bool,
tuple_arguments: TupleArgumentsFlag) {
let tcx = self.tcx;
fn check_method_call(&self,
expr: &'gcx hir::Expr,
method_name: Spanned<ast::Name>,
- args: &'gcx [P<hir::Expr>],
+ args: &'gcx [hir::Expr],
tps: &[P<hir::Ty>],
expected: Expectation<'tcx>,
lvalue_pref: LvaluePreference) -> Ty<'tcx> {
fn suggest_field_name(variant: ty::VariantDef<'tcx>,
field: &Spanned<ast::Name>,
skip : Vec<InternedString>)
- -> Option<InternedString> {
+ -> Option<Symbol> {
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
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,
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));
}
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 {
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
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
}
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 {
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)
};
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() {
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<F: FnOnce()>(&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
- // <id> 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>,
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> {
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(()) => {
-> 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| {
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);
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);
}
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);
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};
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("<upvar>"),
+ name: Symbol::intern("<upvar>"),
def_id: def_id,
default_def_id: base_def_id,
default: None,
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::hir::print as pprust;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty;
use rustc::util::nodemap::FxHashSet;
use rustc_const_eval::lookup_const_by_id;
/// of a vector of items if it was successfully expanded.
pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
-> Option<Vec<clean::Item>> {
- let tcx = match cx.tcx_opt() {
- Some(tcx) => tcx,
- None => return None,
- };
- let def = match tcx.expect_def_or_none(id) {
+ let def = match cx.tcx.expect_def_or_none(id) {
Some(def) => def,
None => return None,
};
let did = def.def_id();
if did.is_local() { return None }
- try_inline_def(cx, tcx, def).map(|vec| {
+ try_inline_def(cx, def).map(|vec| {
vec.into_iter().map(|mut item| {
match into {
Some(into) if item.name.is_some() => {
})
}
-fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def: Def) -> Option<Vec<clean::Item>> {
+fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
+ let tcx = cx.tcx;
let mut ret = Vec::new();
- let did = def.def_id();
let inner = match def {
Def::Trait(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Trait);
- ret.extend(build_impls(cx, tcx, did));
- clean::TraitItem(build_external_trait(cx, tcx, did))
+ ret.extend(build_impls(cx, did));
+ clean::TraitItem(build_external_trait(cx, did))
}
Def::Fn(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Function);
- clean::FunctionItem(build_external_function(cx, tcx, did))
+ clean::FunctionItem(build_external_function(cx, did))
}
Def::Struct(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Struct);
- ret.extend(build_impls(cx, tcx, did));
- clean::StructItem(build_struct(cx, tcx, did))
+ ret.extend(build_impls(cx, did));
+ clean::StructItem(build_struct(cx, did))
}
Def::Union(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Union);
- ret.extend(build_impls(cx, tcx, did));
- clean::UnionItem(build_union(cx, tcx, did))
+ ret.extend(build_impls(cx, did));
+ clean::UnionItem(build_union(cx, did))
}
Def::TyAlias(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
- ret.extend(build_impls(cx, tcx, did));
- clean::TypedefItem(build_type_alias(cx, tcx, did), false)
+ ret.extend(build_impls(cx, did));
+ clean::TypedefItem(build_type_alias(cx, did), false)
}
Def::Enum(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Enum);
- ret.extend(build_impls(cx, tcx, did));
- clean::EnumItem(build_enum(cx, tcx, did))
+ ret.extend(build_impls(cx, did));
+ clean::EnumItem(build_enum(cx, did))
}
// Assume that the enum type is reexported next to the variant, and
// variants don't show up in documentation specially.
Def::StructCtor(..) => return Some(Vec::new()),
Def::Mod(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Module);
- clean::ModuleItem(build_module(cx, tcx, did))
+ clean::ModuleItem(build_module(cx, did))
}
Def::Static(did, mtbl) => {
record_extern_fqn(cx, did, clean::TypeKind::Static);
- clean::StaticItem(build_static(cx, tcx, did, mtbl))
+ clean::StaticItem(build_static(cx, did, mtbl))
}
Def::Const(did) => {
record_extern_fqn(cx, did, clean::TypeKind::Const);
- clean::ConstantItem(build_const(cx, tcx, did))
+ clean::ConstantItem(build_const(cx, did))
}
_ => return None,
};
+ let did = def.def_id();
cx.renderinfo.borrow_mut().inlined.insert(did);
ret.push(clean::Item {
source: clean::Span::empty(),
name: Some(tcx.item_name(did).to_string()),
- attrs: load_attrs(cx, tcx, did),
+ attrs: load_attrs(cx, did),
inner: inner,
visibility: Some(clean::Public),
stability: tcx.lookup_stability(did).clean(cx),
Some(ret)
}
-pub fn load_attrs<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> Vec<clean::Attribute> {
- tcx.get_attrs(did).iter().map(|a| a.clean(cx)).collect()
+pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes {
+ cx.tcx.get_attrs(did).clean(cx)
}
/// Record an external fully qualified name in the external_paths cache.
/// These names are used later on by HTML rendering to generate things like
/// source links back to the original item.
pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
- if let Some(tcx) = cx.tcx_opt() {
- let crate_name = tcx.sess.cstore.crate_name(did.krate).to_string();
- let relative = tcx.def_path(did).data.into_iter().filter_map(|elem| {
- // extern blocks have an empty name
- let s = elem.data.to_string();
- if !s.is_empty() {
- Some(s)
- } else {
- None
- }
- });
- let fqn = once(crate_name).chain(relative).collect();
- cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
- }
+ let crate_name = cx.tcx.sess.cstore.crate_name(did.krate).to_string();
+ let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
+ // extern blocks have an empty name
+ let s = elem.data.to_string();
+ if !s.is_empty() {
+ Some(s)
+ } else {
+ None
+ }
+ });
+ let fqn = once(crate_name).chain(relative).collect();
+ cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
}
-pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Trait {
- let def = tcx.lookup_trait_def(did);
- let trait_items = tcx.associated_items(did).map(|item| item.clean(cx)).collect();
- let predicates = tcx.item_predicates(did);
+pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
+ let def = cx.tcx.lookup_trait_def(did);
+ let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect();
+ let predicates = cx.tcx.item_predicates(did);
let generics = (def.generics, &predicates).clean(cx);
let generics = filter_non_trait_generics(did, generics);
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
}
}
-fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Function {
- let ty = tcx.item_type(did);
+fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
+ let ty = cx.tcx.item_type(did);
let (decl, style, abi) = match ty.sty {
ty::TyFnDef(.., ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
_ => panic!("bad function"),
};
- let constness = if tcx.sess.cstore.is_const_fn(did) {
+ let constness = if cx.tcx.sess.cstore.is_const_fn(did) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
- let predicates = tcx.item_predicates(did);
+ let predicates = cx.tcx.item_predicates(did);
clean::Function {
decl: decl,
- generics: (tcx.item_generics(did), &predicates).clean(cx),
+ generics: (cx.tcx.item_generics(did), &predicates).clean(cx),
unsafety: style,
constness: constness,
abi: abi,
}
}
-fn build_enum<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Enum {
- let predicates = tcx.item_predicates(did);
+fn build_enum(cx: &DocContext, did: DefId) -> clean::Enum {
+ let predicates = cx.tcx.item_predicates(did);
clean::Enum {
- generics: (tcx.item_generics(did), &predicates).clean(cx),
+ generics: (cx.tcx.item_generics(did), &predicates).clean(cx),
variants_stripped: false,
- variants: tcx.lookup_adt_def(did).variants.clean(cx),
+ variants: cx.tcx.lookup_adt_def(did).variants.clean(cx),
}
}
-fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Struct {
- let predicates = tcx.item_predicates(did);
- let variant = tcx.lookup_adt_def(did).struct_variant();
+fn build_struct(cx: &DocContext, did: DefId) -> clean::Struct {
+ let predicates = cx.tcx.item_predicates(did);
+ let variant = cx.tcx.lookup_adt_def(did).struct_variant();
clean::Struct {
struct_type: match variant.ctor_kind {
CtorKind::Fn => doctree::Tuple,
CtorKind::Const => doctree::Unit,
},
- generics: (tcx.item_generics(did), &predicates).clean(cx),
+ generics: (cx.tcx.item_generics(did), &predicates).clean(cx),
fields: variant.fields.clean(cx),
fields_stripped: false,
}
}
-fn build_union<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Union {
- let predicates = tcx.item_predicates(did);
- let variant = tcx.lookup_adt_def(did).struct_variant();
+fn build_union(cx: &DocContext, did: DefId) -> clean::Union {
+ let predicates = cx.tcx.item_predicates(did);
+ let variant = cx.tcx.lookup_adt_def(did).struct_variant();
clean::Union {
struct_type: doctree::Plain,
- generics: (tcx.item_generics(did), &predicates).clean(cx),
+ generics: (cx.tcx.item_generics(did), &predicates).clean(cx),
fields: variant.fields.clean(cx),
fields_stripped: false,
}
}
-fn build_type_alias<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Typedef {
- let predicates = tcx.item_predicates(did);
+fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
+ let predicates = cx.tcx.item_predicates(did);
clean::Typedef {
- type_: tcx.item_type(did).clean(cx),
- generics: (tcx.item_generics(did), &predicates).clean(cx),
+ type_: cx.tcx.item_type(did).clean(cx),
+ generics: (cx.tcx.item_generics(did), &predicates).clean(cx),
}
}
-pub fn build_impls<'a, 'tcx>(cx: &DocContext,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> Vec<clean::Item> {
+pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
+ let tcx = cx.tcx;
tcx.populate_inherent_implementations_for_type_if_necessary(did);
let mut impls = Vec::new();
if let Some(i) = tcx.inherent_impls.borrow().get(&did) {
for &did in i.iter() {
- build_impl(cx, tcx, did, &mut impls);
+ build_impl(cx, did, &mut impls);
}
}
// If this is the first time we've inlined something from another crate, then
cx.populated_all_crate_impls.set(true);
for did in tcx.sess.cstore.implementations_of_trait(None) {
- build_impl(cx, tcx, did, &mut impls);
+ build_impl(cx, did, &mut impls);
}
// Also try to inline primitive impls from other crates.
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
if !def_id.is_local() {
- build_impl(cx, tcx, def_id, &mut impls);
+ build_impl(cx, def_id, &mut impls);
}
}
impls
}
-pub fn build_impl<'a, 'tcx>(cx: &DocContext,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId,
- ret: &mut Vec<clean::Item>) {
+pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
if !cx.renderinfo.borrow_mut().inlined.insert(did) {
return
}
- let attrs = load_attrs(cx, tcx, did);
+ let attrs = load_attrs(cx, did);
+ let tcx = cx.tcx;
let associated_trait = tcx.impl_trait_ref(did);
// Only inline impl if the implemented trait is
default,
),
source: clean::Span::empty(),
- attrs: vec![],
+ attrs: clean::Attributes::default(),
visibility: None,
stability: tcx.lookup_stability(item.def_id).clean(cx),
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
name: Some(item.name.clean(cx)),
inner: clean::TypedefItem(typedef, true),
source: clean::Span::empty(),
- attrs: vec![],
+ attrs: clean::Attributes::default(),
visibility: None,
stability: tcx.lookup_stability(item.def_id).clean(cx),
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
clean::RegionBound(..) => unreachable!(),
}
});
- if trait_.def_id() == cx.deref_trait_did.get() {
+ if trait_.def_id() == tcx.lang_items.deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
let provided = trait_.def_id().map(|did| {
- cx.tcx().provided_trait_methods(did)
- .into_iter()
- .map(|meth| meth.name.to_string())
- .collect()
+ tcx.provided_trait_methods(did)
+ .into_iter()
+ .map(|meth| meth.name.to_string())
+ .collect()
}).unwrap_or(FxHashSet());
ret.push(clean::Item {
});
}
-fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Module {
+fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
let mut items = Vec::new();
- fill_in(cx, tcx, did, &mut items);
+ fill_in(cx, did, &mut items);
return clean::Module {
items: items,
is_crate: false,
};
- fn fill_in<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId, items: &mut Vec<clean::Item>) {
+ fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
// If we're reexporting a reexport it may actually reexport something in
// two namespaces, so the target may be listed twice. Make sure we only
// visit each node at most once.
let mut visited = FxHashSet();
- for item in tcx.sess.cstore.item_children(did) {
+ for item in cx.tcx.sess.cstore.item_children(did) {
let def_id = item.def.def_id();
- if tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
+ if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
if !visited.insert(def_id) { continue }
- if let Some(i) = try_inline_def(cx, tcx, item.def) {
+ if let Some(i) = try_inline_def(cx, item.def) {
items.extend(i)
}
}
}
}
-fn build_const<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId) -> clean::Constant {
- let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
+fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {
+ let (expr, ty) = lookup_const_by_id(cx.tcx, did, None).unwrap_or_else(|| {
panic!("expected lookup_const_by_id to succeed for {:?}", did);
});
debug!("converting constant expr {:?} to snippet", expr);
debug!("got snippet {}", sn);
clean::Constant {
- type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| tcx.item_type(did).clean(cx)),
+ type_: ty.map(|t| t.clean(cx)).unwrap_or_else(|| cx.tcx.item_type(did).clean(cx)),
expr: sn
}
}
-fn build_static<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- did: DefId,
- mutable: bool) -> clean::Static {
+fn build_static(cx: &DocContext, did: DefId, mutable: bool) -> clean::Static {
clean::Static {
- type_: tcx.item_type(did).clean(cx),
+ type_: cx.tcx.item_type(did).clean(cx),
mutability: if mutable {clean::Mutable} else {clean::Immutable},
expr: "\n\n\n".to_string(), // trigger the "[definition]" links
}
pub use self::Type::*;
pub use self::Mutability::*;
pub use self::ItemEnum::*;
-pub use self::Attribute::*;
pub use self::TyParamBound::*;
pub use self::SelfTy::*;
pub use self::FunctionRetTy::*;
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;
use std::path::PathBuf;
use std::rc::Rc;
+use std::slice;
use std::sync::Arc;
use std::u32;
use std::env::current_dir;
// extract the stability index for a node from tcx, if possible
fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
- cx.tcx_opt().and_then(|tcx| tcx.lookup_stability(def_id)).clean(cx)
+ cx.tcx.lookup_stability(def_id).clean(cx)
}
fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
- cx.tcx_opt().and_then(|tcx| tcx.lookup_deprecation(def_id)).clean(cx)
+ cx.tcx.lookup_deprecation(def_id).clean(cx)
}
pub trait Clean<T> {
use rustc::session::config::Input;
use ::visit_lib::LibEmbargoVisitor;
- if let Some(t) = cx.tcx_opt() {
- cx.deref_trait_did.set(t.lang_items.deref_trait());
- cx.renderinfo.borrow_mut().deref_trait_did = cx.deref_trait_did.get();
- cx.deref_mut_trait_did.set(t.lang_items.deref_mut_trait());
- cx.renderinfo.borrow_mut().deref_mut_trait_did = cx.deref_mut_trait_did.get();
+ {
+ let mut r = cx.renderinfo.borrow_mut();
+ r.deref_trait_did = cx.tcx.lang_items.deref_trait();
+ r.deref_mut_trait_did = cx.tcx.lang_items.deref_mut_trait();
}
let mut externs = Vec::new();
for cnum in cx.sess().cstore.crates() {
externs.push((cnum, CrateNum(cnum).clean(cx)));
- if cx.tcx_opt().is_some() {
- // Analyze doc-reachability for extern items
- LibEmbargoVisitor::new(cx).visit_lib(cnum);
- }
+ // Analyze doc-reachability for extern items
+ LibEmbargoVisitor::new(cx).visit_lib(cnum);
}
externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ExternalCrate {
pub name: String,
- pub attrs: Vec<Attribute>,
+ pub attrs: Attributes,
pub primitives: Vec<PrimitiveType>,
}
fn clean(&self, cx: &DocContext) -> ExternalCrate {
let mut primitives = Vec::new();
let root = DefId { krate: self.0, index: CRATE_DEF_INDEX };
- cx.tcx_opt().map(|tcx| {
- for item in tcx.sess.cstore.item_children(root) {
- let attrs = inline::load_attrs(cx, tcx, item.def.def_id());
- PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
- }
- });
+ for item in cx.tcx.sess.cstore.item_children(root) {
+ let attrs = inline::load_attrs(cx, item.def.def_id());
+ PrimitiveType::find(&attrs).map(|prim| primitives.push(prim));
+ }
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,
}
pub source: Span,
/// Not everything has a name. E.g., impls
pub name: Option<String>,
- pub attrs: Vec<Attribute>,
+ pub attrs: Attributes,
pub inner: ItemEnum,
pub visibility: Option<Visibility>,
pub def_id: DefId,
/// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found.
pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
- self.attrs.value("doc")
+ self.attrs.doc_value()
}
pub fn is_crate(&self) -> bool {
match self.inner {
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
items: items
}
}
-pub trait Attributes {
- fn has_word(&self, &str) -> bool;
- fn value<'a>(&'a self, &str) -> Option<&'a str>;
- fn list<'a>(&'a self, &str) -> &'a [Attribute];
+pub struct ListAttributesIter<'a> {
+ attrs: slice::Iter<'a, ast::Attribute>,
+ current_list: slice::Iter<'a, ast::NestedMetaItem>,
+ name: &'a str
}
-impl Attributes for [Attribute] {
- /// Returns whether the attribute list contains a specific `Word`
- fn has_word(&self, word: &str) -> bool {
- for attr in self {
- if let Word(ref w) = *attr {
- if word == *w {
- return true;
- }
- }
+impl<'a> Iterator for ListAttributesIter<'a> {
+ type Item = &'a ast::NestedMetaItem;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(nested) = self.current_list.next() {
+ return Some(nested);
}
- false
- }
- /// Finds an attribute as NameValue and returns the corresponding value found.
- fn value<'a>(&'a self, name: &str) -> Option<&'a str> {
- for attr in self {
- if let NameValue(ref x, ref v) = *attr {
- if name == *x {
- return Some(v);
+ for attr in &mut self.attrs {
+ if let Some(ref list) = attr.meta_item_list() {
+ if attr.check_name(self.name) {
+ self.current_list = list.iter();
+ if let Some(nested) = self.current_list.next() {
+ return Some(nested);
+ }
}
}
}
+
None
}
+}
+pub trait AttributesExt {
/// Finds an attribute as List and returns the list of attributes nested inside.
- fn list<'a>(&'a self, name: &str) -> &'a [Attribute] {
- for attr in self {
- if let List(ref x, ref list) = *attr {
- if name == *x {
- return &list[..];
- }
- }
+ fn lists<'a>(&'a self, &'a str) -> ListAttributesIter<'a>;
+}
+
+impl AttributesExt for [ast::Attribute] {
+ fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
+ ListAttributesIter {
+ attrs: self.iter(),
+ current_list: [].iter(),
+ name: name
}
- &[]
}
}
-/// This is a flattened version of the AST's Attribute + MetaItem.
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
-pub enum Attribute {
- Word(String),
- List(String, Vec<Attribute>),
- NameValue(String, String),
- Literal(String),
+pub trait NestedAttributesExt {
+ /// Returns whether the attribute list contains a specific `Word`
+ fn has_word(self, &str) -> bool;
+}
+
+impl<'a, I: IntoIterator<Item=&'a ast::NestedMetaItem>> NestedAttributesExt for I {
+ fn has_word(self, word: &str) -> bool {
+ self.into_iter().any(|attr| attr.is_word() && attr.check_name(word))
+ }
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
+pub struct Attributes {
+ pub doc_strings: Vec<String>,
+ pub other_attrs: Vec<ast::Attribute>
}
-impl Clean<Attribute> for ast::NestedMetaItem {
- fn clean(&self, cx: &DocContext) -> Attribute {
- if let Some(mi) = self.meta_item() {
- mi.clean(cx)
- } else { // must be a literal
- let lit = self.literal().unwrap();
- Literal(syntax_pprust::lit_to_string(lit))
+impl Attributes {
+ pub fn from_ast(attrs: &[ast::Attribute]) -> Attributes {
+ let mut doc_strings = vec![];
+ let other_attrs = attrs.iter().filter_map(|attr| {
+ attr.with_desugared_doc(|attr| {
+ if let Some(value) = attr.value_str() {
+ if attr.check_name("doc") {
+ doc_strings.push(value.to_string());
+ return None;
+ }
+ }
+
+ Some(attr.clone())
+ })
+ }).collect();
+ Attributes {
+ doc_strings: doc_strings,
+ other_attrs: other_attrs
}
}
+
+ /// Finds the `doc` attribute as a NameValue and returns the corresponding
+ /// value found.
+ pub fn doc_value<'a>(&'a self) -> Option<&'a str> {
+ self.doc_strings.first().map(|s| &s[..])
+ }
}
-impl Clean<Attribute> for ast::MetaItem {
- fn clean(&self, cx: &DocContext) -> Attribute {
- if self.is_word() {
- Word(self.name().to_string())
- } else if let Some(v) = self.value_str() {
- NameValue(self.name().to_string(), v.to_string())
- } else { // must be a list
- let l = self.meta_item_list().unwrap();
- List(self.name().to_string(), l.clean(cx))
- }
+impl AttributesExt for Attributes {
+ fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> {
+ self.other_attrs.lists(name)
}
}
-impl Clean<Attribute> for ast::Attribute {
- fn clean(&self, cx: &DocContext) -> Attribute {
- self.with_desugared_doc(|a| a.meta().clean(cx))
+impl Clean<Attributes> for [ast::Attribute] {
+ fn clean(&self, _cx: &DocContext) -> Attributes {
+ Attributes::from_ast(self)
}
}
fn clean(&self, cx: &DocContext) -> TyParam {
TyParam {
name: self.name.clean(cx),
- did: cx.map.local_def_id(self.id),
+ did: cx.tcx.map.local_def_id(self.id),
bounds: self.bounds.clean(cx),
default: self.default.clean(cx),
}
fn is_sized_bound(&self, cx: &DocContext) -> bool {
use rustc::hir::TraitBoundModifier as TBM;
- if let Some(tcx) = cx.tcx_opt() {
- if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
- if trait_.def_id() == tcx.lang_items.sized_trait() {
- return true;
- }
+ if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
+ if trait_.def_id() == cx.tcx.lang_items.sized_trait() {
+ return true;
}
}
false
let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect();
let types = substs.types().skip(has_self as usize).collect::<Vec<_>>();
- match (trait_did, cx.tcx_opt()) {
+ match trait_did {
// Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
- (Some(did), Some(ref tcx)) if tcx.lang_items.fn_trait_kind(did).is_some() => {
+ Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => {
assert_eq!(types.len(), 1);
let inputs = match types[0].sty {
ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(),
output: output
}
},
- (..) => {
+ _ => {
PathParameters::AngleBracketed {
lifetimes: lifetimes,
types: types.clean(cx),
impl Clean<TyParamBound> for ty::BuiltinBound {
fn clean(&self, cx: &DocContext) -> TyParamBound {
- let tcx = match cx.tcx_opt() {
- Some(tcx) => tcx,
- None => return RegionBound(Lifetime::statik())
- };
+ let tcx = cx.tcx;
let empty = tcx.intern_substs(&[]);
let (did, path) = match *self {
ty::BoundSend =>
impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
fn clean(&self, cx: &DocContext) -> TyParamBound {
- let tcx = match cx.tcx_opt() {
- Some(tcx) => tcx,
- None => return RegionBound(Lifetime::statik())
- };
inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
- let path = external_path(cx, &tcx.item_name(self.def_id).as_str(),
+ let path = external_path(cx, &cx.tcx.item_name(self.def_id).as_str(),
Some(self.def_id), true, vec![], self.substs);
debug!("ty::TraitRef\n subst: {:?}\n", self.substs);
impl Clean<Lifetime> for hir::Lifetime {
fn clean(&self, cx: &DocContext) -> Lifetime {
- if let Some(tcx) = cx.tcx_opt() {
- let def = tcx.named_region_map.defs.get(&self.id).cloned();
- match def {
- Some(DefEarlyBoundRegion(_, node_id)) |
- Some(DefLateBoundRegion(_, node_id)) |
- Some(DefFreeRegion(_, node_id)) => {
- if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
- return lt;
- }
+ let def = cx.tcx.named_region_map.defs.get(&self.id).cloned();
+ match def {
+ Some(DefEarlyBoundRegion(_, node_id)) |
+ Some(DefLateBoundRegion(_, node_id)) |
+ Some(DefFreeRegion(_, node_id)) => {
+ if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
+ return lt;
}
- _ => {}
}
+ _ => {}
}
Lifetime(self.name.to_string())
}
},
output: self.decl.output.clean(cx),
variadic: false,
- attrs: Vec::new()
+ attrs: Attributes::default()
};
Method {
generics: self.generics.clean(cx),
},
output: self.decl.output.clean(cx),
variadic: false,
- attrs: Vec::new()
+ attrs: Attributes::default()
};
TyMethod {
unsafety: self.unsafety.clone(),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
inner: FunctionItem(Function {
decl: self.decl.clean(cx),
generics: self.generics.clean(cx),
pub inputs: Arguments,
pub output: FunctionRetTy,
pub variadic: bool,
- pub attrs: Vec<Attribute>,
+ pub attrs: Attributes,
}
impl FnDecl {
},
output: self.output.clean(cx),
variadic: self.variadic,
- attrs: Vec::new()
+ attrs: Attributes::default()
}
}
}
impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
fn clean(&self, cx: &DocContext) -> FnDecl {
let (did, sig) = *self;
- let mut names = if cx.map.as_local_node_id(did).is_some() {
+ let mut names = if cx.tcx.map.as_local_node_id(did).is_some() {
vec![].into_iter()
} else {
- cx.tcx().sess.cstore.fn_arg_names(did).into_iter()
+ cx.tcx.sess.cstore.fn_arg_names(did).into_iter()
}.peekable();
FnDecl {
output: Return(sig.0.output.clean(cx)),
- attrs: Vec::new(),
+ attrs: Attributes::default(),
variadic: sig.0.variadic,
inputs: Arguments {
values: sig.0.inputs.iter().map(|t| {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: None,
- stability: get_stability(cx, cx.map.local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
+ stability: get_stability(cx, cx.tcx.map.local_def_id(self.id)),
+ deprecation: get_deprecation(cx, cx.tcx.map.local_def_id(self.id)),
inner: inner
}
}
name: Some(self.name.clean(cx)),
source: self.span.clean(cx),
attrs: self.attrs.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.map.local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
+ stability: get_stability(cx, cx.tcx.map.local_def_id(self.id)),
+ deprecation: get_deprecation(cx, cx.tcx.map.local_def_id(self.id)),
inner: inner
}
}
fn clean(&self, cx: &DocContext) -> Item {
let inner = match self.kind {
ty::AssociatedKind::Const => {
- let ty = cx.tcx().item_type(self.def_id);
+ let ty = cx.tcx.item_type(self.def_id);
AssociatedConstItem(ty.clean(cx), None)
}
ty::AssociatedKind::Method => {
- let generics = (cx.tcx().item_generics(self.def_id),
- &cx.tcx().item_predicates(self.def_id)).clean(cx);
- let fty = match cx.tcx().item_type(self.def_id).sty {
+ let generics = (cx.tcx.item_generics(self.def_id),
+ &cx.tcx.item_predicates(self.def_id)).clean(cx);
+ let fty = match cx.tcx.item_type(self.def_id).sty {
ty::TyFnDef(_, _, f) => f,
_ => unreachable!()
};
if self.method_has_self_argument {
let self_ty = match self.container {
ty::ImplContainer(def_id) => {
- cx.tcx().item_type(def_id)
+ cx.tcx.item_type(def_id)
}
- ty::TraitContainer(_) => cx.tcx().mk_self_type()
+ ty::TraitContainer(_) => cx.tcx.mk_self_type()
};
let self_arg_ty = *fty.sig.input(0).skip_binder();
if self_arg_ty == self_ty {
// are actually located on the trait/impl itself, so we need to load
// all of the generics from there and then look for bounds that are
// applied to this associated type in question.
- let def = cx.tcx().lookup_trait_def(did);
- let predicates = cx.tcx().item_predicates(did);
+ let def = cx.tcx.lookup_trait_def(did);
+ let predicates = cx.tcx.item_predicates(did);
let generics = (def.generics, &predicates).clean(cx);
generics.where_predicates.iter().filter_map(|pred| {
let (name, self_type, trait_, bounds) = match *pred {
}
let ty = if self.defaultness.has_value() {
- Some(cx.tcx().item_type(self.def_id))
+ Some(cx.tcx.item_type(self.def_id))
} else {
None
};
stability: get_stability(cx, self.def_id),
deprecation: get_deprecation(cx, self.def_id),
def_id: self.def_id,
- attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
+ attrs: inline::load_attrs(cx, self.def_id),
source: Span::empty(),
inner: inner,
}
}
}
- fn find(attrs: &[Attribute]) -> Option<PrimitiveType> {
- for attr in attrs.list("doc") {
- if let NameValue(ref k, ref v) = *attr {
- if "primitive" == *k {
- if let ret@Some(..) = PrimitiveType::from_str(v) {
+ fn find(attrs: &Attributes) -> Option<PrimitiveType> {
+ for attr in attrs.lists("doc") {
+ if let Some(v) = attr.value_str() {
+ if attr.check_name("primitive") {
+ if let ret@Some(..) = PrimitiveType::from_str(&v.as_str()) {
return ret;
}
}
type_: box m.ty.clean(cx)},
TySlice(ref ty) => Vector(box ty.clean(cx)),
TyArray(ref ty, ref e) => {
- let n = if let Some(tcx) = cx.tcx_opt() {
- use rustc_const_math::{ConstInt, ConstUsize};
- use rustc_const_eval::eval_const_expr;
- use rustc::middle::const_val::ConstVal;
- match eval_const_expr(tcx, e) {
- ConstVal::Integral(ConstInt::Usize(u)) => match u {
- ConstUsize::Us16(u) => u.to_string(),
- ConstUsize::Us32(u) => u.to_string(),
- ConstUsize::Us64(u) => u.to_string(),
- },
- // after type checking this can't fail
- _ => unreachable!(),
- }
- } else {
- pprust::expr_to_string(e)
+ use rustc_const_math::{ConstInt, ConstUsize};
+ use rustc_const_eval::eval_const_expr;
+ use rustc::middle::const_val::ConstVal;
+
+ let n = match eval_const_expr(cx.tcx, e) {
+ ConstVal::Integral(ConstInt::Usize(u)) => match u {
+ ConstUsize::Us16(u) => u.to_string(),
+ ConstUsize::Us32(u) => u.to_string(),
+ ConstUsize::Us64(u) => u.to_string(),
+ },
+ // after type checking this can't fail
+ _ => unreachable!(),
};
FixedVector(box ty.clean(cx), n)
},
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(None, ref path) => {
- let tcx_and_def = cx.tcx_opt().map(|tcx| (tcx, tcx.expect_def(self.id)));
- if let Some((_, def)) = tcx_and_def {
- if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
- return new_ty;
- }
+ let def = cx.tcx.expect_def(self.id);
+ if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
+ return new_ty;
}
- let tcx_and_alias = tcx_and_def.and_then(|(tcx, def)| {
- if let Def::TyAlias(def_id) = def {
- // Substitute private type aliases
- tcx.map.as_local_node_id(def_id).and_then(|node_id| {
- if !cx.access_levels.borrow().is_exported(def_id) {
- Some((tcx, &tcx.map.expect_item(node_id).node))
- } else {
- None
- }
- })
- } else {
- None
+ let mut alias = None;
+ if let Def::TyAlias(def_id) = def {
+ // Substitute private type aliases
+ if let Some(node_id) = cx.tcx.map.as_local_node_id(def_id) {
+ if !cx.access_levels.borrow().is_exported(def_id) {
+ alias = Some(&cx.tcx.map.expect_item(node_id).node);
+ }
}
- });
- if let Some((tcx, &hir::ItemTy(ref ty, ref generics))) = tcx_and_alias {
+ };
+
+ if let Some(&hir::ItemTy(ref ty, ref generics)) = alias {
let provided_params = &path.segments.last().unwrap().parameters;
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
- let ty_param_def = tcx.expect_def(ty_param.id);
+ let ty_param_def = cx.tcx.expect_def(ty_param.id);
if let Some(ty) = provided_params.types().get(i).cloned()
.cloned() {
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
ty::TyFloat(float_ty) => Primitive(float_ty.into()),
ty::TyStr => Primitive(PrimitiveType::Str),
ty::TyBox(t) => {
- let box_did = cx.tcx_opt().and_then(|tcx| {
- tcx.lang_items.owned_box()
- });
+ let box_did = cx.tcx.lang_items.owned_box();
lang_struct(cx, box_did, t, "Box", Unique)
}
ty::TySlice(ty) => Vector(box ty.clean(cx)),
type_params: Vec::new(),
where_predicates: Vec::new()
},
- decl: (cx.map.local_def_id(ast::CRATE_NODE_ID), &fty.sig).clean(cx),
+ decl: (cx.tcx.map.local_def_id(ast::CRATE_NODE_ID), &fty.sig).clean(cx),
abi: fty.abi,
}),
ty::TyAdt(def, substs) => {
AdtKind::Enum => TypeKind::Enum,
};
inline::record_extern_fqn(cx, did, kind);
- let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
+ let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
None, false, vec![], substs);
ResolvedPath {
path: path,
});
}
- let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
+ let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, bindings, obj.principal.0.substs);
ResolvedPath {
path: path,
ty::TyAnon(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
- let item_predicates = cx.tcx().item_predicates(def_id);
- let substs = cx.tcx().lift(&substs).unwrap();
- let bounds = item_predicates.instantiate(cx.tcx(), substs);
+ let item_predicates = cx.tcx.item_predicates(def_id);
+ let substs = cx.tcx.lift(&substs).unwrap();
+ let bounds = item_predicates.instantiate(cx.tcx, substs);
ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| {
predicate.to_opt_poly_trait_ref().clean(cx)
}).collect())
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.map.local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
- def_id: cx.map.local_def_id(self.id),
+ stability: get_stability(cx, cx.tcx.map.local_def_id(self.id)),
+ deprecation: get_deprecation(cx, cx.tcx.map.local_def_id(self.id)),
+ def_id: cx.tcx.map.local_def_id(self.id),
inner: StructFieldItem(self.ty.clean(cx)),
}
}
fn clean(&self, cx: &DocContext) -> Item {
Item {
name: Some(self.name).clean(cx),
- attrs: cx.tcx().get_attrs(self.did).clean(cx),
+ attrs: cx.tcx.get_attrs(self.did).clean(cx),
source: Span::empty(),
visibility: self.vis.clean(cx),
stability: get_stability(cx, self.did),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
visibility: None,
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.map.local_def_id(self.def.id()),
+ def_id: cx.tcx.map.local_def_id(self.def.id()),
inner: VariantItem(Variant {
kind: self.def.clean(cx),
}),
Item {
source: Span::empty(),
name: Some(field.name.clean(cx)),
- attrs: cx.tcx().get_attrs(field.did).clean(cx),
+ attrs: cx.tcx.get_attrs(field.did).clean(cx),
visibility: field.vis.clean(cx),
def_id: field.did,
stability: get_stability(cx, field.did),
};
Item {
name: Some(self.name.clean(cx)),
- attrs: inline::load_attrs(cx, cx.tcx(), self.did),
+ attrs: inline::load_attrs(cx, self.did),
source: Span::empty(),
visibility: Some(Inherited),
def_id: self.did,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id.clone()),
+ def_id: cx.tcx.map.local_def_id(self.id.clone()),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
// If this impl block is an implementation of the Deref trait, then we
// need to try inlining the target's inherent impl blocks as well.
- if trait_.def_id() == cx.deref_trait_did.get() {
+ if trait_.def_id() == cx.tcx.lang_items.deref_trait() {
build_deref_target_impls(cx, &items, &mut ret);
}
- let provided = trait_.def_id().and_then(|did| {
- cx.tcx_opt().map(|tcx| {
- tcx.provided_trait_methods(did)
- .into_iter()
- .map(|meth| meth.name.to_string())
- .collect()
- })
+ let provided = trait_.def_id().map(|did| {
+ cx.tcx.provided_trait_methods(did)
+ .into_iter()
+ .map(|meth| meth.name.to_string())
+ .collect()
}).unwrap_or(FxHashSet());
ret.push(Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
fn build_deref_target_impls(cx: &DocContext,
items: &[Item],
ret: &mut Vec<Item>) {
- let tcx = match cx.tcx_opt() {
- Some(t) => t,
- None => return,
- };
+ let tcx = cx.tcx;
for item in items {
let target = match item.inner {
let primitive = match *target {
ResolvedPath { did, .. } if did.is_local() => continue,
ResolvedPath { did, .. } => {
- ret.extend(inline::build_impls(cx, tcx, did));
+ ret.extend(inline::build_impls(cx, did));
continue
}
_ => match target.primitive_type() {
};
if let Some(did) = did {
if !did.is_local() {
- inline::build_impl(cx, tcx, did, ret);
+ inline::build_impl(cx, did, ret);
}
}
}
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: Some(Public),
stability: None,
deprecation: None,
// #[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,
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
- def_id: cx.map.local_def_id(ast::CRATE_NODE_ID),
+ def_id: cx.tcx.map.local_def_id(ast::CRATE_NODE_ID),
visibility: self.vis.clean(cx),
stability: None,
deprecation: None,
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
visibility: self.vis.clean(cx),
- stability: get_stability(cx, cx.map.local_def_id(self.id)),
- deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)),
+ stability: get_stability(cx, cx.tcx.map.local_def_id(self.id)),
+ deprecation: get_deprecation(cx, cx.tcx.map.local_def_id(self.id)),
inner: inner,
}
}
path: Path,
id: ast::NodeId) -> Type {
debug!("resolve_type({:?},{:?})", path, id);
- let tcx = match cx.tcx_opt() {
- Some(tcx) => tcx,
- // If we're extracting tests, this return value's accuracy is not
- // important, all we want is a string representation to help people
- // figure out what doctests are failing.
- None => {
- let did = DefId::local(DefIndex::from_u32(0));
- return ResolvedPath {
- path: path,
- typarams: None,
- did: did,
- is_generic: false
- };
- }
- };
- let def = tcx.expect_def(id);
+ let def = cx.tcx.expect_def(id);
debug!("resolve_type: def={:?}", def);
let is_generic = match def {
fn register_def(cx: &DocContext, def: Def) -> DefId {
debug!("register_def({:?})", def);
- let tcx = cx.tcx();
-
let (did, kind) = match def {
Def::Fn(i) => (i, TypeKind::Function),
Def::TyAlias(i) => (i, TypeKind::Typedef),
Def::Union(i) => (i, TypeKind::Union),
Def::Mod(i) => (i, TypeKind::Module),
Def::Static(i, _) => (i, TypeKind::Static),
- Def::Variant(i) => (tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
+ Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum),
Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
Def::SelfTy(_, Some(impl_def_id)) => {
return impl_def_id
if did.is_local() { return did }
inline::record_extern_fqn(cx, did, kind);
if let TypeKind::Trait = kind {
- let t = inline::build_external_trait(cx, tcx, did);
+ let t = inline::build_external_trait(cx, did);
cx.external_traits.borrow_mut().insert(did, t);
}
did
}
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
- cx.tcx_opt().and_then(|tcx| {
- tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
- })
+ cx.tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
visibility: Some(Public),
stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx),
- def_id: cx.map.local_def_id(self.id),
+ def_id: cx.tcx.map.local_def_id(self.id),
inner: MacroItem(Macro {
source: format!("macro_rules! {} {{\n{}}}",
name,
if child == trait_ {
return true
}
- let predicates = cx.tcx().item_super_predicates(child).predicates;
+ let predicates = cx.tcx.item_super_predicates(child).predicates;
predicates.iter().filter_map(|pred| {
if let ty::Predicate::Trait(ref pred) = *pred {
if pred.0.trait_ref.self_ty().is_self() {
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub use self::MaybeTyped::*;
use rustc_lint;
use rustc_driver::{driver, target_features, abort_on_err};
pub use rustc::session::config::Input;
pub use rustc::session::search_paths::SearchPaths;
-/// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
-pub enum MaybeTyped<'a, 'tcx: 'a> {
- Typed(TyCtxt<'a, 'tcx, 'tcx>),
- NotTyped(&'a session::Session)
-}
-
pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
pub struct DocContext<'a, 'tcx: 'a> {
- pub map: &'a hir_map::Map<'tcx>,
- pub maybe_typed: MaybeTyped<'a, 'tcx>,
+ pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
pub input: Input,
pub populated_all_crate_impls: Cell<bool>,
- pub deref_trait_did: Cell<Option<DefId>>,
- pub deref_mut_trait_did: Cell<Option<DefId>>,
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
// the access levels from crateanalysis.
pub export_map: ExportMap,
}
-impl<'b, 'tcx> DocContext<'b, 'tcx> {
- pub fn sess<'a>(&'a self) -> &'a session::Session {
- match self.maybe_typed {
- Typed(tcx) => &tcx.sess,
- NotTyped(ref sess) => sess
- }
- }
-
- pub fn tcx_opt<'a>(&'a self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
- match self.maybe_typed {
- Typed(tcx) => Some(tcx),
- NotTyped(_) => None
- }
- }
-
- pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
- let tcx_opt = self.tcx_opt();
- tcx_opt.expect("tcx not present")
+impl<'a, 'tcx> DocContext<'a, 'tcx> {
+ pub fn sess(&self) -> &session::Session {
+ &self.tcx.sess
}
/// Call the closure with the given parameters set as
};
let ctxt = DocContext {
- map: &tcx.map,
- maybe_typed: Typed(tcx),
+ tcx: tcx,
input: input,
populated_all_crate_impls: Cell::new(false),
- deref_trait_did: Cell::new(None),
- deref_mut_trait_did: Cell::new(None),
access_levels: RefCell::new(access_levels),
external_traits: Default::default(),
renderinfo: Default::default(),
lt_substs: Default::default(),
export_map: export_map,
};
- debug!("crate: {:?}", ctxt.map.krate());
+ debug!("crate: {:?}", tcx.map.krate());
let krate = {
let mut v = RustdocVisitor::new(&ctxt);
- v.visit(ctxt.map.krate());
+ v.visit(tcx.map.krate());
v.clean(&ctxt)
};
use externalfiles::ExternalHtml;
use serialize::json::{ToJson, Json, as_json};
-use syntax::abi;
+use syntax::{abi, ast};
use syntax::feature_gate::UnstableFeatures;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use rustc::middle::privacy::AccessLevels;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::flock;
-use clean::{self, Attributes, GetDefId, SelfTy, Mutability};
+use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability};
use doctree;
use fold::DocFolder;
use html::escape::Escape;
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
- if let Some(attrs) = krate.module.as_ref().map(|m| m.attrs.list("doc")) {
- for attr in attrs {
- match *attr {
- clean::NameValue(ref x, ref s)
- if "html_favicon_url" == *x => {
+ if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) {
+ for attr in attrs.lists("doc") {
+ let name = attr.name().map(|s| s.as_str());
+ match (name.as_ref().map(|s| &s[..]), attr.value_str()) {
+ (Some("html_favicon_url"), Some(s)) => {
scx.layout.favicon = s.to_string();
}
- clean::NameValue(ref x, ref s)
- if "html_logo_url" == *x => {
+ (Some("html_logo_url"), Some(s)) => {
scx.layout.logo = s.to_string();
}
- clean::NameValue(ref x, ref s)
- if "html_playground_url" == *x => {
+ (Some("html_playground_url"), Some(s)) => {
markdown::PLAYGROUND.with(|slot| {
let name = krate.name.clone();
- *slot.borrow_mut() = Some((Some(name), s.clone()));
+ *slot.borrow_mut() = Some((Some(name), s.to_string()));
});
}
- clean::NameValue(ref x, ref s)
- if "issue_tracker_base_url" == *x => {
+ (Some("issue_tracker_base_url"), Some(s)) => {
scx.issue_tracker_base_url = Some(s.to_string());
}
- clean::Word(ref x)
- if "html_no_source" == *x => {
+ (Some("html_no_source"), None) if attr.is_word() => {
scx.include_sources = false;
}
_ => {}
// Failing that, see if there's an attribute specifying where to find this
// external crate
- e.attrs.list("doc").value("html_root_url").map(|url| {
- let mut url = url.to_owned();
+ e.attrs.lists("doc")
+ .filter(|a| a.check_name("html_root_url"))
+ .filter_map(|a| a.value_str())
+ .map(|url| {
+ let mut url = url.to_string();
if !url.ends_with("/") {
url.push('/')
}
Remote(url)
- }).unwrap_or(Unknown) // Well, at least we tried.
+ }).next().unwrap_or(Unknown) // Well, at least we tried.
}
impl<'a> DocFolder for SourceCollector<'a> {
write!(w, "}}")?;
}
write!(w, "</pre>")?;
- render_stability_since_raw(w, it.stable_since(), None)?;
document(w, cx, it)?;
if !e.variants.is_empty() {
Ok(())
}
-fn attribute_without_value(s: &str) -> bool {
- ["must_use", "no_mangle", "unsafe_destructor_blind_to_params"].iter().any(|x| x == &s)
-}
-
-fn attribute_with_value(s: &str) -> bool {
- ["export_name", "lang", "link_section", "must_use"].iter().any(|x| x == &s)
-}
-
-fn attribute_with_values(s: &str) -> bool {
- ["repr"].iter().any(|x| x == &s)
-}
+fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
+ let name = attr.name();
-fn render_attribute(attr: &clean::Attribute, recurse: bool) -> Option<String> {
- match *attr {
- clean::Word(ref s) if attribute_without_value(&*s) || recurse => {
- Some(format!("{}", s))
- }
- clean::NameValue(ref k, ref v) if attribute_with_value(&*k) => {
- Some(format!("{} = \"{}\"", k, v))
- }
- clean::List(ref k, ref values) if attribute_with_values(&*k) => {
- let display: Vec<_> = values.iter()
- .filter_map(|value| render_attribute(value, true))
- .map(|entry| format!("{}", entry))
- .collect();
+ if attr.is_word() {
+ Some(format!("{}", name))
+ } else if let Some(v) = attr.value_str() {
+ Some(format!("{} = {:?}", name, &v.as_str()[..]))
+ } else if let Some(values) = attr.meta_item_list() {
+ let display: Vec<_> = values.iter().filter_map(|attr| {
+ attr.meta_item().and_then(|mi| render_attribute(mi))
+ }).collect();
- if display.len() > 0 {
- Some(format!("{}({})", k, display.join(", ")))
- } else {
- None
- }
- }
- _ => {
+ if display.len() > 0 {
+ Some(format!("{}({})", name, display.join(", ")))
+ } else {
None
}
+ } else {
+ None
}
}
+const ATTRIBUTE_WHITELIST: &'static [&'static str] = &[
+ "export_name",
+ "lang",
+ "link_section",
+ "must_use",
+ "no_mangle",
+ "repr",
+ "unsafe_destructor_blind_to_params"
+];
+
fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
let mut attrs = String::new();
- for attr in &it.attrs {
- if let Some(s) = render_attribute(attr, false) {
+ for attr in &it.attrs.other_attrs {
+ let name = attr.name();
+ if !ATTRIBUTE_WHITELIST.contains(&&name.as_str()[..]) {
+ continue;
+ }
+ if let Some(s) = render_attribute(attr.meta()) {
attrs.push_str(&format!("#[{}]\n", s));
}
}
}
write!(w, "</span>")?;
write!(w, "</h3>\n")?;
- if let Some(ref dox) = i.impl_item.attrs.value("doc") {
+ if let Some(ref dox) = i.impl_item.doc_value() {
write!(w, "<div class='docblock'>{}</div>", Markdown(dox))?;
}
}
Some("macro"),
None,
None))?;
- render_stability_since_raw(w, it.stable_since(), None)?;
document(w, cx, it)
}
pub mod visit_lib;
pub mod test;
-use clean::Attributes;
+use clean::AttributesExt;
struct Output {
krate: clean::Crate,
!matches.opt_present("markdown-no-toc")),
(false, false) => {}
}
- let out = match acquire_input(input, externs, &matches) {
- Ok(out) => out,
- Err(s) => {
- println!("input error: {}", s);
- return 1;
- }
- };
- let Output { krate, passes, renderinfo } = out;
- info!("going to format");
- match matches.opt_str("w").as_ref().map(|s| &**s) {
- Some("html") | None => {
- html::render::run(krate, &external_html,
- output.unwrap_or(PathBuf::from("doc")),
- passes.into_iter().collect(),
- css_file_extension,
- renderinfo)
- .expect("failed to generate documentation");
- 0
- }
- Some(s) => {
- println!("unknown output format: {}", s);
- 1
+
+ let output_format = matches.opt_str("w");
+ let res = acquire_input(input, externs, &matches, move |out| {
+ let Output { krate, passes, renderinfo } = out;
+ info!("going to format");
+ match output_format.as_ref().map(|s| &**s) {
+ Some("html") | None => {
+ html::render::run(krate, &external_html,
+ output.unwrap_or(PathBuf::from("doc")),
+ passes.into_iter().collect(),
+ css_file_extension,
+ renderinfo)
+ .expect("failed to generate documentation");
+ 0
+ }
+ Some(s) => {
+ println!("unknown output format: {}", s);
+ 1
+ }
}
- }
+ });
+ res.unwrap_or_else(|s| {
+ println!("input error: {}", s);
+ 1
+ })
}
/// Looks inside the command line arguments to extract the relevant input format
/// and files and then generates the necessary rustdoc output for formatting.
-fn acquire_input(input: &str,
- externs: Externs,
- matches: &getopts::Matches) -> Result<Output, String> {
+fn acquire_input<R, F>(input: &str,
+ externs: Externs,
+ matches: &getopts::Matches,
+ f: F)
+ -> Result<R, String>
+where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
match matches.opt_str("r").as_ref().map(|s| &**s) {
- Some("rust") => Ok(rust_input(input, externs, matches)),
+ Some("rust") => Ok(rust_input(input, externs, matches, f)),
Some(s) => Err(format!("unknown input format: {}", s)),
- None => {
- Ok(rust_input(input, externs, matches))
- }
+ None => Ok(rust_input(input, externs, matches, f))
}
}
/// generated from the cleaned AST of the crate.
///
/// This form of input will run all of the plug/cleaning passes
-fn rust_input(cratefile: &str, externs: Externs, matches: &getopts::Matches) -> Output {
+fn rust_input<R, F>(cratefile: &str, externs: Externs, matches: &getopts::Matches, f: F) -> R
+where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
let mut default_passes = !matches.opt_present("no-defaults");
let mut passes = matches.opt_strs("passes");
let mut plugins = matches.opt_strs("plugins");
let cfgs = matches.opt_strs("cfg");
let triple = matches.opt_str("target");
let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
+ let crate_name = matches.opt_str("crate-name");
+ let plugin_path = matches.opt_str("plugin-path");
let cr = PathBuf::from(cratefile);
info!("starting to run rustc");
rustc_driver::monitor(move || {
use rustc::session::config::Input;
- tx.send(core::run_core(paths, cfgs, externs, Input::File(cr),
- triple, maybe_sysroot)).unwrap();
- });
- let (mut krate, renderinfo) = rx.recv().unwrap();
- info!("finished with rustc");
+ let (mut krate, renderinfo) =
+ core::run_core(paths, cfgs, externs, Input::File(cr), triple, maybe_sysroot);
- if let Some(name) = matches.opt_str("crate-name") {
- krate.name = name
- }
+ info!("finished with rustc");
- // Process all of the crate attributes, extracting plugin metadata along
- // with the passes which we are supposed to run.
- for attr in krate.module.as_ref().unwrap().attrs.list("doc") {
- match *attr {
- clean::Word(ref w) if "no_default_passes" == *w => {
- default_passes = false;
- },
- clean::NameValue(ref name, ref value) => {
- let sink = match &name[..] {
- "passes" => &mut passes,
- "plugins" => &mut plugins,
+ if let Some(name) = crate_name {
+ krate.name = name
+ }
+
+ // Process all of the crate attributes, extracting plugin metadata along
+ // with the passes which we are supposed to run.
+ for attr in krate.module.as_ref().unwrap().attrs.lists("doc") {
+ let name = attr.name().map(|s| s.as_str());
+ let name = name.as_ref().map(|s| &s[..]);
+ if attr.is_word() {
+ if name == Some("no_default_passes") {
+ default_passes = false;
+ }
+ } else if let Some(value) = attr.value_str() {
+ let sink = match name {
+ Some("passes") => &mut passes,
+ Some("plugins") => &mut plugins,
_ => continue,
};
- for p in value.split_whitespace() {
+ for p in value.as_str().split_whitespace() {
sink.push(p.to_string());
}
}
- _ => (),
}
- }
- if default_passes {
- for name in passes::DEFAULT_PASSES.iter().rev() {
- passes.insert(0, name.to_string());
+ if default_passes {
+ for name in passes::DEFAULT_PASSES.iter().rev() {
+ passes.insert(0, name.to_string());
+ }
}
- }
- // Load all plugins/passes into a PluginManager
- let path = matches.opt_str("plugin-path")
- .unwrap_or("/tmp/rustdoc/plugins".to_string());
- let mut pm = plugins::PluginManager::new(PathBuf::from(path));
- for pass in &passes {
- let plugin = match passes::PASSES.iter()
- .position(|&(p, ..)| {
- p == *pass
- }) {
- Some(i) => passes::PASSES[i].1,
- None => {
- error!("unknown pass {}, skipping", *pass);
- continue
- },
- };
- pm.add_plugin(plugin);
- }
- info!("loading plugins...");
- for pname in plugins {
- pm.load_plugin(pname);
- }
+ // Load all plugins/passes into a PluginManager
+ let path = plugin_path.unwrap_or("/tmp/rustdoc/plugins".to_string());
+ let mut pm = plugins::PluginManager::new(PathBuf::from(path));
+ for pass in &passes {
+ let plugin = match passes::PASSES.iter()
+ .position(|&(p, ..)| {
+ p == *pass
+ }) {
+ Some(i) => passes::PASSES[i].1,
+ None => {
+ error!("unknown pass {}, skipping", *pass);
+ continue
+ },
+ };
+ pm.add_plugin(plugin);
+ }
+ info!("loading plugins...");
+ for pname in plugins {
+ pm.load_plugin(pname);
+ }
+
+ // Run everything!
+ info!("Executing passes/plugins");
+ let krate = pm.run_plugins(krate);
- // Run everything!
- info!("Executing passes/plugins");
- let krate = pm.run_plugins(krate);
- Output { krate: krate, renderinfo: renderinfo, passes: passes }
+ tx.send(f(Output { krate: krate, renderinfo: renderinfo, passes: passes })).unwrap();
+ });
+ rx.recv().unwrap()
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::string::String;
-
use clean::{self, Item};
use plugins;
use fold;
use fold::DocFolder;
pub fn collapse_docs(krate: clean::Crate) -> plugins::PluginResult {
- let mut collapser = Collapser;
- let krate = collapser.fold_crate(krate);
- krate
+ Collapser.fold_crate(krate)
}
struct Collapser;
impl fold::DocFolder for Collapser {
fn fold_item(&mut self, mut i: Item) -> Option<Item> {
- let mut docstr = String::new();
- for attr in &i.attrs {
- if let clean::NameValue(ref x, ref s) = *attr {
- if "doc" == *x {
- docstr.push_str(s);
- docstr.push('\n');
- }
- }
- }
- let mut a: Vec<clean::Attribute> = i.attrs.iter().filter(|&a| match a {
- &clean::NameValue(ref x, _) if "doc" == *x => false,
- _ => true
- }).cloned().collect();
- if !docstr.is_empty() {
- a.push(clean::NameValue("doc".to_string(), docstr));
- }
- i.attrs = a;
+ i.attrs.collapse_doc_comments();
self.fold_item_recur(i)
}
}
+
+impl clean::Attributes {
+ pub fn collapse_doc_comments(&mut self) {
+ let mut doc_string = self.doc_strings.join("\n");
+ if doc_string.is_empty() {
+ self.doc_strings = vec![];
+ } else {
+ // FIXME(eddyb) Is this still needed?
+ doc_string.push('\n');
+ self.doc_strings = vec![doc_string];
+ }
+ }
+}
use rustc::util::nodemap::DefIdSet;
use std::mem;
-use clean::{self, Attributes};
+use clean::{self, AttributesExt, NestedAttributesExt};
use clean::Item;
use plugins;
use fold;
impl<'a> fold::DocFolder for Stripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
- if i.attrs.list("doc").has_word("hidden") {
+ if i.attrs.lists("doc").has_word("hidden") {
debug!("found one in strip_hidden; removing");
// use a dedicated hidden item for given item type if any
match i.inner {
use fold::{self, DocFolder};
pub fn unindent_comments(krate: clean::Crate) -> plugins::PluginResult {
- let mut cleaner = CommentCleaner;
- let krate = cleaner.fold_crate(krate);
- krate
+ CommentCleaner.fold_crate(krate)
}
struct CommentCleaner;
impl fold::DocFolder for CommentCleaner {
fn fold_item(&mut self, mut i: Item) -> Option<Item> {
- let mut avec: Vec<clean::Attribute> = Vec::new();
- for attr in &i.attrs {
- match attr {
- &clean::NameValue(ref x, ref s)
- if "doc" == *x => {
- avec.push(clean::NameValue("doc".to_string(),
- unindent(s)))
- }
- x => avec.push(x.clone())
- }
- }
- i.attrs = avec;
+ i.attrs.unindent_doc_comments();
self.fold_item_recur(i)
}
}
+impl clean::Attributes {
+ pub fn unindent_doc_comments(&mut self) {
+ for doc_string in &mut self.doc_strings {
+ *doc_string = unindent(doc_string);
+ }
+ }
+}
+
fn unindent(s: &str) -> String {
let lines = s.lines().collect::<Vec<&str> >();
let mut saw_first_line = false;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::cell::Cell;
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
use testing;
use rustc_lint;
use rustc::dep_graph::DepGraph;
-use rustc::hir::map as hir_map;
+use rustc::hir;
+use rustc::hir::intravisit;
use rustc::session::{self, config};
use rustc::session::config::{OutputType, OutputTypes, Externs};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_driver::driver::phase_2_configure_and_expand;
use rustc_metadata::cstore::CStore;
use rustc_resolve::MakeGlobMap;
+use rustc_trans::back::link;
+use syntax::ast;
use syntax::codemap::CodeMap;
use syntax::feature_gate::UnstableFeatures;
use errors;
use errors::emitter::ColorConfig;
-use core;
-use clean;
-use clean::Clean;
-use fold::DocFolder;
+use clean::Attributes;
use html::markdown;
-use passes;
-use visit_ast::RustdocVisitor;
#[derive(Clone, Default)]
pub struct TestOptions {
config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
let krate = panictry!(driver::phase_1_parse_input(&sess, &input));
- let driver::ExpansionResult { defs, mut hir_forest, analysis, .. } = {
+ let driver::ExpansionResult { defs, mut hir_forest, .. } = {
phase_2_configure_and_expand(
&sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(())
).expect("phase_2_configure_and_expand aborted in rustdoc!")
};
- let dep_graph = DepGraph::new(false);
+ let crate_name = crate_name.unwrap_or_else(|| {
+ link::find_crate_name(None, &hir_forest.krate().attrs, &input)
+ });
let opts = scrape_test_config(hir_forest.krate());
- let _ignore = dep_graph.in_ignore();
- let map = hir_map::map_crate(&mut hir_forest, defs);
-
- let ctx = core::DocContext {
- map: &map,
- maybe_typed: core::NotTyped(&sess),
- input: input,
- populated_all_crate_impls: Cell::new(false),
- external_traits: Default::default(),
- deref_trait_did: Cell::new(None),
- deref_mut_trait_did: Cell::new(None),
- access_levels: Default::default(),
- renderinfo: Default::default(),
- ty_substs: Default::default(),
- lt_substs: Default::default(),
- export_map: analysis.export_map,
- };
-
- let mut v = RustdocVisitor::new(&ctx);
- v.visit(ctx.map.krate());
- let mut krate = v.clean(&ctx);
- if let Some(name) = crate_name {
- krate.name = name;
- }
- let krate = passes::collapse_docs(krate);
- let krate = passes::unindent_comments(krate);
-
- let mut collector = Collector::new(krate.name.to_string(),
+ let mut collector = Collector::new(crate_name,
cfgs,
libs,
externs,
false,
opts);
- collector.fold_crate(krate);
+
+ {
+ let dep_graph = DepGraph::new(false);
+ let _ignore = dep_graph.in_ignore();
+ let map = hir::map::map_crate(&mut hir_forest, defs);
+ let krate = map.krate();
+ let mut hir_collector = HirCollector {
+ collector: &mut collector,
+ map: &map
+ };
+ hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
+ intravisit::walk_crate(this, krate);
+ });
+ }
test_args.insert(0, "rustdoctest".to_string());
}
}
-impl DocFolder for Collector {
- fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
- let current_name = match item.name {
- Some(ref name) if !name.is_empty() => Some(name.clone()),
- _ => typename_if_impl(&item)
- };
+struct HirCollector<'a, 'hir: 'a> {
+ collector: &'a mut Collector,
+ map: &'a hir::map::Map<'hir>
+}
- let pushed = current_name.map(|name| self.names.push(name)).is_some();
+impl<'a, 'hir> HirCollector<'a, 'hir> {
+ fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
+ name: String,
+ attrs: &[ast::Attribute],
+ nested: F) {
+ let has_name = !name.is_empty();
+ if has_name {
+ self.collector.names.push(name);
+ }
- if let Some(doc) = item.doc_value() {
- self.cnt = 0;
- markdown::find_testable_code(doc, &mut *self);
+ let mut attrs = Attributes::from_ast(attrs);
+ attrs.collapse_doc_comments();
+ attrs.unindent_doc_comments();
+ if let Some(doc) = attrs.doc_value() {
+ self.collector.cnt = 0;
+ markdown::find_testable_code(doc, self.collector);
}
- let ret = self.fold_item_recur(item);
- if pushed {
- self.names.pop();
+ nested(self);
+
+ if has_name {
+ self.collector.names.pop();
}
+ }
+}
+
+impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> {
+ fn nested_visit_map(&mut self) -> Option<&hir::map::Map<'hir>> {
+ Some(self.map)
+ }
+
+ fn visit_item(&mut self, item: &'hir hir::Item) {
+ let name = if let hir::ItemImpl(.., ref ty, _) = item.node {
+ hir::print::ty_to_string(ty)
+ } else {
+ item.name.to_string()
+ };
- return ret;
+ self.visit_testable(name, &item.attrs, |this| {
+ intravisit::walk_item(this, item);
+ });
+ }
- // FIXME: it would be better to not have the escaped version in the first place
- fn unescape_for_testname(mut s: String) -> String {
- // for refs `&foo`
- if s.contains("&") {
- s = s.replace("&", "&");
+ fn visit_trait_item(&mut self, item: &'hir hir::TraitItem) {
+ self.visit_testable(item.name.to_string(), &item.attrs, |this| {
+ intravisit::walk_trait_item(this, item);
+ });
+ }
- // `::&'a mut Foo::` looks weird, let's make it `::<&'a mut Foo>`::
- if let Some('&') = s.chars().nth(0) {
- s = format!("<{}>", s);
- }
- }
+ fn visit_impl_item(&mut self, item: &'hir hir::ImplItem) {
+ self.visit_testable(item.name.to_string(), &item.attrs, |this| {
+ intravisit::walk_impl_item(this, item);
+ });
+ }
- // either `<..>` or `->`
- if s.contains(">") {
- s.replace(">", ">")
- .replace("<", "<")
- } else {
- s
- }
- }
+ fn visit_foreign_item(&mut self, item: &'hir hir::ForeignItem) {
+ self.visit_testable(item.name.to_string(), &item.attrs, |this| {
+ intravisit::walk_foreign_item(this, item);
+ });
+ }
- fn typename_if_impl(item: &clean::Item) -> Option<String> {
- if let clean::ItemEnum::ImplItem(ref impl_) = item.inner {
- let path = impl_.for_.to_string();
- let unescaped_path = unescape_for_testname(path);
- Some(unescaped_path)
- } else {
- None
- }
- }
+ fn visit_variant(&mut self,
+ v: &'hir hir::Variant,
+ g: &'hir hir::Generics,
+ item_id: ast::NodeId) {
+ self.visit_testable(v.node.name.to_string(), &v.node.attrs, |this| {
+ intravisit::walk_variant(this, v, g, item_id);
+ });
+ }
+
+ fn visit_struct_field(&mut self, f: &'hir hir::StructField) {
+ self.visit_testable(f.name.to_string(), &f.attrs, |this| {
+ intravisit::walk_struct_field(this, f);
+ });
}
}
use rustc::hir;
use core;
-use clean::{self, Clean, Attributes};
+use clean::{self, AttributesExt, NestedAttributesExt};
use doctree::*;
// looks to me like the first two of these are actually
}
fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
- self.cx.tcx_opt().and_then(|tcx| {
- self.cx.map.opt_local_def_id(id)
- .and_then(|def_id| tcx.lookup_stability(def_id))
- .cloned()
- })
+ self.cx.tcx.map.opt_local_def_id(id)
+ .and_then(|def_id| self.cx.tcx.lookup_stability(def_id)).cloned()
}
fn deprecation(&self, id: ast::NodeId) -> Option<attr::Deprecation> {
- self.cx.tcx_opt().and_then(|tcx| {
- self.cx.map.opt_local_def_id(id)
- .and_then(|def_id| tcx.lookup_deprecation(def_id))
- })
+ self.cx.tcx.map.opt_local_def_id(id)
+ .and_then(|def_id| self.cx.tcx.lookup_deprecation(def_id))
}
pub fn visit(&mut self, krate: &hir::Crate) {
let orig_inside_public_path = self.inside_public_path;
self.inside_public_path &= vis == hir::Public;
for i in &m.item_ids {
- let item = self.cx.map.expect_item(i.id);
+ let item = self.cx.tcx.map.expect_item(i.id);
self.visit_item(item, None, &mut om);
}
self.inside_public_path = orig_inside_public_path;
glob: bool, om: &mut Module, please_inline: bool) -> bool {
fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
- while let Some(id) = cx.map.get_enclosing_scope(node) {
+ while let Some(id) = cx.tcx.map.get_enclosing_scope(node) {
node = id;
- let attrs = cx.map.attrs(node).clean(cx);
- if attrs.list("doc").has_word("hidden") {
+ if cx.tcx.map.attrs(node).lists("doc").has_word("hidden") {
return true;
}
if node == ast::CRATE_NODE_ID {
false
}
- let tcx = match self.cx.tcx_opt() {
- Some(tcx) => tcx,
- None => return false
- };
+ let tcx = self.cx.tcx;
let def = tcx.expect_def(id);
let def_did = def.def_id();
- let use_attrs = tcx.map.attrs(id).clean(self.cx);
+ let use_attrs = tcx.map.attrs(id);
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
- let is_no_inline = use_attrs.list("doc").has_word("no_inline") ||
- use_attrs.list("doc").has_word("hidden");
+ let is_no_inline = use_attrs.lists("doc").has_word("no_inline") ||
+ use_attrs.lists("doc").has_word("hidden");
// For cross-crate impl inlining we need to know whether items are
// reachable in documentation - a previously nonreachable item can be
// made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront)
if !def_did.is_local() && !is_no_inline {
- let attrs = clean::inline::load_attrs(self.cx, tcx, def_did);
- let self_is_hidden = attrs.list("doc").has_word("hidden");
+ let attrs = clean::inline::load_attrs(self.cx, def_did);
+ let self_is_hidden = attrs.lists("doc").has_word("hidden");
match def {
Def::Trait(did) |
Def::Struct(did) |
match it.node {
hir::ItemMod(ref m) => {
for i in &m.item_ids {
- let i = self.cx.map.expect_item(i.id);
+ let i = self.cx.tcx.map.expect_item(i.id);
self.visit_item(i, None, om);
}
}
// regardless of where they're located.
if !self.inlining {
let items = item_ids.iter()
- .map(|ii| self.cx.map.impl_item(ii.id).clone())
+ .map(|ii| self.cx.tcx.map.impl_item(ii.id).clone())
.collect();
let i = Impl {
unsafety: unsafety,
use std::cell::RefMut;
-use clean::{Attributes, Clean};
+use clean::{AttributesExt, NestedAttributesExt};
// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
// Updates node level and returns the updated level
fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLevel> {
- let attrs: Vec<_> = self.cx.tcx().get_attrs(did).iter()
- .map(|a| a.clean(self.cx))
- .collect();
- let is_hidden = attrs.list("doc").has_word("hidden");
+ let is_hidden = self.cx.tcx.get_attrs(did).lists("doc").has_word("hidden");
let old_level = self.access_levels.map.get(&did).cloned();
// Accessibility levels can only grow
os_imp::current_exe()
}
-/// An iterator over the arguments of a process, yielding a `String` value
+/// An iterator over the arguments of a process, yielding a [`String`] value
/// for each argument.
///
-/// This structure is created through the `std::env::args` method.
+/// This structure is created through the [`std::env::args`] method.
+///
+/// [`String`]: ../string/struct.String.html
+/// [`std::env::args`]: ./fn.args.html
#[stable(feature = "env", since = "1.0.0")]
pub struct Args { inner: ArgsOs }
-/// An iterator over the arguments of a process, yielding an `OsString` value
+/// An iterator over the arguments of a process, yielding an [`OsString`] value
/// for each argument.
///
-/// This structure is created through the `std::env::args_os` method.
+/// This structure is created through the [`std::env::args_os`] method.
+///
+/// [`OsString`]: ../ffi/struct.OsString.html
+/// [`std::env::args_os`]: ./fn.args_os.html
#[stable(feature = "env", since = "1.0.0")]
pub struct ArgsOs { inner: sys::args::Args }
///
/// The returned iterator will panic during iteration if any argument to the
/// process is not valid unicode. If this is not desired,
-/// use the `args_os` function instead.
+/// use the [`args_os`] function instead.
///
/// # Examples
///
/// println!("{}", argument);
/// }
/// ```
+///
+/// [`args_os`]: ./fn.args_os.html
#[stable(feature = "env", since = "1.0.0")]
pub fn args() -> Args {
Args { inner: args_os() }
inner: self.inner.duplicate()?
})
}
+
+ /// 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)
+ }
}
impl AsInner<fs_imp::File> for File {
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();
/// 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),
}
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 {
}
/// 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 {
}
/// 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.
}
/// 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 {
}
/// 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 {
/// 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 {
/// 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 {
impl SocketAddrV4 {
/// Creates a new socket address from the (ip, port) pair.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
SocketAddrV4 {
}
/// Returns the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn ip(&self) -> &Ipv4Addr {
unsafe {
}
/// Change the IP address associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
+ /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
+ /// ```
#[stable(feature = "sockaddr_setters", since = "1.9.0")]
pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
self.inner.sin_addr = *new_ip.as_inner()
}
/// Returns the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// assert_eq!(socket.port(), 8080);
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn port(&self) -> u16 {
ntoh(self.inner.sin_port)
}
/// Change the port number associated with this socket address.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::net::{SocketAddrV4, Ipv4Addr};
+ ///
+ /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+ /// socket.set_port(4242);
+ /// assert_eq!(socket.port(), 4242);
+ /// ```
#[stable(feature = "sockaddr_setters", since = "1.9.0")]
pub fn set_port(&mut self, new_port: u16) {
self.inner.sin_port = hton(new_port);
::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::*;
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 {
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;
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,
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<c::HANDLE> for File {
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();
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,
//
// 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)
}
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<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_str(&self.as_str())
- }
-}
-
-impl Decodable for Name {
- fn decode<D: Decoder>(d: &mut D) -> Result<Name, D::Error> {
- 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 {
}
pub fn span_for_name(&self, name: &str) -> Option<Span> {
for t in &self.ty_params {
- if t.ident.name.as_str() == name {
+ if t.ident.name == name {
return Some(t.span);
}
}
/// The set of MetaItems that define the compilation environment of the crate,
/// used to drive conditional compilation
-pub type CrateConfig = Vec<P<MetaItem>>;
+pub type CrateConfig = HashSet<(Name, Option<Symbol>)>;
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Crate {
#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialEq)]
pub enum NestedMetaItemKind {
/// A full MetaItem, for recursive meta items.
- MetaItem(P<MetaItem>),
+ MetaItem(MetaItem),
/// A literal.
///
/// E.g. "foo", 64, true
/// A spanned compile-time attribute item.
///
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
-pub type MetaItem = Spanned<MetaItemKind>;
+#[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<NestedMetaItem>),
+ List(Vec<NestedMetaItem>),
/// 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 (`{ .. }`).
/// A referencing operation (`&a` or `&mut a`)
AddrOf(Mutability, P<Expr>),
- /// A `break`, with an optional label to break
- Break(Option<SpannedIdent>),
+ /// A `break`, with an optional label to break, and an optional expression
+ Break(Option<SpannedIdent>, Option<P<Expr>>),
/// A `continue`, with an optional label
Continue(Option<SpannedIdent>),
/// A `return`, with an optional value to be returned
#[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<Vec<u8>>),
/// A byte char (`b'f'`)
/// 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),
}
/// 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<Expr>,
pub is_rw: bool,
pub is_indirect: bool,
/// 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<InlineAsmOutput>,
- pub inputs: Vec<(InternedString, P<Expr>)>,
- pub clobbers: Vec<InternedString>,
+ pub inputs: Vec<(Symbol, P<Expr>)>,
+ pub clobbers: Vec<Symbol>,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect,
}
}
-/// Meta-data associated with an item
-pub type Attribute = Spanned<Attribute_>;
/// Distinguishes between Attributes that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
#[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<MetaItem>,
+ pub value: MetaItem,
pub is_sugared_doc: bool,
+ pub span: Span,
}
/// TraitRef's appear in impls.
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};
}
enum AttrError {
- MultipleItem(InternedString),
- UnknownMetaItem(InternedString),
+ MultipleItem(Name),
+ UnknownMetaItem(Name),
MissingSince,
MissingFeature,
MultipleStabilityLevels,
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;
}
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;
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;
}
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;
impl NestedMetaItem {
/// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
- pub fn meta_item(&self) -> Option<&P<MetaItem>> {
+ pub fn meta_item(&self) -> Option<&MetaItem> {
match self.node {
NestedMetaItemKind::MetaItem(ref item) => Some(&item),
_ => None
/// 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<InternedString> {
+ pub fn name(&self) -> Option<Name> {
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<InternedString> {
+ pub fn value_str(&self) -> Option<Symbol> {
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<MetaItem>> {
+ pub fn word(&self) -> Option<&MetaItem> {
self.meta_item().and_then(|meta_item| if meta_item.is_word() {
Some(meta_item)
} else {
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<InternedString> {
+ pub fn value_str(&self) -> Option<Symbol> {
self.meta().value_str()
}
}
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<InternedString> {
+ pub fn value_str(&self) -> Option<Symbol> {
match self.node {
- MetaItemKind::NameValue(_, ref v) => {
+ MetaItemKind::NameValue(ref v) => {
match v.node {
ast::LitKind::Str(ref s, _) => Some((*s).clone()),
_ => None,
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,
}
}
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 {
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
pub fn with_desugared_doc<T, F>(&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)
/* Constructors */
-pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
- -> P<MetaItem> {
+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<MetaItem> {
+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<NestedMetaItem>) -> P<MetaItem> {
+pub fn mk_list_item(name: Name, items: Vec<NestedMetaItem>) -> 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<MetaItem> {
+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<MetaItem> {
- 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<NestedMetaItem>)
- -> P<MetaItem> {
- P(respan(sp, MetaItemKind::List(name, items)))
+pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec<NestedMetaItem>) -> MetaItem {
+ MetaItem { span: sp, name: name, node: MetaItemKind::List(items) }
}
-pub fn mk_spanned_word_item(sp: Span, name: InternedString) -> P<MetaItem> {
- 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 }
}
}
/// Returns an inner attribute with the given value.
-pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> 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<MetaItem>) -> 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<MetaItem>) -> 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<MetaItem>) -> 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<MetaItem>, 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<MetaItem>], 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 {
})
}
-pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
- -> Option<InternedString> {
+pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<Symbol> {
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<MetaItem>], name: &str)
- -> Option<InternedString> {
+pub fn last_meta_item_value_str_by_name(items: &[MetaItem], name: &str) -> Option<Symbol> {
items.iter()
.rev()
.find(|mi| mi.check_name(name))
/* Higher-level applications */
-pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
+pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
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<InternedString> {
+pub fn find_export_name_attr(diag: &Handler, attrs: &[Attribute]) -> Option<Symbol> {
attrs.iter().fold(None, |ia,attr| {
if attr.check_name("export_name") {
if let s@Some(_) = attr.value_str() {
/// 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"); });
/// 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);
// 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)
}),
}
}
},
- 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()))
}
}
}
#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Stability {
pub level: StabilityLevel,
- pub feature: InternedString,
+ pub feature: Symbol,
pub rustc_depr: Option<RustcDeprecation>,
}
#[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<InternedString>, issue: u32 },
- Stable { since: InternedString },
+ Unstable { reason: Option<Symbol>, 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<InternedString>,
- pub note: Option<InternedString>,
+ pub since: Option<Symbol>,
+ pub note: Option<Symbol>,
}
impl StabilityLevel {
'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
}
mark_used(attr);
if let Some(metas) = attr.meta_item_list() {
- let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+ let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
return false
}
};
- match tag {
+ match &*tag.as_str() {
"rustc_deprecated" => {
if rustc_depr.is_some() {
span_err!(diagnostic, item_sp, E0540,
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 },
_ => {
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 },
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,
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 },
_ => {
}
depr = if let Some(metas) = attr.meta_item_list() {
- let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+ let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
if item.is_some() {
handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
return false
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 },
_ => {
find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
}
-pub fn require_unique_names(diagnostic: &Handler, metas: &[P<MetaItem>]) {
+pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) {
let mut set = HashSet::new();
for meta in metas {
let name = meta.name();
/// structure layout, and `packed` to remove padding.
pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> {
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() {
}
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),
#[cfg(test)]
mod tests {
use super::*;
+ use symbol::keywords;
use std::rc::Rc;
#[test]
#[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 };
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) };
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) };
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 };
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;
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
},
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
};
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();
use ext::build::AstBuilder;
use parse::token;
use ptr::P;
+use symbol::Symbol;
use tokenstream::{TokenTree};
use util::small_vector::SmallVector;
));
}
});
- 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![
let (count, expr) =
with_registered_diagnostics(|diagnostics| {
let descriptions: Vec<P<ast::Expr>> =
- 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();
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
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;
pub depth: usize,
pub backtrace: ExpnId,
pub module: Rc<ModuleData>,
-
- // 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;
depth: 0,
backtrace: NO_EXPANSION,
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
- no_noninline_mod: false,
+ directory_ownership: DirectoryOwnership::Owned,
},
}
}
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;
}
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<ast::Ident> {
let mut v = Vec::new();
return v
}
pub fn name_of(&self, st: &str) -> ast::Name {
- token::intern(st)
+ Symbol::intern(st)
}
}
/// 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<ast::Expr>, err_msg: &str)
- -> Option<Spanned<(InternedString, ast::StrStyle)>> {
+ -> Option<Spanned<(Symbol, ast::StrStyle)>> {
// 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();
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)
}
pub fn expr_to_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &str)
- -> Option<(InternedString, ast::StrStyle)> {
+ -> Option<(Symbol, ast::StrStyle)> {
expr_to_spanned_string(cx, expr, err_msg).map(|s| s.node)
}
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 {
fn expr_vec(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>;
fn expr_vec_ng(&self, sp: Span) -> P<ast::Expr>;
fn expr_vec_slice(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>;
- fn expr_str(&self, sp: Span, s: InternedString) -> P<ast::Expr>;
+ fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr>;
fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr>;
fn expr_none(&self, sp: Span) -> P<ast::Expr>;
fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>;
- fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr>;
+ fn expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr>;
fn expr_unreachable(&self, span: Span) -> P<ast::Expr>;
fn expr_ok(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>;
generics: Generics) -> P<ast::Item>;
fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> P<ast::Item>;
- fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute;
+ fn attribute(&self, sp: Span, mi: ast::MetaItem) -> ast::Attribute;
- fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem>;
+ 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<ast::NestedMetaItem> )
- -> P<ast::MetaItem>;
+ -> ast::MetaItem;
fn meta_name_value(&self,
sp: Span,
- name: InternedString,
+ name: ast::Name,
value: ast::LitKind)
- -> P<ast::MetaItem>;
+ -> ast::MetaItem;
fn item_use(&self, sp: Span,
vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item>;
fn expr_vec_slice(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
self.expr_addr_of(sp, self.expr_vec(sp, exprs))
}
- fn expr_str(&self, sp: Span, s: InternedString) -> P<ast::Expr> {
+ fn expr_str(&self, sp: Span, s: Symbol) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked))
}
fn expr_break(&self, sp: Span) -> P<ast::Expr> {
- self.expr(sp, ast::ExprKind::Break(None))
+ self.expr(sp, ast::ExprKind::Break(None, None))
}
self.expr(sp, ast::ExprKind::Tup(exprs))
}
- fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr> {
+ fn expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr> {
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);
}
fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
- 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<ast::Expr>) -> P<ast::Expr> {
self.item_ty_poly(span, name, ty, Generics::default())
}
- fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> 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<ast::MetaItem> {
+ 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<ast::NestedMetaItem>)
- -> P<ast::MetaItem> {
+ fn meta_list(&self, sp: Span, name: ast::Name, mis: Vec<ast::NestedMetaItem>)
+ -> ast::MetaItem {
attr::mk_spanned_list_item(sp, name, mis)
}
- fn meta_name_value(&self, sp: Span, name: InternedString, value: ast::LitKind)
- -> P<ast::MetaItem> {
+ 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))
}
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;
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();
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)
}
};
attr::mark_used(&attr);
- let name = intern(&attr.name());
+ let name = attr.name();
self.cx.bt_push(ExpnInfo {
call_site: attr.span,
callee: NameAndSpan {
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)
}
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
- 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
}
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);
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.
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;
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(),
}],
},
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};
}
use parse::{self, token, classify};
use ptr::P;
use std::rc::Rc;
+ use symbol::Symbol;
use tokenstream::{self, TokenTree};
impl_to_tokens_slice! { P<ast::Item>, [] }
impl_to_tokens_slice! { ast::Arg, [TokenTree::Token(DUMMY_SP, token::Comma)] }
- impl ToTokens for P<ast::MetaItem> {
+ impl ToTokens for ast::MetaItem {
fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
let nt = token::NtMeta(self.clone());
vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))]
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
impl ToTokens for str {
fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
- 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)
}
}
panictry!(parser.parse_block())
}
-pub fn parse_meta_item_panic(parser: &mut Parser) -> P<ast::MetaItem> {
+pub fn parse_meta_item_panic(parser: &mut Parser) -> ast::MetaItem {
panictry!(parser.parse_meta_item())
}
base::MacEager::expr(expanded)
}
-fn ids_ext(strs: Vec<String> ) -> Vec<ast::Ident> {
- strs.iter().map(|str| str_to_ident(&(*str))).collect()
+fn ids_ext(strs: Vec<String>) -> Vec<ast::Ident> {
+ 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<ast::Expr> {
- 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"),
// Lift a name to the expr that evaluates to that name
fn mk_name(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P<ast::Expr> {
- 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"),
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;
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<base::MacResult+'static> {
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])
let mod_path = &cx.current_expansion.module.mod_path;
let string = mod_path.iter().map(|x| x.to_string()).collect::<Vec<String>>().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
};
// 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>,
// 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,
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};
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.
/// 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![
"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)
}
},
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)
}
},
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;
/// 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),+
}
// 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)),
(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! (
(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)
impl GatedCfg {
pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
- let name = cfg.name();
+ let name = &*cfg.name().as_str();
GATED_CFGS.iter()
.position(|info| info.0 == name)
.map(|idx| {
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 {
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,
}
}),
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");
}
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 {
}
}
}
+ ast::ExprKind::Break(_, Some(_)) => {
+ gate_feature_post!(&self, loop_break_value, e.span,
+ "`break` with a value is experimental");
+ }
_ => {}
}
visit::walk_expr(self, e);
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;
noop_fold_crate(c, self)
}
- fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
+ fn fold_meta_items(&mut self, meta_items: Vec<MetaItem>) -> Vec<MetaItem> {
noop_fold_meta_items(meta_items, self)
}
noop_fold_meta_list_item(list_item, self)
}
- fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
+ fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
noop_fold_meta_item(meta_item, self)
}
}
}
-pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T)
- -> Vec<P<MetaItem>> {
+pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<MetaItem>, fld: &mut T) -> Vec<MetaItem> {
meta_items.move_map(|x| fld.fold_meta_item(x))
}
})
}
-pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
- 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<T: Folder>(attr: Attribute, fld: &mut T) -> Option<Attribute> {
+ 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),
})
}
}
}
-pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
- 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<T: Folder>(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<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg {
});
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)))
#[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::*;
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)
#![feature(associated_consts)]
#![feature(const_fn)]
#![feature(libc)]
+#![feature(optin_builtin_traits)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(str_escape)]
pub mod diagnostic_list;
pub mod util {
- pub mod interner;
pub mod lev_distance;
pub mod node_count;
pub mod parser;
pub mod show_span;
pub mod std_inject;
pub mod str;
+pub mod symbol;
pub mod test;
pub mod tokenstream;
pub mod visit;
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> {
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");
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,
- },
})
}
}
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 {
///
/// 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<ast::MetaItem>> {
+ 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()),
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) ;
// 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;
/// 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`
if string == "_" {
None
} else {
- Some(token::intern(string))
+ Some(Symbol::intern(string))
}
})
}
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
};
} else {
string.into()
};
- token::DocComment(token::intern(&string[..]))
+ token::DocComment(Symbol::intern(&string[..]))
} else {
token::Comment
};
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
token::Underscore
} else {
// FIXME: perform NFKC normalization here. (Issue #2253)
- token::Ident(str_to_ident(string))
+ token::Ident(Ident::from_str(string))
}
}));
}
// 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;
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();
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();
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));
let id = if valid {
self.name_from(start)
} else {
- token::intern("?")
+ Symbol::intern("?")
};
self.bump(); // advance ch past token
return token::Byte(id);
let id = if valid {
self.name_from(start)
} else {
- token::intern("??")
+ Symbol::intern("??")
};
self.bump();
return token::ByteStr(id);
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;
&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();
// 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),
// 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]
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]
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]
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]
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]
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]
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));
}}
}
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]
_ => 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]
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")));
}
}
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;
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
}
}
}
+#[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_<thing>_from_<source>
// where <thing> includes crate, expr, item, stmt, tts, and one that
// uses a HOF to parse anything, and <source> includes file and
}
pub fn parse_meta_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
- -> PResult<'a, P<ast::MetaItem>> {
+ -> PResult<'a, ast::MetaItem> {
new_parser_from_source_str(sess, name, source).parse_meta_item()
}
/// 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<String>,
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
}
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<Symbol>, 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..]))
ast::LitKind::FloatUnsuffixed(data)
}
- None => ast::LitKind::FloatUnsuffixed(data)
}
}
-pub fn float_lit(s: &str, suffix: Option<InternedString>,
- sd: &Handler, sp: Span) -> ast::LitKind {
+pub fn float_lit(s: &str, suffix: Option<Symbol>, 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::<String>();
- 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`
Rc::new(res)
}
-pub fn integer_lit(s: &str,
- suffix: Option<InternedString>,
- sd: &Handler,
- sp: Span)
- -> ast::LitKind {
+pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> ast::LitKind {
// s can only be ascii, byte indexing is fine
let s2 = s.chars().filter(|&c| c != '_').collect::<String>();
}
// 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)
}
}
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),
"u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
"u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
"u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
- _ => {
+ suf => {
// i<digits> and u<digits> look like widths, so lets
// give an error message along those lines
if looks_like_width_suffix(&['i', 'u'], suf) {
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};
global: false,
segments: vec![
ast::PathSegment {
- identifier: str_to_ident("a"),
+ identifier: Ident::from_str("a"),
parameters: ast::PathParameters::none(),
}
],
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(),
}
]
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)) {
(
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[..];
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),
}
},
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),
})),
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),
global: false,
segments: vec![
ast::PathSegment {
- identifier: str_to_ident("d"),
+ identifier: Ident::from_str("d"),
parameters: ast::PathParameters::none(),
}
],
global:false,
segments: vec![
ast::PathSegment {
- identifier: str_to_ident("b"),
+ identifier: Ident::from_str("b"),
parameters: ast::PathParameters::none(),
}
],
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)}));
// 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 {
global:false,
segments: vec![
ast::PathSegment {
- identifier:
- str_to_ident("i32"),
+ identifier: Ident::from_str("i32"),
parameters: ast::PathParameters::none(),
}
],
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)
global:false,
segments: vec![
ast::PathSegment {
- identifier:
- str_to_ident(
- "b"),
+ identifier: Ident::from_str("b"),
parameters:
ast::PathParameters::none(),
}
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::<Vec<_>>();
let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
assert_eq!(&docs[..], b);
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]
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};
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;
flags Restrictions: u8 {
const RESTRICTION_STMT_EXPR = 1 << 0,
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
- const NO_NONINLINE_MOD = 1 << 2,
}
}
/// extra detail when the same error is seen twice
pub obsolete_set: HashSet<ObsoleteSyntax>,
/// 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.
}
pub struct ModulePathSuccess {
- pub path: ::std::path::PathBuf,
- pub owns_directory: bool,
+ pub path: PathBuf,
+ pub directory_ownership: DirectoryOwnership,
+ warn: bool,
}
pub struct ModulePathError {
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(),
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
}
&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 {
// 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 {
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
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::<f64>().ok() {
Some(f) => f,
})));
} 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();
/// 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",
};
}
} 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),
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 {
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<PathBuf> {
- ::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 .
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 {:?}",
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);
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(),
};
&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 {
/// 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<ast::Attribute> )> {
- 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<ast::Attribute> )> {
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: ");
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)?;
})
}
- pub fn parse_optional_str(&mut self)
- -> Option<(InternedString,
- ast::StrStyle,
- Option<ast::Name>)> {
+ pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
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;
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)]
NtTy(P<ast::Ty>),
NtIdent(ast::SpannedIdent),
/// Stuff inside brackets for attributes
- NtMeta(P<ast::MetaItem>),
+ NtMeta(ast::MetaItem),
NtPath(ast::Path),
NtTT(tokenstream::TokenTree),
// These are not exposed to macros, but are used by quasiquote.
}
}
}
-
-// 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: FnOnce(&mut IdentInterner) -> T>(f: F) -> T {
- thread_local!(static KEY: RefCell<IdentInterner> = {
- 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<str>,
-}
-
-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<InternedString> 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<str> 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<InternedString> 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: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
- Ok(intern(&d.read_str()?).as_str())
- }
-}
-
-impl Encodable for InternedString {
- fn encode<S: Encoder>(&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))*/
-}
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};
use print::pp::Breaks::{Consistent, Inconsistent};
use ptr::P;
use std_inject;
+use symbol::{Symbol, keywords};
use tokenstream::{self, TokenTree};
use std::ascii;
// 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));
}
_ => ()
}
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));
&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") }
}
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());
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(), "#[")),
}
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[..],
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"));
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));
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());
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(())
}));
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(),
#[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,
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
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,
}
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,
}));
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,
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ s.emit_str(&self.as_str())
+ }
+}
+
+impl Decodable for Symbol {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
+ 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<Box<str>, Symbol>,
+ strings: Vec<Box<str>>,
+}
+
+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: FnOnce(&mut Interner) -> T>(f: F) -> T {
+ thread_local!(static INTERNER: RefCell<Interner> = {
+ 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: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
+ Ok(Symbol::intern(&d.read_str()?).as_str())
+ }
+}
+
+impl Encodable for InternedString {
+ fn encode<S: Encoder>(&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));
+ }
+}
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<InternedString>),
+ Yes(Option<Symbol>),
}
struct Test {
span: Span,
- path: Vec<ast::Ident> ,
+ path: Vec<Ident> ,
bench: bool,
ignore: bool,
should_panic: ShouldPanic
struct TestCtxt<'a> {
sess: &'a ParseSess,
span_diagnostic: &'a errors::Handler,
- path: Vec<ast::Ident>,
+ path: Vec<Ident>,
ext_cx: ExtCtxt<'a>,
testfns: Vec<Test>,
- reexport_test_harness_main: Option<InternedString>,
+ reexport_test_harness_main: Option<Symbol>,
is_test_crate: bool,
// top-level re-export submodule, filled out after folding is finished
- toplevel_reexport: Option<ast::Ident>,
+ toplevel_reexport: Option<Ident>,
}
// Traverse the crate, collecting all the test functions, eliding any
struct TestHarnessGenerator<'a> {
cx: TestCtxt<'a>,
- tests: Vec<ast::Ident>,
+ tests: Vec<Ident>,
// 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> {
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(),
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { mac }
}
-fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec<ast::Ident>,
- tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P<ast::Item>, ast::Ident) {
- let super_ = token::str_to_ident("super");
+fn mk_reexport_mod(cx: &mut TestCtxt,
+ parent: ast::NodeId,
+ tests: Vec<Ident>,
+ tested_submods: Vec<(Ident, Ident)>)
+ -> (P<ast::Item>, 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,
items: items,
};
- let sym = token::gensym_ident("__test_reexports");
+ let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports"));
let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent };
cx.ext_cx.current_expansion.mark = cx.ext_cx.resolver.get_module_scope(parent);
let it = cx.ext_cx.monotonic_expander().fold_item(P(ast::Item {
fn generate_test_harness(sess: &ParseSess,
resolver: &mut Resolver,
- reexport_test_harness_main: Option<InternedString>,
+ reexport_test_harness_main: Option<Symbol>,
krate: ast::Crate,
sd: &errors::Handler) -> ast::Crate {
// Remove the entry points
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,
}
let info = ExpnInfo {
call_site: DUMMY_SP,
callee: NameAndSpan {
- format: MacroAttribute(intern("test")),
+ format: MacroAttribute(Symbol::intern("test")),
span: None,
allow_internal_unstable: true,
}
*/
fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
- 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,
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![]));
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,
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 {
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 <ident> = __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,
codemap::Spanned { node: t, span: DUMMY_SP }
}
-fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
+fn path_node(ids: Vec<Ident>) -> ast::Path {
ast::Path {
span: DUMMY_SP,
global: false,
}
}
-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::<Vec<String>>().join("::")
}
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
}
}
// 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,
};
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])
}
use parse;
use parse::token::{self, Token, Lit, Nonterminal};
use print::pprust;
+use symbol::Symbol;
use std::fmt;
use std::iter::*;
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,
}))
}
pub fn maybe_str(&self) -> Option<ast::Lit> {
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,
})
}
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,
#[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;
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);
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);
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);
}
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 {
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,
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Rc<str>, Name>,
- strings: Vec<Rc<str>>,
-}
-
-/// When traits can extend traits, we should extend index<Name,T> 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<str> {
- self.strings[name.0 as usize].clone()
- }
-
- pub fn find(&self, string: &str) -> Option<Name> {
- 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");
- }
-}
// 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 {
/// to one-third of the given word
pub fn find_best_match_for_name<'a, T>(iter_names: T,
lookup: &str,
- dist: Option<usize>) -> Option<InternedString>
- where T: Iterator<Item = &'a Name> {
+ dist: Option<usize>) -> Option<Symbol>
+ where T: Iterator<Item = &'a Symbol> {
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,
}
})
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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.
// 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;
})
}
-/// Convert a vector of strings to a vector of ast::Ident's
-pub fn strs_to_idents(ids: Vec<&str> ) -> Vec<ast::Ident> {
- 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<Ident> {
+ ids.iter().map(|u| Ident::from_str(*u)).collect()
}
/// Does the given string match the pattern? whitespace in the first string
}
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) => {
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;
})
.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();
// 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 '+'");
};
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,
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 '+'");
}
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");
}
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,
},
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,
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;
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);
}
}
}
- base::MacEager::expr(cx.expr_str(sp, token::intern_and_get_ident(&accumulator[..])))
+ base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
}
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;
}
}
}
- let res = str_to_ident(&res_str);
+ let res = ast::Ident::from_str(&res_str);
struct Result {
ident: ast::Ident,
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,
_ => 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,
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,
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,
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,
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,
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,
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,
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,
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,
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 {
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) {
pub struct CustomDerive {
inner: fn(TokenStream) -> TokenStream,
- attrs: Vec<InternedString>,
+ attrs: Vec<ast::Name>,
}
impl CustomDerive {
- pub fn new(inner: fn(TokenStream) -> TokenStream,
- attrs: Vec<InternedString>)
- -> CustomDerive {
+ pub fn new(inner: fn(TokenStream) -> TokenStream, attrs: Vec<ast::Name>) -> CustomDerive {
CustomDerive { inner: inner, attrs: attrs }
}
}
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};
// We want to make sure we have the expn_id set so that we can use unstable methods
let span = Span { expn_id: cx.backtrace(), ..span };
- let name = cx.expr_lit(span,
- ast::LitKind::Str(ident.name.as_str(), ast::StrStyle::Cooked));
- let builder = token::str_to_ident("builder");
+ let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
+ let builder = Ident::from_str("builder");
let builder_expr = cx.expr_ident(span, builder.clone());
let fmt = substr.nonself_args[0].clone();
if !is_struct {
// tuple struct/"normal" variant
let expr =
- cx.expr_method_call(span, fmt, token::str_to_ident("debug_tuple"), vec![name]);
+ cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
let expr = cx.expr_method_call(span,
builder_expr.clone(),
- token::str_to_ident("field"),
+ Ident::from_str("field"),
vec![field]);
// Use `let _ = expr;` to avoid triggering the
} else {
// normal struct/struct variant
let expr =
- cx.expr_method_call(span, fmt, token::str_to_ident("debug_struct"), vec![name]);
+ cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
let name = cx.expr_lit(field.span,
- ast::LitKind::Str(field.name.unwrap().name.as_str(),
+ ast::LitKind::Str(field.name.unwrap().name,
ast::StrStyle::Cooked));
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
- token::str_to_ident("field"),
+ Ident::from_str("field"),
vec![name, field]);
stmts.push(stmt_let_undescore(cx, span, expr));
}
_ => 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);
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,
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)])
}
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| {
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)"),
fields: &StaticFields,
mut getarg: F)
-> P<Expr>
- where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P<Expr>
+ where F: FnMut(&mut ExtCtxt, Span, Symbol, usize) -> P<Expr>
{
match *fields {
Unnamed(ref fields, is_tuple) => {
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();
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();
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,
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,
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,
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()]);
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])
}
}
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"),
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)]))
}
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;
attrs.extend(item.attrs
.iter()
.filter(|a| {
- match &a.name()[..] {
+ match &*a.name().as_str() {
"allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
_ => false,
}
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());
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 {
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,
},
}
};
+ 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
});
// 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
}))];
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]
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)
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));
}
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
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 {
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);
// 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| {
// 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| {
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,
},
};
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();
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,
}
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,
},
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;
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,
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)
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),
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)
}
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;
/// Translate the accumulated string literals to a literal expression
fn trans_literal_string(&mut self) -> P<ast::Expr> {
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)
}
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 {
// 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.
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<NamedSyntaxExtension>,
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));
)* }
}
}
// 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);
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<InternedString>,
+ attrs: Vec<ast::Name>,
}
struct CollectCustomDerives<'a> {
in_root: bool,
handler: &'a errors::Handler,
is_proc_macro_crate: bool,
+ is_test_crate: bool,
}
pub fn modify(sess: &ParseSess,
resolver: &mut ::syntax::ext::base::Resolver,
mut krate: ast::Crate,
is_proc_macro_crate: bool,
+ is_test_crate: bool,
num_crate_types: usize,
handler: &errors::Handler,
features: &Features) -> ast::Crate {
in_root: true,
handler: handler,
is_proc_macro_crate: is_proc_macro_crate,
+ is_test_crate: is_test_crate,
};
visit::walk_crate(&mut collect, &krate);
attributes found");
}
+ if self.is_test_crate {
+ self.handler.span_err(attr.span(),
+ "`--test` cannot be used with proc-macro crates");
+ return;
+ }
+
if !self.is_proc_macro_crate {
self.handler.span_err(attr.span(),
"the `#[proc_macro_derive]` attribute is \
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");
}
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::<Vec<_>>()
+ cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
);
(path, trait_name, attrs)
}).map(|(path, trait_name, attrs)| {
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
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;
#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"
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
return wrap(Type::getMetadataTy(*unwrap(C)));
}
-extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
+static Attribute::AttrKind
+from_rust(LLVMRustAttribute kind) {
+ switch (kind) {
+ case AlwaysInline:
+ return Attribute::AlwaysInline;
+ case ByVal:
+ return Attribute::ByVal;
+ case Cold:
+ return Attribute::Cold;
+ case InlineHint:
+ return Attribute::InlineHint;
+ case MinSize:
+ return Attribute::MinSize;
+ case Naked:
+ return Attribute::Naked;
+ case NoAlias:
+ return Attribute::NoAlias;
+ case NoCapture:
+ return Attribute::NoCapture;
+ case NoInline:
+ return Attribute::NoInline;
+ case NonNull:
+ return Attribute::NonNull;
+ case NoRedZone:
+ return Attribute::NoRedZone;
+ case NoReturn:
+ return Attribute::NoReturn;
+ case NoUnwind:
+ return Attribute::NoUnwind;
+ case OptimizeForSize:
+ return Attribute::OptimizeForSize;
+ case ReadOnly:
+ return Attribute::ReadOnly;
+ case SExt:
+ return Attribute::SExt;
+ case StructRet:
+ return Attribute::StructRet;
+ case UWTable:
+ return Attribute::UWTable;
+ case ZExt:
+ return Attribute::ZExt;
+ default:
+ llvm_unreachable("bad AttributeKind");
+ }
+}
+
+extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, LLVMRustAttribute attr) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
- AttrBuilder B;
- B.addRawValue(Val);
+ Attribute Attr = Attribute::get(Call->getContext(), from_rust(attr));
+ AttrBuilder B(Attr);
Call.setAttributes(
Call.getAttributes().addAttributes(Call->getContext(), index,
AttributeSet::get(Call->getContext(),
index, B)));
}
-
extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
- unsigned idx,
- uint64_t b)
+ unsigned index,
+ uint64_t bytes)
{
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
- B.addDereferenceableAttr(b);
+ B.addDereferenceableAttr(bytes);
Call.setAttributes(
- Call.getAttributes().addAttributes(Call->getContext(), idx,
+ Call.getAttributes().addAttributes(Call->getContext(), index,
AttributeSet::get(Call->getContext(),
- idx, B)));
+ index, B)));
}
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
unsigned index,
- uint64_t Val)
+ LLVMRustAttribute attr)
{
Function *A = unwrap<Function>(Fn);
- AttrBuilder B;
- B.addRawValue(Val);
+ Attribute Attr = Attribute::get(A->getContext(), from_rust(attr));
+ AttrBuilder B(Attr);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
-extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn,
- unsigned index,
- const char *Name)
-{
- Function *F = unwrap<Function>(Fn);
- AttrBuilder B;
- B.addAttribute(Name);
- F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
-}
-
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
unsigned index,
const char *Name,
extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
unsigned index,
- uint64_t Val)
+ LLVMRustAttribute attr)
{
- Function *A = unwrap<Function>(Fn);
- const AttributeSet PAL = A->getAttributes();
- AttrBuilder B(Val);
+ Function *F = unwrap<Function>(Fn);
+ const AttributeSet PAL = F->getAttributes();
+ Attribute Attr = Attribute::get(F->getContext(), from_rust(attr));
+ AttrBuilder B(Attr);
const AttributeSet PALnew =
- PAL.removeAttributes(A->getContext(), index,
- AttributeSet::get(A->getContext(), index, B));
- A->setAttributes(PALnew);
-}
-
-extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn,
- unsigned index,
- const char *Name)
-{
- Function *f = unwrap<Function>(fn);
- LLVMContext &C = f->getContext();
- AttrBuilder B;
- B.addAttribute(Name);
- AttributeSet to_remove = AttributeSet::get(C, index, B);
-
- AttributeSet attrs = f->getAttributes();
- f->setAttributes(attrs.removeAttributes(f->getContext(),
- index,
- to_remove));
+ PAL.removeAttributes(F->getContext(), index,
+ AttributeSet::get(F->getContext(), index, B));
+ F->setAttributes(PALnew);
}
// enable fpmath flag UnsafeAlgebra
extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
LLVMSetLinkage(V, from_rust(RustLinkage));
}
+
+extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
+ return wrap(&unwrap(V)->getContext());
+}
Failure
};
+enum LLVMRustAttribute {
+ AlwaysInline = 0,
+ ByVal = 1,
+ Cold = 2,
+ InlineHint = 3,
+ MinSize = 4,
+ Naked = 5,
+ NoAlias = 6,
+ NoCapture = 7,
+ NoInline = 8,
+ NonNull = 9,
+ NoRedZone = 10,
+ NoReturn = 11,
+ NoUnwind = 12,
+ OptimizeForSize = 13,
+ ReadOnly = 14,
+ SExt = 15,
+ StructRet = 16,
+ UWTable = 17,
+ ZExt = 18,
+};
+
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
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'");
}
}
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;
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)));
}
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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+#[proc_macro_derive(A)]
+//~^ ERROR: `--test` cannot be used with proc-macro crates
+pub fn foo1(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ "".parse().unwrap()
+}
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() {
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,
}
// 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
}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub mod bar {
- pub fn foo() {}
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// 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();
- pub struct US;
- pub enum E {
- V {},
- TV(),
- UV,
- }
-
- pub struct Item;
-}
-
-pub mod xm1 {
- pub use ::c::*;
- pub type S = ::c::Item;
-}
-pub mod xm2 {
- pub use ::c::*;
- pub const S: ::c::Item = ::c::Item;
-}
-
-pub mod xm3 {
- pub use ::c::*;
- pub type TS = ::c::Item;
-}
-pub mod xm4 {
- pub use ::c::*;
- pub const TS: ::c::Item = ::c::Item;
-}
-
-pub mod xm5 {
- pub use ::c::*;
- pub type US = ::c::Item;
-}
-pub mod xm6 {
- pub use ::c::*;
- pub const US: ::c::Item = ::c::Item;
-}
-
-pub mod xm7 {
- pub use ::c::E::*;
- pub type V = ::c::Item;
-}
-pub mod xm8 {
- pub use ::c::E::*;
- pub const V: ::c::Item = ::c::Item;
-}
-
-pub mod xm9 {
- pub use ::c::E::*;
- pub type TV = ::c::Item;
-}
-pub mod xmA {
- pub use ::c::E::*;
- pub const TV: ::c::Item = ::c::Item;
-}
-
-pub mod xmB {
- pub use ::c::E::*;
- pub type UV = ::c::Item;
-}
-pub mod xmC {
- pub use ::c::E::*;
- pub const UV: ::c::Item = ::c::Item;
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
-}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod c {
+ pub struct S {}
+ pub struct TS();
+ pub struct US;
+ pub enum E {
+ V {},
+ TV(),
+ UV,
+ }
+
+ pub struct Item;
+}
+
+pub mod xm1 {
+ pub use ::c::*;
+ pub type S = ::c::Item;
+}
+pub mod xm2 {
+ pub use ::c::*;
+ pub const S: ::c::Item = ::c::Item;
+}
+
+pub mod xm3 {
+ pub use ::c::*;
+ pub type TS = ::c::Item;
+}
+pub mod xm4 {
+ pub use ::c::*;
+ pub const TS: ::c::Item = ::c::Item;
+}
+
+pub mod xm5 {
+ pub use ::c::*;
+ pub type US = ::c::Item;
+}
+pub mod xm6 {
+ pub use ::c::*;
+ pub const US: ::c::Item = ::c::Item;
+}
+
+pub mod xm7 {
+ pub use ::c::E::*;
+ pub type V = ::c::Item;
+}
+pub mod xm8 {
+ pub use ::c::E::*;
+ pub const V: ::c::Item = ::c::Item;
+}
+
+pub mod xm9 {
+ pub use ::c::E::*;
+ pub type TV = ::c::Item;
+}
+pub mod xmA {
+ pub use ::c::E::*;
+ pub const TV: ::c::Item = ::c::Item;
+}
+
+pub mod xmB {
+ pub use ::c::E::*;
+ pub type UV = ::c::Item;
+}
+pub mod xmC {
+ pub use ::c::E::*;
+ pub const UV: ::c::Item = ::c::Item;
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type="metadata"]
+
+pub struct Foo {
+ pub field: i32,
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,
+}
let _ = cf as *const Bar;
//~^ ERROR casting
//~^^ NOTE vtable kinds
+
+ vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
+ //~^ ERROR casting `&{float}` as `f32` is invalid
+ //~| NOTE cannot cast `&{float}` as `f32`
+ //~| NOTE did you mean `*s`?
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+// error-pattern: will become a hard error
+// error-pattern: compilation successful
+
+#![feature(rustc_attrs)]
+
+#[path="mod_file_not_owning_aux3.rs"]
+mod foo;
+
+#[rustc_error]
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that macro-expanded non-inline modules behave correctly
+
+macro_rules! mod_decl {
+ ($i:ident) => { mod $i; }
+}
+
+mod macro_expanded_mod_helper {
+ mod_decl!(foo); // This should search in the folder `macro_expanded_mod_helper`
+}
+
+fn main() {
+ mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test
+
+mod_decl!(bar);
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+
+mod mod_file_not_owning_aux1;
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test this is not a test
+
+macro_rules! m {
+ () => { mod mod_file_not_owning_aux2; }
+}
+m!();
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-test this is not a test
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that non-inline modules are not allowed inside blocks.
+
+fn main() {
+ mod foo; //~ ERROR Cannot declare a non-inline module inside a block
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+ }
+}
// 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 {
}
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
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 bar::*; //~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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 foo::*; //~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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::*; //~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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 qux::*;
-use foo::*; //~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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
}
fn main() {
- zed::foo(); //~ ERROR unresolved name
+ zed::foo(); //~ ERROR `foo` is private
bar();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(item_like_imports)]
-
mod a {
pub fn foo() {}
}
// 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 {}
// 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 {
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:issue_12612_1.rs
-
-extern crate issue_12612_1 as foo;
-
-use foo::bar;
-
-mod test {
- use bar::foo; //~ ERROR unresolved import `bar::foo` [E0432]
- //~^ Maybe a missing `extern crate bar;`?
-}
-
-fn main() {}
// 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
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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ };
+}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that macro-expanded non-inline modules behave correctly
-
-macro_rules! mod_decl {
- ($i:ident) => { mod $i; }
-}
-
-mod macro_expanded_mod_helper {
- mod_decl!(foo); // This should search in the folder `macro_expanded_mod_helper`
-}
-
-fn main() {
- mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test
-
-mod_decl!(bar);
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// 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;
-
-fn main() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-test this is not a test
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:namespace-mix-new.rs
-
-#![feature(item_like_imports)]
-
-extern crate namespace_mix_new;
-use namespace_mix_new::*;
-
-mod c {
- pub struct S {}
- pub struct TS();
- pub struct US;
- pub enum E {
- V {},
- TV(),
- UV,
- }
-
- pub struct Item;
-}
-
-// Use something emitting the type argument name, e.g. unsatisfied bound.
-trait Impossible {}
-fn check<T: Impossible>(_: T) {}
-
-mod m1 {
- pub use ::c::*;
- pub type S = ::c::Item;
-}
-mod m2 {
- pub use ::c::*;
- 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 ::c::*;
- pub type TS = ::c::Item;
-}
-mod m4 {
- pub use ::c::*;
- 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 ::c::*;
- pub type US = ::c::Item;
-}
-mod m6 {
- pub use ::c::*;
- 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 ::c::E::*;
- pub type V = ::c::Item;
-}
-mod m8 {
- pub use ::c::E::*;
- 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 ::c::E::*;
- pub type TV = ::c::Item;
-}
-mod mA {
- pub use ::c::E::*;
- 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 ::c::E::*;
- pub type UV = ::c::Item;
-}
-mod mC {
- pub use ::c::E::*;
- 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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: Impossible>(_: 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() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:namespace-mix.rs
+
+extern crate namespace_mix;
+use namespace_mix::*;
+
+mod c {
+ pub struct S {}
+ pub struct TS();
+ pub struct US;
+ pub enum E {
+ V {},
+ TV(),
+ UV,
+ }
+
+ pub struct Item;
+}
+
+// Use something emitting the type argument name, e.g. unsatisfied bound.
+trait Impossible {}
+fn check<T: Impossible>(_: T) {}
+
+mod m1 {
+ pub use ::c::*;
+ pub type S = ::c::Item;
+}
+mod m2 {
+ pub use ::c::*;
+ 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 ::c::*;
+ pub type TS = ::c::Item;
+}
+mod m4 {
+ pub use ::c::*;
+ 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 ::c::*;
+ pub type US = ::c::Item;
+}
+mod m6 {
+ pub use ::c::*;
+ 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 ::c::E::*;
+ pub type V = ::c::Item;
+}
+mod m8 {
+ pub use ::c::E::*;
+ 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 ::c::E::*;
+ pub type TV = ::c::Item;
+}
+mod mA {
+ pub use ::c::E::*;
+ 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 ::c::E::*;
+ pub type UV = ::c::Item;
+}
+mod mC {
+ pub use ::c::E::*;
+ 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() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that non-inline modules are not allowed inside blocks.
-
-fn main() {
- mod foo; //~ ERROR Cannot declare a non-inline module inside a block
-}
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 }
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 };
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 };
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+// Check that building a metadata crate finds an error.
+
+#![crate_type="metadata"]
+
+fn main() {
+ let _ = Foo; //~ ERROR unresolved name `Foo`
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+// error-pattern: crate `rmeta_meta` required to be available in rlib, but it was not available
+
+// Check that building a non-metadata crate fails if a dependent crate is
+// metadata-only.
+
+extern crate rmeta_meta;
+use rmeta_meta::Foo;
+
+fn main() {
+ let _ = Foo { field: 42 };
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
+
+// Check that building a metadata crate finds an error with a dependent,
+// metadata-only crate.
+
+#![crate_type="metadata"]
+
+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 {
- 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() {}
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
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Point>) -> 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() {
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 struct constructor expressions.
+
+// 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"]
+
+
+struct RegularStruct {
+ x: i32,
+ y: i64,
+ z: i16,
+}
+
+// Change field value (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_value_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+}
+
+#[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_field_value_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 0,
+ y: 2,
+ z: 2,
+ }
+}
+
+
+
+// Change field order (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_order_regular_struct() -> RegularStruct {
+ RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ }
+}
+
+#[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_field_order_regular_struct() -> RegularStruct {
+ RegularStruct {
+ y: 4,
+ x: 3,
+ z: 5,
+ }
+}
+
+
+
+// Add field (regular struct) --------------------------------------------------
+#[cfg(cfail1)]
+fn add_field_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ .. struct1
+ }
+}
+
+#[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_field_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ y: 8,
+ .. struct1
+ }
+}
+
+
+
+// Change field label (regular struct) -----------------------------------------
+#[cfg(cfail1)]
+fn change_field_label_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ y: 9,
+ .. struct1
+ }
+}
+
+#[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_field_label_regular_struct() -> RegularStruct {
+ let struct1 = RegularStruct {
+ x: 3,
+ y: 4,
+ z: 5,
+ };
+
+ RegularStruct {
+ x: 7,
+ z: 9,
+ .. struct1
+ }
+}
+
+
+
+struct RegularStruct2 {
+ x: i8,
+ y: i8,
+ z: i8,
+}
+
+// Change constructor path (regular struct) ------------------------------------
+#[cfg(cfail1)]
+fn change_constructor_path_regular_struct() {
+ let _ = RegularStruct {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+#[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_constructor_path_regular_struct() {
+ let _ = RegularStruct2 {
+ x: 0,
+ y: 1,
+ z: 2,
+ };
+}
+
+
+
+// Change constructor path indirectly (regular struct) -------------------------
+mod change_constructor_path_indirectly_regular_struct {
+ #[cfg(cfail1)]
+ use super::RegularStruct as Struct;
+ #[cfg(not(cfail1))]
+ use super::RegularStruct2 as Struct;
+
+ fn function() -> Struct {
+ Struct {
+ x: 0,
+ y: 1,
+ z: 2,
+ }
+ }
+}
+
+
+
+struct TupleStruct(i32, i64, i16);
+
+// Change field value (tuple struct) -------------------------------------------
+#[cfg(cfail1)]
+fn change_field_value_tuple_struct() -> TupleStruct {
+ TupleStruct(0, 1, 2)
+}
+
+#[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_field_value_tuple_struct() -> TupleStruct {
+ TupleStruct(0, 1, 3)
+}
+
+
+
+struct TupleStruct2(u16, u16, u16);
+
+// Change constructor path (tuple struct) --------------------------------------
+#[cfg(cfail1)]
+fn change_constructor_path_tuple_struct() {
+ let _ = TupleStruct(0, 1, 2);
+}
+
+#[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_constructor_path_tuple_struct() {
+ let _ = TupleStruct2(0, 1, 2);
+}
+
+
+
+// Change constructor path indirectly (tuple struct) ---------------------------
+mod change_constructor_path_indirectly_tuple_struct {
+ #[cfg(cfail1)]
+ use super::TupleStruct as Struct;
+ #[cfg(not(cfail1))]
+ use super::TupleStruct2 as Struct;
+
+ fn function() -> Struct {
+ Struct(0, 1, 2)
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
+ }
+}
// compile-flags: -Z parse-only
-// error-pattern:expected `]`
+// error-pattern:expected one of `=` or `]`
// asterisk is bogus
#[attr*]
// 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() {
use syntax::ast;
use syntax::codemap;
-use syntax::parse;
use syntax::print::pprust;
+use syntax::symbol::Symbol;
use syntax_pos::DUMMY_SP;
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,
}
use rustc_metadata::cstore::CStore;
use rustc_errors::registry::Registry;
+use std::collections::HashSet;
use std::path::PathBuf;
use std::rc::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);
--- /dev/null
+-include ../tools.mk
+
+all:
+ $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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"]
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+#[macro_use] extern crate a;
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
--- /dev/null
+-include ../tools.mk
+all: code
+krate2: krate2.rs
+ $(RUSTC) $<
+code: foo.rs krate2
+ $(RUSTC) foo.rs -Zsave-analysis || exit 0
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// sub-module in the same directory as the main crate file
+
+pub struct SameStruct {
+ pub name: String
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn hello(x: isize) {
+ println!("macro {} :-(", x);
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// sub-module in a sub-directory
+
+use sub::sub2 as msalias;
+use sub::sub2;
+
+static yy: usize = 25;
+
+mod sub {
+ pub mod sub2 {
+ pub mod sub3 {
+ pub fn hello() {
+ println!("hello from module 3");
+ }
+ }
+ pub fn hello() {
+ println!("hello from a module");
+ }
+
+ pub struct nested_struct {
+ pub field2: u32,
+ }
+ }
+}
+
+pub struct SubStruct {
+ pub name: String
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![ crate_name = "test" ]
+#![feature(box_syntax)]
+#![feature(rustc_private)]
+
+extern crate graphviz;
+// A simple rust project
+
+extern crate krate2;
+extern crate krate2 as krate3;
+extern crate flate as myflate;
+
+use graphviz::RenderOption;
+use std::collections::{HashMap,HashSet};
+use std::cell::RefCell;
+use std::io::Write;
+
+
+use sub::sub2 as msalias;
+use sub::sub2;
+use sub::sub2::nested_struct as sub_struct;
+
+use std::mem::size_of;
+
+use std::char::from_u32;
+
+static uni: &'static str = "Les Miséééééééérables";
+static yy: usize = 25;
+
+static bob: Option<graphviz::RenderOption> = None;
+
+// buglink test - see issue #1337.
+
+fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
+ let s = sub_struct{ field2: 45u32, };
+
+ // import tests
+ fn foo(x: &Write) {}
+ let _: Option<_> = from_u32(45);
+
+ let x = 42usize;
+
+ krate2::hello();
+ krate3::hello();
+ myflate::deflate_bytes(&[]);
+
+ let x = (3isize, 4usize);
+ let y = x.1;
+}
+
+// Issue #37700
+const LUT_BITS: usize = 3;
+pub struct HuffmanTable {
+ ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
+}
+
+struct TupStruct(isize, isize, Box<str>);
+
+fn test_tup_struct(x: TupStruct) -> isize {
+ x.1
+}
+
+fn println(s: &str) {
+ std::io::stdout().write_all(s.as_bytes());
+}
+
+mod sub {
+ pub mod sub2 {
+ use std::io::Write;
+ pub mod sub3 {
+ use std::io::Write;
+ pub fn hello() {
+ ::println("hello from module 3");
+ }
+ }
+ pub fn hello() {
+ ::println("hello from a module");
+ }
+
+ pub struct nested_struct {
+ pub field2: u32,
+ }
+
+ pub enum nested_enum {
+ Nest2 = 2,
+ Nest3 = 3
+ }
+ }
+}
+
+pub mod SameDir;
+pub mod SubDir;
+
+#[path = "SameDir3.rs"]
+pub mod SameDir2;
+
+struct nofields;
+
+#[derive(Clone)]
+struct some_fields {
+ field1: u32,
+}
+
+type SF = some_fields;
+
+trait SuperTrait {
+ fn qux(&self) { panic!(); }
+}
+
+trait SomeTrait: SuperTrait {
+ fn Method(&self, x: u32) -> u32;
+
+ fn prov(&self, x: u32) -> u32 {
+ println(&x.to_string());
+ 42
+ }
+ fn provided_method(&self) -> u32 {
+ 42
+ }
+}
+
+trait SubTrait: SomeTrait {
+ fn stat2(x: &Self) -> u32 {
+ 32
+ }
+}
+
+trait SizedTrait: Sized {}
+
+fn error(s: &SizedTrait) {
+ let foo = 42;
+ println!("Hello world! {}", foo);
+}
+
+impl SomeTrait for some_fields {
+ fn Method(&self, x: u32) -> u32 {
+ println(&x.to_string());
+ self.field1
+ }
+}
+
+impl SuperTrait for some_fields {
+}
+
+impl SubTrait for some_fields {}
+
+impl some_fields {
+ fn stat(x: u32) -> u32 {
+ println(&x.to_string());
+ 42
+ }
+ fn stat2(x: &some_fields) -> u32 {
+ 42
+ }
+
+ fn align_to<T>(&mut self) {
+
+ }
+
+ fn test(&mut self) {
+ self.align_to::<bool>();
+ }
+}
+
+impl SuperTrait for nofields {
+}
+impl SomeTrait for nofields {
+ fn Method(&self, x: u32) -> u32 {
+ self.Method(x);
+ 43
+ }
+
+ fn provided_method(&self) -> u32 {
+ 21
+ }
+}
+
+impl SubTrait for nofields {}
+
+impl SuperTrait for (Box<nofields>, Box<some_fields>) {}
+
+fn f_with_params<T: SomeTrait>(x: &T) {
+ x.Method(41);
+}
+
+type MyType = Box<some_fields>;
+
+enum SomeEnum<'a> {
+ Ints(isize, isize),
+ Floats(f64, f64),
+ Strings(&'a str, &'a str, &'a str),
+ MyTypes(MyType, MyType)
+}
+
+#[derive(Copy, Clone)]
+enum SomeOtherEnum {
+ SomeConst1,
+ SomeConst2,
+ SomeConst3
+}
+
+enum SomeStructEnum {
+ EnumStruct{a:isize, b:isize},
+ EnumStruct2{f1:MyType, f2:MyType},
+ EnumStruct3{f1:MyType, f2:MyType, f3:SomeEnum<'static>}
+}
+
+fn matchSomeEnum(val: SomeEnum) {
+ match val {
+ SomeEnum::Ints(int1, int2) => { println(&(int1+int2).to_string()); }
+ SomeEnum::Floats(float1, float2) => { println(&(float2*float1).to_string()); }
+ SomeEnum::Strings(.., s3) => { println(s3); }
+ SomeEnum::MyTypes(mt1, mt2) => { println(&(mt1.field1 - mt2.field1).to_string()); }
+ }
+}
+
+fn matchSomeStructEnum(se: SomeStructEnum) {
+ match se {
+ SomeStructEnum::EnumStruct{a:a, ..} => println(&a.to_string()),
+ SomeStructEnum::EnumStruct2{f1:f1, f2:f_2} => println(&f_2.field1.to_string()),
+ SomeStructEnum::EnumStruct3{f1, ..} => println(&f1.field1.to_string()),
+ }
+}
+
+
+fn matchSomeStructEnum2(se: SomeStructEnum) {
+ use SomeStructEnum::*;
+ match se {
+ EnumStruct{a: ref aaa, ..} => println(&aaa.to_string()),
+ EnumStruct2{f1, f2: f2} => println(&f1.field1.to_string()),
+ EnumStruct3{f1, f3: SomeEnum::Ints(..), f2} => println(&f1.field1.to_string()),
+ _ => {},
+ }
+}
+
+fn matchSomeOtherEnum(val: SomeOtherEnum) {
+ use SomeOtherEnum::{SomeConst2, SomeConst3};
+ match val {
+ SomeOtherEnum::SomeConst1 => { println("I'm const1."); }
+ SomeConst2 | SomeConst3 => { println("I'm const2 or const3."); }
+ }
+}
+
+fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
+ SameDir2::hello(43);
+
+ println(&yy.to_string());
+ let (x, y): (u32, u32) = (5, 3);
+ println(&x.to_string());
+ println(&z.to_string());
+ let x: u32 = x;
+ println(&x.to_string());
+ let x = "hello";
+ println(x);
+
+ let x = 32.0f32;
+ let _ = (x + ((x * x) + 1.0).sqrt()).ln();
+
+ let s: Box<SomeTrait> = box some_fields {field1: 43};
+ let s2: Box<some_fields> = box some_fields {field1: 43};
+ let s3 = box nofields;
+
+ s.Method(43);
+ s3.Method(43);
+ s2.Method(43);
+
+ ex.prov(43);
+
+ let y: u32 = 56;
+ // static method on struct
+ let r = some_fields::stat(y);
+ // trait static method, calls default
+ let r = SubTrait::stat2(&*s3);
+
+ let s4 = s3 as Box<SomeTrait>;
+ s4.Method(43);
+
+ s4.provided_method();
+ s2.prov(45);
+
+ let closure = |x: u32, s: &SomeTrait| {
+ s.Method(23);
+ return x + y;
+ };
+
+ let z = closure(10, &*s);
+}
+
+pub struct blah {
+ used_link_args: RefCell<[&'static str; 0]>,
+}
+
+#[macro_use]
+mod macro_use_test {
+ macro_rules! test_rec {
+ (q, $src: expr) => {{
+ print!("{}", $src);
+ test_rec!($src);
+ }};
+ ($src: expr) => {
+ print!("{}", $src);
+ };
+ }
+
+ macro_rules! internal_vars {
+ ($src: ident) => {{
+ let mut x = $src;
+ x += 100;
+ }};
+ }
+}
+
+fn main() { // foo
+ let s = box some_fields {field1: 43};
+ hello((43, "a".to_string()), *s);
+ sub::sub2::hello();
+ sub2::sub3::hello();
+
+ let h = sub2::sub3::hello;
+ h();
+
+ // utf8 chars
+ let ut = "Les Miséééééééérables";
+
+ // For some reason, this pattern of macro_rules foiled our generated code
+ // avoiding strategy.
+ macro_rules! variable_str(($name:expr) => (
+ some_fields {
+ field1: $name,
+ }
+ ));
+ let vs = variable_str!(32);
+
+ let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
+ let _ = blah {
+ used_link_args: RefCell::new([]),
+ };
+ let s1 = nofields;
+ let s2 = SF { field1: 55};
+ let s3: some_fields = some_fields{ field1: 55};
+ let s4: msalias::nested_struct = sub::sub2::nested_struct{ field2: 55};
+ let s4: msalias::nested_struct = sub2::nested_struct{ field2: 55};
+ println(&s2.field1.to_string());
+ let s5: MyType = box some_fields{ field1: 55};
+ let s = SameDir::SameStruct{name: "Bob".to_string()};
+ let s = SubDir::SubStruct{name:"Bob".to_string()};
+ let s6: SomeEnum = SomeEnum::MyTypes(box s2.clone(), s5);
+ let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
+ matchSomeEnum(s6);
+ matchSomeEnum(s7);
+ let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
+ matchSomeOtherEnum(s8);
+ let s9: SomeStructEnum = SomeStructEnum::EnumStruct2{ f1: box some_fields{ field1:10 },
+ f2: box s2 };
+ matchSomeStructEnum(s9);
+
+ for x in &vec![1, 2, 3] {
+ let _y = x;
+ }
+
+ let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
+ if let SomeEnum::Strings(..) = s7 {
+ println!("hello!");
+ }
+
+ for i in 0..5 {
+ foo_foo(i);
+ }
+
+ if let Some(x) = None {
+ foo_foo(x);
+ }
+
+ if false {
+ } else if let Some(y) = None {
+ foo_foo(y);
+ }
+
+ while let Some(z) = None {
+ foo_foo(z);
+ }
+
+ let mut x = 4;
+ test_rec!(q, "Hello");
+ assert_eq!(x, 4);
+ internal_vars!(x);
+}
+
+fn foo_foo(_: i32) {}
+
+impl Iterator for nofields {
+ type Item = (usize, usize);
+
+ fn next(&mut self) -> Option<(usize, usize)> {
+ panic!()
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ panic!()
+ }
+}
+
+trait Pattern<'a> {
+ type Searcher;
+}
+
+struct CharEqPattern;
+
+impl<'a> Pattern<'a> for CharEqPattern {
+ type Searcher = CharEqPattern;
+}
+
+struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
+
+pub trait Error {
+}
+
+impl Error + 'static {
+ pub fn is<T: Error + 'static>(&self) -> bool {
+ panic!()
+ }
+}
+
+impl Error + 'static + Send {
+ pub fn is<T: Error + 'static>(&self) -> bool {
+ <Error + 'static>::is::<T>(self)
+ }
+}
+extern crate serialize;
+#[derive(Clone, Copy, Hash, Encodable, Decodable, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
+struct AllDerives(i32);
+
+fn test_format_args() {
+ let x = 1;
+ let y = 2;
+ let name = "Joe Blogg";
+ println!("Hello {}", name);
+ print!("Hello {0}", name);
+ print!("{0} + {} = {}", x, y);
+ print!("x is {}, y is {1}, name is {n}", x, y, n = name);
+}
--- /dev/null
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![ crate_name = "krate2" ]
+#![ crate_type = "lib" ]
+
+use std::io::Write;
+
+pub fn hello() {
+ std::io::stdout().write_all(b"hello world!\n");
+}
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;
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)) } })
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]
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)) } })
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)) } })
// force-host
-#![feature(plugin_registrar, rustc_private, item_like_imports)]
+#![feature(plugin_registrar, rustc_private)]
extern crate syntax;
extern crate syntax_ext;
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)));
}
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",
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;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
- token::intern("derive_TotalSum"),
+ Symbol::intern("derive_TotalSum"),
MultiDecorator(box expand));
}
|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??"); },
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};
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
- token::intern("derive_TotalSum"),
+ Symbol::intern("derive_TotalSum"),
MultiDecorator(box expand));
}
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'");
}
}
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;
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)));
}
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;
}
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.")
};
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;
_: &[tokenstream::TokenTree]) -> Box<MacResult+'cx> {
let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
.collect::<Vec<_>>().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));
}
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)));
}
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;
}
};
- 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<P<Pat>> = pats.iter().map(|pat_nt| {
match **pat_nt {
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");
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test case tests whether we can handle code bases that contain a high
+// number of closures, something that needs special handling in the MingGW
+// toolchain.
+// See https://github.com/rust-lang/rust/issues/34793 for more information.
+
+// Make sure we don't optimize anything away:
+// compile-flags: -C no-prepopulate-passes
+
+// Expand something exponentially
+macro_rules! go_bacterial {
+ ($mac:ident) => ($mac!());
+ ($mac:ident 1 $($t:tt)*) => (
+ go_bacterial!($mac $($t)*);
+ go_bacterial!($mac $($t)*);
+ )
+}
+
+macro_rules! mk_closure {
+ () => ((move || {})())
+}
+
+macro_rules! mk_fn {
+ () => {
+ {
+ fn function() {
+ // Make 16 closures
+ go_bacterial!(mk_closure 1 1 1 1);
+ }
+ let _ = function();
+ }
+ }
+}
+
+fn main() {
+ // Make 2^12 functions, each containing 16 closures,
+ // resulting in 2^16 closures overall.
+ go_bacterial!(mk_fn 1 1 1 1 1 1 1 1 1 1 1 1);
+}
extern crate syntax_pos;
use syntax::print::pprust::*;
-use syntax::parse::token::intern;
+use syntax::symbol::Symbol;
use syntax_pos::DUMMY_SP;
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,
}
// 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")]"#);
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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,
+}
// 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.
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn gimme_a_raw_pointer<T>(_: *const T) { }
+
+fn test<T>(t: T) { }
+
+fn main() {
+ // Clearly `pointer` must be of type `*const ()`.
+ let pointer = &() as *const _;
+ gimme_a_raw_pointer(pointer);
+
+ let t = test as fn (i32);
+ t(0i32);
+}
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
+}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// This test case tests whether we can handle code bases that contain a high
-// number of closures, something that needs special handling in the MingGW
-// toolchain.
-// See https://github.com/rust-lang/rust/issues/34793 for more information.
-
-// Expand something exponentially
-macro_rules! go_bacterial {
- ($mac:ident) => ($mac!());
- ($mac:ident 1 $($t:tt)*) => (
- go_bacterial!($mac $($t)*);
- go_bacterial!($mac $($t)*);
- )
-}
-
-macro_rules! mk_closure {
- () => ({
- let c = |a: u32| a + 4;
- let _ = c(2);
- })
-}
-
-macro_rules! mk_fn {
- () => {
- {
- fn function() {
- // Make 16 closures
- go_bacterial!(mk_closure 1 1 1 1);
- }
- let _ = function();
- }
- }
-}
-
-fn main() {
- // Make 2^12 functions, each containing 16 closures,
- // resulting in 2^16 closures overall.
- go_bacterial!(mk_fn 1 1 1 1 1 1 1 1 1 1 1 1);
-}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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.
+
+// aux-build:rmeta_rmeta.rs
+// aux-build:rmeta_rlib.rs
+
+extern crate rmeta_aux;
+use rmeta_aux::Foo;
+
+pub fn main() {
+ let _ = Foo { field: 42 };
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// All of the types that occur in this function are uninteresting, in
+// that one cannot control the sizes of these types with the same sort
+// of enum-variant manipulation tricks.
+
+pub fn main() {
+ let _byte: u8 = 0;
+ let _word: usize = 0;
+ let _tuple: (u8, usize)= (0, 0);
+ let _array: [u8; 128] = [0; 128];
+ let _fn: fn (u8) -> u8 = id;
+ let _diverging: fn (u8) -> ! = bye;
+
+ fn id(x: u8) -> u8 { x };
+ fn bye(_: u8) -> ! { loop { } }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates how generics are handled: types have to be
+// monomorphized, in the MIR of the original function in which they
+// occur, to have their size reported.
+
+// In an ad-hoc attempt to avoid the injection of unwinding code
+// (which clutters the output of `-Z print-type-sizes` with types from
+// `unwind::libunwind`):
+//
+// * I am not using Default to build values because that seems to
+// cause the injection of unwinding code. (Instead I just make `fn new`
+// methods.)
+//
+// * Pair derive Copy to ensure that we don't inject
+// unwinding code into generic uses of Pair when T itself is also
+// Copy.
+//
+// (I suspect this reflect some naivety within the rust compiler
+// itself; it should be checking for drop glue, i.e. a destructor
+// somewhere in the monomorphized types. It should not matter whether
+// the type is Copy.)
+#[derive(Copy, Clone)]
+pub struct Pair<T> {
+ _car: T,
+ _cdr: T,
+}
+
+impl<T> Pair<T> {
+ fn new(a: T, d: T) -> Self {
+ Pair {
+ _car: a,
+ _cdr: d,
+ }
+ }
+}
+
+#[derive(Copy, Clone)]
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub struct ZeroSized;
+
+impl SevenBytes {
+ fn new() -> Self { SevenBytes([0; 7]) }
+}
+
+impl FiftyBytes {
+ fn new() -> Self { FiftyBytes([0; 50]) }
+}
+
+pub fn f1<T:Copy>(x: T) {
+ let _v: Pair<T> = Pair::new(x, x);
+ let _v2: Pair<FiftyBytes> =
+ Pair::new(FiftyBytes::new(), FiftyBytes::new());
+}
+
+pub fn main() {
+ let _b: Pair<u8> = Pair::new(0, 0);
+ let _s: Pair<SevenBytes> = Pair::new(SevenBytes::new(), SevenBytes::new());
+ let _z: ZeroSized = ZeroSized;
+ f1::<SevenBytes>(SevenBytes::new());
+}
--- /dev/null
+print-type-size type: `Pair<FiftyBytes>`: 100 bytes, alignment: 1 bytes
+print-type-size field `._car`: 50 bytes
+print-type-size field `._cdr`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `Pair<SevenBytes>`: 14 bytes, alignment: 1 bytes
+print-type-size field `._car`: 7 bytes
+print-type-size field `._cdr`: 7 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size type: `Pair<u8>`: 2 bytes, alignment: 1 bytes
+print-type-size field `._car`: 1 bytes
+print-type-size field `._cdr`: 1 bytes
+print-type-size type: `ZeroSized`: 0 bytes, alignment: 1 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates that when multiple structural types occur in
+// a function, every one of them is included in the output.
+
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+ Small(SevenBytes),
+ Large(FiftyBytes),
+}
+
+pub fn main() {
+ let _e: Enum;
+ let _f: FiftyBytes;
+ let _s: SevenBytes;
+}
--- /dev/null
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Small`: 7 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size variant `Large`: 50 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates that when the same type occurs repeatedly
+// (even if multiple functions), it is only printed once in the
+// print-type-sizes output.
+
+pub struct SevenBytes([u8; 7]);
+
+pub fn f1() {
+ let _s: SevenBytes = SevenBytes([0; 7]);
+}
+
+pub fn main() {
+ let _s: SevenBytes = SevenBytes([0; 7]);
+}
--- /dev/null
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates how enums with a non-null field are handled,
+// modelled after cases like `Option<&u32>` and such.
+//
+// It uses NonZero directly, rather than `&_` or `Unique<_>`, because
+// the test is not set up to deal with target-dependent pointer width.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![feature(nonzero)]
+#![allow(dead_code)]
+
+extern crate core;
+use core::nonzero::{NonZero, Zeroable};
+
+pub enum MyOption<T> { None, Some(T) }
+
+impl<T> Default for MyOption<T> {
+ fn default() -> Self { MyOption::None }
+}
+
+pub enum EmbeddedDiscr {
+ None,
+ Record { pre: u8, val: NonZero<u32>, post: u16 },
+}
+
+impl Default for EmbeddedDiscr {
+ fn default() -> Self { EmbeddedDiscr::None }
+}
+
+#[derive(Default)]
+pub struct IndirectNonZero<T: Zeroable> {
+ pre: u8,
+ nested: NestedNonZero<T>,
+ post: u16,
+}
+
+pub struct NestedNonZero<T: Zeroable> {
+ pre: u8,
+ val: NonZero<T>,
+ post: u16,
+}
+
+impl<T: Zeroable+Default> Default for NestedNonZero<T> {
+ fn default() -> Self {
+ unsafe {
+ NestedNonZero { pre: 0, val: NonZero::new(Default::default()), post: 0 }
+ }
+ }
+}
+
+pub fn main() {
+ let _x: MyOption<NonZero<u32>> = Default::default();
+ let _y: EmbeddedDiscr = Default::default();
+ let _z: MyOption<IndirectNonZero<u32>> = Default::default();
+}
--- /dev/null
+print-type-size type: `IndirectNonZero<u32>`: 20 bytes, alignment: 4 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.nested`: 12 bytes, alignment: 4 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size end padding: 2 bytes
+print-type-size type: `MyOption<IndirectNonZero<u32>>`: 20 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 20 bytes
+print-type-size field `.0`: 20 bytes
+print-type-size type: `EmbeddedDiscr`: 12 bytes, alignment: 4 bytes
+print-type-size variant `Record`: 10 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size end padding: 2 bytes
+print-type-size type: `NestedNonZero<u32>`: 12 bytes, alignment: 4 bytes
+print-type-size field `.pre`: 1 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.val`: 4 bytes, alignment: 4 bytes
+print-type-size field `.post`: 2 bytes
+print-type-size end padding: 2 bytes
+print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
+print-type-size variant `Some`: 4 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes
+print-type-size field `.0`: 4 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates how packing is handled; it should cause
+// the elimination of padding that would normally be introduced
+// to satisfy alignment desirata.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![feature(untagged_unions)]
+
+#![allow(dead_code)]
+
+#[derive(Default)]
+#[repr(packed)]
+struct Packed {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
+
+#[derive(Default)]
+struct Padded {
+ a: u8,
+ b: u8,
+ g: i32,
+ c: u8,
+ h: i16,
+ d: u8,
+}
+
+pub fn main() {
+ let _c: Packed = Default::default();
+ let _d: Padded = Default::default();
+}
--- /dev/null
+print-type-size type: `Padded`: 16 bytes, alignment: 4 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.g`: 4 bytes, alignment: 4 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size padding: 1 bytes
+print-type-size field `.h`: 2 bytes, alignment: 2 bytes
+print-type-size field `.d`: 1 bytes
+print-type-size end padding: 3 bytes
+print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size field `.g`: 4 bytes
+print-type-size field `.c`: 1 bytes
+print-type-size field `.h`: 2 bytes
+print-type-size field `.d`: 1 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates how padding is handled: alignment
+// requirements can lead to the introduction of padding, either before
+// fields or at the end of the structure as a whole.
+//
+// It avoids using u64/i64 because on some targets that is only 4-byte
+// aligned (while on most it is 8-byte aligned) and so the resulting
+// padding and overall computed sizes can be quite different.
+
+#![allow(dead_code)]
+
+struct S {
+ a: bool,
+ b: bool,
+ g: i32,
+}
+
+enum E1 {
+ A(i32, i8),
+ B(S),
+}
+
+enum E2 {
+ A(i8, i32),
+ B(S),
+}
+
+fn main() { }
--- /dev/null
+print-type-size type: `E1`: 12 bytes, alignment: 4 bytes
+print-type-size discriminant: 4 bytes
+print-type-size variant `A`: 5 bytes
+print-type-size field `.0`: 4 bytes
+print-type-size field `.1`: 1 bytes
+print-type-size variant `B`: 8 bytes
+print-type-size field `.0`: 8 bytes
+print-type-size type: `E2`: 12 bytes, alignment: 4 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `A`: 7 bytes
+print-type-size field `.0`: 1 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.1`: 4 bytes, alignment: 4 bytes
+print-type-size variant `B`: 11 bytes
+print-type-size padding: 3 bytes
+print-type-size field `.0`: 8 bytes, alignment: 4 bytes
+print-type-size type: `S`: 8 bytes, alignment: 4 bytes
+print-type-size field `.a`: 1 bytes
+print-type-size field `.b`: 1 bytes
+print-type-size padding: 2 bytes
+print-type-size field `.g`: 4 bytes, alignment: 4 bytes
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z print-type-sizes
+
+// This file illustrates two things:
+//
+// 1. Only types that appear in a monomorphized function appear in the
+// print-type-sizes output, and
+//
+// 2. For an enum, the print-type-sizes output will also include the
+// size of each variant.
+
+pub struct SevenBytes([u8; 7]);
+pub struct FiftyBytes([u8; 50]);
+
+pub enum Enum {
+ Small(SevenBytes),
+ Large(FiftyBytes),
+}
+
+pub fn main() {
+ let _e: Enum;
+}
--- /dev/null
+print-type-size type: `Enum`: 51 bytes, alignment: 1 bytes
+print-type-size discriminant: 1 bytes
+print-type-size variant `Small`: 7 bytes
+print-type-size field `.0`: 7 bytes
+print-type-size variant `Large`: 50 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `FiftyBytes`: 50 bytes, alignment: 1 bytes
+print-type-size field `.0`: 50 bytes
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size field `.0`: 7 bytes