]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #37944 - bluss:adaptors-are-empty, r=alexcrichton
authorbors <bors@rust-lang.org>
Thu, 24 Nov 2016 17:56:11 +0000 (11:56 -0600)
committerGitHub <noreply@github.com>
Thu, 24 Nov 2016 17:56:11 +0000 (11:56 -0600)
Forward ExactSizeIterator::len and is_empty for important iterator adaptors

Forward ExactSizeIterator::len and is_empty for important iterator adaptors

Because some iterators will provide improved version of len and/or is_empty,
adaptors should forward to those implementations if possible.

347 files changed:
configure
src/Cargo.lock
src/compiler-rt
src/doc/book/lifetimes.md
src/doc/index.md
src/doc/reference.md
src/etc/char_private.py
src/libcollections/lib.rs
src/libcollections/vec.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/slice.rs
src/libcollectionstest/str.rs
src/libcore/char_private.rs
src/libcore/iter/mod.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/char.rs
src/libcoretest/iter.rs
src/libcoretest/num/flt2dec/strategy/dragon.rs
src/libcoretest/num/flt2dec/strategy/grisu.rs
src/libproc_macro_plugin/qquote.rs
src/libproc_macro_tokens/build.rs
src/librustc/cfg/construct.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/infer/error_reporting.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/middle/const_val.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/reachable.rs
src/librustc/middle/recursion_limit.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/session/code_stats.rs [new file with mode: 0644]
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/project.rs
src/librustc/ty/context.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/ty/walk.rs
src/librustc/util/common.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_data_structures/small_vec.rs
src/librustc_data_structures/unify/mod.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/target_features.rs
src/librustc_driver/test.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh/mod.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_incremental/persist/directory.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/fs.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_llvm/Cargo.toml
src/librustc_llvm/build.rs
src/librustc_llvm/ffi.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/lib.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/diagnostics.rs
src/librustc_passes/hir_stats.rs
src/librustc_passes/loops.rs
src/librustc_plugin/load.rs
src/librustc_plugin/registry.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/span_utils.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/abi.rs
src/librustc_trans/adt.rs
src/librustc_trans/asm.rs
src/librustc_trans/assert_module_sources.rs
src/librustc_trans/attributes.rs
src/librustc_trans/back/archive.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/rpath.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/base.rs
src/librustc_trans/cabi_asmjs.rs
src/librustc_trans/cabi_x86.rs
src/librustc_trans/cabi_x86_64.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/consts.rs
src/librustc_trans/context.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/namespace.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/partitioning.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/simplify.rs
src/librustdoc/core.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collapse_docs.rs
src/librustdoc/passes/strip_hidden.rs
src/librustdoc/passes/unindent_comments.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/librustdoc/visit_lib.rs
src/libstd/env.rs
src/libstd/fs.rs
src/libstd/net/addr.rs
src/libstd/process.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/pipe.rs
src/libsyntax/ast.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/config.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/entry.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/proc_macro_shim.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/symbol.rs [new file with mode: 0644]
src/libsyntax/test.rs
src/libsyntax/tokenstream.rs
src/libsyntax/util/interner.rs [deleted file]
src/libsyntax/util/lev_distance.rs
src/libsyntax/util/parser.rs
src/libsyntax/util/parser_testing.rs
src/libsyntax/visit.rs
src/libsyntax_ext/asm.rs
src/libsyntax_ext/concat.rs
src/libsyntax_ext/concat_idents.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/cmp/eq.rs
src/libsyntax_ext/deriving/cmp/ord.rs
src/libsyntax_ext/deriving/cmp/partial_eq.rs
src/libsyntax_ext/deriving/cmp/partial_ord.rs
src/libsyntax_ext/deriving/custom.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/default.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/env.rs
src/libsyntax_ext/format.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/libsyntax_ext/trace_macros.rs
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.h
src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs
src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs
src/test/compile-fail-fulldeps/proc-macro/error-on-test.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/qquote.rs
src/test/compile-fail/E0088.rs
src/test/compile-fail/auxiliary/issue_12612_1.rs [deleted file]
src/test/compile-fail/auxiliary/namespace-mix-new.rs [deleted file]
src/test/compile-fail/auxiliary/namespace-mix-old.rs [deleted file]
src/test/compile-fail/auxiliary/namespace-mix.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/rmeta_meta.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/rmeta_rlib.rs [new file with mode: 0644]
src/test/compile-fail/cast-rfc0401.rs
src/test/compile-fail/directory_ownership/backcompat-warnings.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/macro-expanded-mod.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/bar.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/mod.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/mod_file_not_owning.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/mod_file_not_owning_aux2.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/non-inline-mod-restriction.rs [new file with mode: 0644]
src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-loop-break-value.rs [new file with mode: 0644]
src/test/compile-fail/glob-cycles.rs
src/test/compile-fail/import-shadow-1.rs [deleted file]
src/test/compile-fail/import-shadow-2.rs [deleted file]
src/test/compile-fail/import-shadow-3.rs [deleted file]
src/test/compile-fail/import-shadow-4.rs [deleted file]
src/test/compile-fail/import-shadow-5.rs [deleted file]
src/test/compile-fail/import-shadow-6.rs [deleted file]
src/test/compile-fail/import-shadow-7.rs [deleted file]
src/test/compile-fail/import.rs
src/test/compile-fail/imports/duplicate.rs
src/test/compile-fail/imports/reexports.rs
src/test/compile-fail/imports/unused.rs
src/test/compile-fail/issue-12612.rs [deleted file]
src/test/compile-fail/issue-32797.rs
src/test/compile-fail/issue-32833.rs
src/test/compile-fail/loop-break-value.rs [new file with mode: 0644]
src/test/compile-fail/macro-expanded-mod.rs [deleted file]
src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs [deleted file]
src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs [deleted file]
src/test/compile-fail/mod_file_not_owning.rs [deleted file]
src/test/compile-fail/mod_file_not_owning_aux1.rs [deleted file]
src/test/compile-fail/mod_file_not_owning_aux2.rs [deleted file]
src/test/compile-fail/namespace-mix-new.rs [deleted file]
src/test/compile-fail/namespace-mix-old.rs [deleted file]
src/test/compile-fail/namespace-mix.rs [new file with mode: 0644]
src/test/compile-fail/non-inline-mod-restriction.rs [deleted file]
src/test/compile-fail/privacy2.rs
src/test/compile-fail/rmeta-lib-pass.rs [new file with mode: 0644]
src/test/compile-fail/rmeta-pass.rs [new file with mode: 0644]
src/test/compile-fail/rmeta.rs [new file with mode: 0644]
src/test/compile-fail/rmeta_lib.rs [new file with mode: 0644]
src/test/compile-fail/rmeta_meta_main.rs [new file with mode: 0644]
src/test/compile-fail/shadowed-use-visibility.rs
src/test/compile-fail/variant-namespacing.rs
src/test/incremental/change_add_field/struct_point.rs [new file with mode: 0644]
src/test/incremental/change_pub_inherent_method_body/struct_point.rs [new file with mode: 0644]
src/test/incremental/change_pub_inherent_method_sig/struct_point.rs [new file with mode: 0644]
src/test/incremental/hashes/for_loops.rs [new file with mode: 0644]
src/test/incremental/hashes/loop_expressions.rs [new file with mode: 0644]
src/test/incremental/hashes/struct_constructors.rs [new file with mode: 0644]
src/test/incremental/hashes/while_let_loops.rs [new file with mode: 0644]
src/test/incremental/hashes/while_loops.rs [new file with mode: 0644]
src/test/parse-fail/attr-bad-meta.rs
src/test/parse-fail/circular_modules_hello.rs
src/test/run-fail-fulldeps/qquote.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-make/issue-37893/Makefile [new file with mode: 0644]
src/test/run-make/issue-37893/a.rs [new file with mode: 0644]
src/test/run-make/issue-37893/b.rs [new file with mode: 0644]
src/test/run-make/issue-37893/c.rs [new file with mode: 0644]
src/test/run-make/save-analysis-fail/Makefile [new file with mode: 0644]
src/test/run-make/save-analysis-fail/SameDir.rs [new file with mode: 0644]
src/test/run-make/save-analysis-fail/SameDir3.rs [new file with mode: 0644]
src/test/run-make/save-analysis-fail/SubDir/mod.rs [new file with mode: 0644]
src/test/run-make/save-analysis-fail/foo.rs [new file with mode: 0644]
src/test/run-make/save-analysis-fail/krate2.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/cond_noprelude_plugin.rs
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/cond_prelude_plugin.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_partial_eq.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs
src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin_attr.rs
src/test/run-pass-fulldeps/auxiliary/lint_plugin_test.rs
src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs
src/test/run-pass-fulldeps/auxiliary/plugin_args.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
src/test/run-pass-fulldeps/macro-quote-1.rs
src/test/run-pass-fulldeps/myriad-closures.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/qquote.rs
src/test/run-pass/auxiliary/rmeta_rlib.rs [new file with mode: 0644]
src/test/run-pass/auxiliary/rmeta_rmeta.rs [new file with mode: 0644]
src/test/run-pass/imports.rs
src/test/run-pass/issue-23699.rs [new file with mode: 0644]
src/test/run-pass/loop-break-value.rs [new file with mode: 0644]
src/test/run-pass/myriad-closures.rs [deleted file]
src/test/run-pass/rmeta.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/anonymous.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/generics.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/generics.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/multiple_types.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/multiple_types.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/no_duplicates.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/no_duplicates.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/nullable.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/nullable.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/packed.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/packed.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/padding.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/padding.stdout [new file with mode: 0644]
src/test/ui/print_type_sizes/variants.rs [new file with mode: 0644]
src/test/ui/print_type_sizes/variants.stdout [new file with mode: 0644]

index 133af075795c67981ff45e6241f455b7297302cf..5311bf4b064eb8cac4c9054a9df70c8017175b1d 100755 (executable)
--- a/configure
+++ b/configure
@@ -856,7 +856,7 @@ probe_need CFG_CMAKE cmake
 if [ -n "$CFG_ANTLR4" ]
 then
    CFG_ANTLR4_JAR="\"$(find /usr/ -name antlr-complete.jar 2>/dev/null | head -n 1)\""
-   if [ "x" -eq "x$CFG_ANTLR4_JAR" ]
+   if [ "x" = "x$CFG_ANTLR4_JAR" ]
    then
      CFG_ANTLR4_JAR="\"$(find ~ -name antlr-complete.jar 2>/dev/null | head -n 1)\""
    fi
index 2d5207e5c6bc88584464d675d0ba145da05f634b..ab1c1c453dd23df68258c3b1da50fb72139167d1 100644 (file)
@@ -409,7 +409,6 @@ version = "0.0.0"
 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]]
@@ -520,6 +519,7 @@ dependencies = [
  "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",
index 3bc0272cab9fdcfc2ef4df9625ec3c9d5909db79..a8fc4c169fac43a5dc204d4fd56ddb1739f8c178 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3bc0272cab9fdcfc2ef4df9625ec3c9d5909db79
+Subproject commit a8fc4c169fac43a5dc204d4fd56ddb1739f8c178
index 397263c69733002afee50d718e039ae01b312b5e..140e27d19248ce3a936d5570740b7d537e13338b 100644 (file)
@@ -352,7 +352,7 @@ to it.
 Rust supports powerful local type inference in the bodies of functions but not in their item signatures. 
 It's forbidden to allow reasoning about types based on the item signature alone. 
 However, for ergonomic reasons, a very restricted secondary inference algorithm called 
-“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely to infer 
+“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring 
 lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision 
 acts as a shorthand for writing an item signature, while not hiding
 away the actual types involved as full local inference would if applied to it.
index f8a1ec134d9242faa877a156868a53dfc5efa110..71dfcf0b067ec2395b45fb0652b36036d1dd6e7f 100644 (file)
@@ -17,7 +17,7 @@ the language.
 
 [**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.
index 0596e476d5f6c14dfb7271a04e5a84f5ab289440..4fbe518396760dbd66cc32f26edf514cab2ce776 100644 (file)
@@ -2474,18 +2474,19 @@ The currently implemented features of the reference compiler are:
                               internally without imposing on callers
                               (i.e. making them behave like function calls in
                               terms of encapsulation).
-* - `default_type_parameter_fallback` - Allows type parameter defaults to
-                                        influence type inference.
 
-* - `stmt_expr_attributes` - Allows attributes on expressions.
+* `default_type_parameter_fallback` - Allows type parameter defaults to
+                                      influence type inference.
 
-* - `type_ascription` - Allows type ascription expressions `expr: Type`.
+* `stmt_expr_attributes` - Allows attributes on expressions.
 
-* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention
-                             (e.g. `extern "vectorcall" func fn_();`)
+* `type_ascription` - Allows type ascription expressions `expr: Type`.
 
-* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention
-                             (e.g. `extern "sysv64" func fn_();`)
+* `abi_vectorcall` - Allows the usage of the vectorcall calling convention
+                     (e.g. `extern "vectorcall" func fn_();`)
+
+* `abi_sysv64` - Allows the usage of the system V AMD64 calling convention
+                 (e.g. `extern "sysv64" func fn_();`)
 
 If a feature is promoted to a language feature, then all existing programs will
 start to receive compilation warnings about `#![feature]` directives which enabled
index 3566d143529be9135a6ce18f80e3b7ba8bb08fe2..9d15f98e06709eaadf5d61d4ef235bc1e65f1b0c 100644 (file)
 # except according to those terms.
 
 # This script uses the following Unicode tables:
-# - Categories.txt
+# - UnicodeData.txt
 
+
+from collections import namedtuple
+import csv
 import os
 import subprocess
 
+NUM_CODEPOINTS=0x110000
+
 def to_ranges(iter):
     current = None
     for i in iter:
@@ -28,10 +33,10 @@ def to_ranges(iter):
     if current is not None:
         yield tuple(current)
 
-def get_escaped(dictionary):
-    for i in range(0x110000):
-        if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '):
-            yield i
+def get_escaped(codepoints):
+    for c in codepoints:
+        if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord(' '):
+            yield c.value
 
 def get_file(f):
     try:
@@ -40,10 +45,41 @@ def get_file(f):
         subprocess.run(["curl", "-O", f], check=True)
         return open(os.path.basename(f))
 
+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 = []
@@ -52,7 +88,7 @@ def main():
     normal1 = []
     extra = []
 
-    for a, b in to_ranges(get_escaped(dictionary)):
+    for a, b in to_ranges(get_escaped(codepoints)):
         if a > 2 * CUTOFF:
             extra.append((a, b - a))
         elif a == b - 1:
index 23d6edd6d794e88c86cc7b2cfc2d0267365a2ee6..f6d83b25b0d89c598468015b5fdfdb04dfd6f19e 100644 (file)
@@ -36,6 +36,7 @@
 #![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)]
index 24f8e3a2d918144a8cbda94dccfb1545ef292a95..f26324127003b32b12ecc7570b93ff627c19f8e6 100644 (file)
@@ -1988,7 +1988,11 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[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> {}
@@ -2082,7 +2086,11 @@ fn drop(&mut self) {
 
 
 #[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> {}
index 14ec8d58bef61065ad669414be9eb19850670a8d..1e08074b14db8bf5d634544cdf1742df809ba7eb 100644 (file)
@@ -18,6 +18,7 @@
 #![feature(const_fn)]
 #![feature(dedup_by)]
 #![feature(enumset)]
+#![feature(exact_size_is_empty)]
 #![feature(pattern)]
 #![feature(rand)]
 #![feature(repeat_str)]
index a6230ef471cec0f69f9cb197ae8f9cd24a16c9c0..0e63e8d4a1ec8ad6a5ec32202b7841e8d2810b8e 100644 (file)
@@ -633,6 +633,16 @@ fn test_iter_clone() {
     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];
index cc56bbf4890aa46de435ab3048d1952aeaaa7e18..14a0819d381bc0033ae8a320188248021a2fd380 100644 (file)
@@ -767,6 +767,7 @@ fn test_iterator() {
         pos += 1;
     }
     assert_eq!(pos, v.len());
+    assert_eq!(s.chars().count(), v.len());
 }
 
 #[test]
@@ -814,6 +815,14 @@ fn test_iterator_clone() {
     assert!(it.clone().zip(it).all(|(x,y)| x == y));
 }
 
+#[test]
+fn test_iterator_last() {
+    let s = "ศไทย中华Việt Nam";
+    let mut it = s.chars();
+    it.next();
+    assert_eq!(it.last(), Some('m'));
+}
+
 #[test]
 fn test_bytesator() {
     let s = "ศไทย中华Việt Nam";
@@ -911,6 +920,14 @@ fn test_char_indices_revator() {
     assert_eq!(pos, p.len());
 }
 
+#[test]
+fn test_char_indices_last() {
+    let s = "ศไทย中华Việt Nam";
+    let mut it = s.char_indices();
+    it.next();
+    assert_eq!(it.last(), Some((27, 'm')));
+}
+
 #[test]
 fn test_splitn_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
index 708e7cc15e7c97f97f89f9f4c326bc02bf2acd97..ddc473592a26026035edd0c0f15705e30f0a3dd0 100644 (file)
@@ -11,6 +11,8 @@
 // NOTE: The following code was generated by "src/etc/char_private.py",
 //       do not edit directly!
 
+use slice::SliceExt;
+
 fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
     for &s in singletons {
         if x == s {
@@ -42,7 +44,16 @@ pub fn is_printable(x: char) -> bool {
     } else if x < 0x20000 {
         check(lower, SINGLETONS1, NORMAL1)
     } else {
-        if 0x20000 <= x && x < 0x2f800 {
+        if 0x2a6d7 <= x && x < 0x2a700 {
+            return false;
+        }
+        if 0x2b735 <= x && x < 0x2b740 {
+            return false;
+        }
+        if 0x2b81e <= x && x < 0x2b820 {
+            return false;
+        }
+        if 0x2cea2 <= x && x < 0x2f800 {
             return false;
         }
         if 0x2fa1e <= x && x < 0xe0100 {
@@ -62,10 +73,13 @@ pub fn is_printable(x: char) -> bool {
     0x38b,
     0x38d,
     0x3a2,
+    0x530,
     0x557,
     0x558,
     0x560,
     0x588,
+    0x58b,
+    0x58c,
     0x590,
     0x61c,
     0x61d,
@@ -79,10 +93,8 @@ pub fn is_printable(x: char) -> bool {
     0x83f,
     0x85c,
     0x85d,
-    0x8a1,
-    0x8ff,
-    0x978,
-    0x980,
+    0x8b5,
+    0x8e2,
     0x984,
     0x98d,
     0x98e,
@@ -154,14 +166,11 @@ pub fn is_printable(x: char) -> bool {
     0xc0d,
     0xc11,
     0xc29,
-    0xc34,
     0xc45,
     0xc49,
     0xc57,
     0xc64,
     0xc65,
-    0xc80,
-    0xc81,
     0xc84,
     0xc8d,
     0xc91,
@@ -193,6 +202,8 @@ pub fn is_printable(x: char) -> bool {
     0xdbf,
     0xdd5,
     0xdd7,
+    0xdf0,
+    0xdf1,
     0xe83,
     0xe85,
     0xe86,
@@ -245,6 +256,10 @@ pub fn is_printable(x: char) -> bool {
     0x1317,
     0x135b,
     0x135c,
+    0x13f6,
+    0x13f7,
+    0x13fe,
+    0x13ff,
     0x1680,
     0x170d,
     0x176d,
@@ -253,6 +268,7 @@ pub fn is_printable(x: char) -> bool {
     0x17df,
     0x180e,
     0x180f,
+    0x191f,
     0x196e,
     0x196f,
     0x1a1c,
@@ -260,6 +276,9 @@ pub fn is_printable(x: char) -> bool {
     0x1a5f,
     0x1a7d,
     0x1a7e,
+    0x1aae,
+    0x1aaf,
+    0x1cf7,
     0x1f16,
     0x1f17,
     0x1f1e,
@@ -285,7 +304,12 @@ pub fn is_printable(x: char) -> bool {
     0x2072,
     0x2073,
     0x208f,
-    0x2700,
+    0x23ff,
+    0x2b74,
+    0x2b75,
+    0x2b96,
+    0x2b97,
+    0x2bc9,
     0x2c2f,
     0x2c5f,
     0x2d26,
@@ -306,8 +330,11 @@ pub fn is_printable(x: char) -> bool {
     0x318f,
     0x321f,
     0x32ff,
-    0xa78f,
+    0xa7af,
+    0xa8fe,
+    0xa8ff,
     0xa9ce,
+    0xa9ff,
     0xaa4e,
     0xaa4f,
     0xaa5a,
@@ -317,6 +344,7 @@ pub fn is_printable(x: char) -> bool {
     0xab0f,
     0xab10,
     0xab27,
+    0xab2f,
     0xabee,
     0xabef,
     0xfa6e,
@@ -350,7 +378,7 @@ pub fn is_printable(x: char) -> bool {
     0x3e,
     0x4e,
     0x4f,
-    0x31f,
+    0x18f,
     0x39e,
     0x49e,
     0x49f,
@@ -361,6 +389,9 @@ pub fn is_printable(x: char) -> bool {
     0x83d,
     0x83e,
     0x856,
+    0x8f3,
+    0x9d0,
+    0x9d1,
     0xa04,
     0xa14,
     0xa18,
@@ -368,6 +399,49 @@ pub fn is_printable(x: char) -> bool {
     0xb57,
     0x10bd,
     0x1135,
+    0x11ce,
+    0x11cf,
+    0x11e0,
+    0x1212,
+    0x1287,
+    0x1289,
+    0x128e,
+    0x129e,
+    0x1304,
+    0x130d,
+    0x130e,
+    0x1311,
+    0x1312,
+    0x1329,
+    0x1331,
+    0x1334,
+    0x133a,
+    0x133b,
+    0x1345,
+    0x1346,
+    0x1349,
+    0x134a,
+    0x134e,
+    0x134f,
+    0x1364,
+    0x1365,
+    0x145a,
+    0x145c,
+    0x15b6,
+    0x15b7,
+    0x1c09,
+    0x1c37,
+    0x1c90,
+    0x1c91,
+    0x1ca8,
+    0x246f,
+    0x6a5f,
+    0x6aee,
+    0x6aef,
+    0x6b5a,
+    0x6b62,
+    0xbc9a,
+    0xbc9b,
     0xd127,
     0xd128,
     0xd455,
@@ -395,6 +469,14 @@ pub fn is_printable(x: char) -> bool {
     0xd6a7,
     0xd7cc,
     0xd7cd,
+    0xdaa0,
+    0xe007,
+    0xe019,
+    0xe01a,
+    0xe022,
+    0xe025,
+    0xe8c5,
+    0xe8c6,
     0xee04,
     0xee20,
     0xee23,
@@ -429,31 +511,25 @@ pub fn is_printable(x: char) -> bool {
     0xeeaa,
     0xf0af,
     0xf0b0,
-    0xf0bf,
     0xf0c0,
     0xf0d0,
     0xf12f,
-    0xf336,
-    0xf3c5,
-    0xf43f,
-    0xf441,
-    0xf4f8,
-    0xf53e,
-    0xf53f,
+    0xf91f,
+    0xf931,
+    0xf932,
+    0xf93f,
 ];
 const NORMAL0: &'static [u16] = &[
     0x0, 0x20,
     0x7f, 0x22,
-    0x37f, 0x5,
-    0x528, 0x9,
-    0x58b, 0x4,
+    0x380, 0x4,
     0x5c8, 0x8,
     0x5eb, 0x5,
     0x5f5, 0x11,
     0x7b2, 0xe,
     0x7fb, 0x5,
     0x85f, 0x41,
-    0x8ad, 0x37,
+    0x8be, 0x16,
     0x9b3, 0x3,
     0x9cf, 0x8,
     0x9d8, 0x4,
@@ -465,7 +541,8 @@ pub fn is_printable(x: char) -> bool {
     0xa5f, 0x7,
     0xa76, 0xb,
     0xad1, 0xf,
-    0xaf2, 0xf,
+    0xaf2, 0x7,
+    0xafa, 0x7,
     0xb4e, 0x8,
     0xb58, 0x4,
     0xb78, 0xa,
@@ -478,21 +555,19 @@ pub fn is_printable(x: char) -> bool {
     0xbc3, 0x3,
     0xbd1, 0x6,
     0xbd8, 0xe,
-    0xbfb, 0x6,
+    0xbfb, 0x5,
     0xc3a, 0x3,
     0xc4e, 0x7,
-    0xc5a, 0x6,
+    0xc5b, 0x5,
     0xc70, 0x8,
     0xcce, 0x7,
     0xcd7, 0x7,
-    0xcf3, 0xf,
-    0xd4f, 0x8,
-    0xd58, 0x8,
-    0xd76, 0x3,
+    0xcf3, 0xe,
+    0xd50, 0x4,
     0xd97, 0x3,
     0xdc7, 0x3,
     0xdcb, 0x4,
-    0xde0, 0x12,
+    0xde0, 0x6,
     0xdf5, 0xc,
     0xe3b, 0x4,
     0xe5c, 0x25,
@@ -503,9 +578,8 @@ pub fn is_printable(x: char) -> bool {
     0x10c8, 0x5,
     0x137d, 0x3,
     0x139a, 0x6,
-    0x13f5, 0xb,
     0x169d, 0x3,
-    0x16f1, 0xf,
+    0x16f9, 0x7,
     0x1715, 0xb,
     0x1737, 0x9,
     0x1754, 0xc,
@@ -516,7 +590,6 @@ pub fn is_printable(x: char) -> bool {
     0x1878, 0x8,
     0x18ab, 0x5,
     0x18f6, 0xa,
-    0x191d, 0x3,
     0x192c, 0x4,
     0x193c, 0x4,
     0x1941, 0x3,
@@ -526,34 +599,34 @@ pub fn is_printable(x: char) -> bool {
     0x19db, 0x3,
     0x1a8a, 0x6,
     0x1a9a, 0x6,
-    0x1aae, 0x52,
+    0x1abf, 0x41,
     0x1b4c, 0x4,
     0x1b7d, 0x3,
     0x1bf4, 0x8,
     0x1c38, 0x3,
     0x1c4a, 0x3,
-    0x1c80, 0x40,
+    0x1c89, 0x37,
     0x1cc8, 0x8,
-    0x1cf7, 0x9,
-    0x1de7, 0x15,
+    0x1cfa, 0x6,
+    0x1df6, 0x5,
     0x1fff, 0x11,
     0x2028, 0x8,
     0x205f, 0x11,
     0x209d, 0x3,
-    0x20ba, 0x16,
+    0x20bf, 0x11,
     0x20f1, 0xf,
-    0x218a, 0x6,
-    0x23f4, 0xc,
+    0x218c, 0x4,
     0x2427, 0x19,
     0x244b, 0x15,
-    0x2b4d, 0x3,
-    0x2b5a, 0xa6,
+    0x2bba, 0x3,
+    0x2bd2, 0x1a,
+    0x2bf0, 0x10,
     0x2cf4, 0x5,
     0x2d28, 0x5,
     0x2d68, 0x7,
     0x2d71, 0xe,
     0x2d97, 0x9,
-    0x2e3c, 0x44,
+    0x2e45, 0x3b,
     0x2ef4, 0xc,
     0x2fd6, 0x1a,
     0x2ffc, 0x5,
@@ -561,32 +634,28 @@ pub fn is_printable(x: char) -> bool {
     0x312e, 0x3,
     0x31bb, 0x5,
     0x31e4, 0xc,
-    0x3400, 0x19c0,
-    0x4e00, 0x5200,
+    0x4db6, 0xa,
+    0x9fd6, 0x2a,
     0xa48d, 0x3,
     0xa4c7, 0x9,
     0xa62c, 0x14,
-    0xa698, 0x7,
     0xa6f8, 0x8,
-    0xa794, 0xc,
-    0xa7ab, 0x4d,
+    0xa7b8, 0x3f,
     0xa82c, 0x4,
     0xa83a, 0x6,
     0xa878, 0x8,
-    0xa8c5, 0x9,
+    0xa8c6, 0x8,
     0xa8da, 0x6,
-    0xa8fc, 0x4,
     0xa954, 0xb,
     0xa97d, 0x3,
     0xa9da, 0x4,
-    0xa9e0, 0x20,
     0xaa37, 0x9,
-    0xaa7c, 0x4,
     0xaac3, 0x18,
     0xaaf7, 0xa,
     0xab17, 0x9,
-    0xab2f, 0x91,
-    0xabfa, 0x2bb6,
+    0xab66, 0xa,
+    0xabfa, 0x6,
+    0xd7a4, 0xc,
     0xd7c7, 0x4,
     0xd7fc, 0x2104,
     0xfada, 0x26,
@@ -596,7 +665,6 @@ pub fn is_printable(x: char) -> bool {
     0xfd40, 0x10,
     0xfdc8, 0x28,
     0xfe1a, 0x6,
-    0xfe27, 0x9,
     0xfe6c, 0x4,
     0xfefd, 0x4,
     0xffbf, 0x3,
@@ -608,61 +676,123 @@ pub fn is_printable(x: char) -> bool {
     0xfb, 0x5,
     0x103, 0x4,
     0x134, 0x3,
-    0x18b, 0x5,
-    0x19c, 0x34,
+    0x19c, 0x4,
+    0x1a1, 0x2f,
     0x1fe, 0x82,
     0x29d, 0x3,
-    0x2d1, 0x2f,
+    0x2d1, 0xf,
+    0x2fc, 0x4,
     0x324, 0xc,
-    0x34b, 0x35,
+    0x34b, 0x5,
+    0x37b, 0x5,
     0x3c4, 0x4,
     0x3d6, 0x2a,
-    0x4aa, 0x356,
+    0x4aa, 0x6,
+    0x4d4, 0x4,
+    0x4fc, 0x4,
+    0x528, 0x8,
+    0x564, 0xb,
+    0x570, 0x90,
+    0x737, 0x9,
+    0x756, 0xa,
+    0x768, 0x98,
     0x839, 0x3,
-    0x860, 0xa0,
+    0x89f, 0x8,
+    0x8b0, 0x30,
+    0x8f6, 0x5,
     0x91c, 0x3,
     0x93a, 0x5,
     0x940, 0x40,
-    0x9b8, 0x6,
-    0x9c0, 0x40,
+    0x9b8, 0x4,
     0xa07, 0x5,
     0xa34, 0x4,
     0xa3b, 0x4,
     0xa48, 0x8,
     0xa59, 0x7,
-    0xa80, 0x80,
+    0xaa0, 0x20,
+    0xae7, 0x4,
+    0xaf7, 0x9,
     0xb36, 0x3,
     0xb73, 0x5,
-    0xb80, 0x80,
-    0xc49, 0x217,
+    0xb92, 0x7,
+    0xb9d, 0xc,
+    0xbb0, 0x50,
+    0xc49, 0x37,
+    0xcb3, 0xd,
+    0xcf3, 0x7,
+    0xd00, 0x160,
     0xe7f, 0x181,
     0x104e, 0x4,
-    0x1070, 0x10,
+    0x1070, 0xf,
     0x10c2, 0xe,
     0x10e9, 0x7,
     0x10fa, 0x6,
-    0x1144, 0x3c,
-    0x11c9, 0x7,
-    0x11da, 0x4a6,
+    0x1144, 0xc,
+    0x1177, 0x9,
+    0x11f5, 0xb,
+    0x123f, 0x41,
+    0x12aa, 0x6,
+    0x12eb, 0x5,
+    0x12fa, 0x6,
+    0x1351, 0x6,
+    0x1358, 0x5,
+    0x136d, 0x3,
+    0x1375, 0x8b,
+    0x145e, 0x22,
+    0x14c8, 0x8,
+    0x14da, 0xa6,
+    0x15de, 0x22,
+    0x1645, 0xb,
+    0x165a, 0x6,
+    0x166d, 0x13,
     0x16b8, 0x8,
-    0x16ca, 0x936,
-    0x236f, 0x91,
-    0x2463, 0xd,
-    0x2474, 0xb8c,
-    0x342f, 0x33d1,
-    0x6a39, 0x4c7,
+    0x16ca, 0x36,
+    0x171a, 0x3,
+    0x172c, 0x4,
+    0x1740, 0x160,
+    0x18f3, 0xc,
+    0x1900, 0x1c0,
+    0x1af9, 0x107,
+    0x1c46, 0xa,
+    0x1c6d, 0x3,
+    0x1cb7, 0x349,
+    0x239a, 0x66,
+    0x2475, 0xb,
+    0x2544, 0xabc,
+    0x342f, 0xfd1,
+    0x4647, 0x21b9,
+    0x6a39, 0x7,
+    0x6a6a, 0x4,
+    0x6a70, 0x60,
+    0x6af6, 0xa,
+    0x6b46, 0xa,
+    0x6b78, 0x5,
+    0x6b90, 0x370,
     0x6f45, 0xb,
     0x6f7f, 0x10,
-    0x6fa0, 0x4060,
-    0xb002, 0x1ffe,
+    0x6fa0, 0x40,
+    0x6fe1, 0x1f,
+    0x87ed, 0x13,
+    0x8af3, 0x250d,
+    0xb002, 0xbfe,
+    0xbc6b, 0x5,
+    0xbc7d, 0x3,
+    0xbc89, 0x7,
+    0xbca0, 0x1360,
     0xd0f6, 0xa,
     0xd173, 0x8,
-    0xd1de, 0x22,
+    0xd1e9, 0x17,
     0xd246, 0xba,
     0xd357, 0x9,
     0xd372, 0x8e,
     0xd547, 0x3,
-    0xd800, 0x1600,
+    0xda8c, 0xf,
+    0xdab0, 0x550,
+    0xe02b, 0x7d5,
+    0xe8d7, 0x29,
+    0xe94b, 0x5,
+    0xe95a, 0x4,
+    0xe960, 0x4a0,
     0xee3c, 0x6,
     0xee43, 0x4,
     0xee9c, 0x5,
@@ -670,24 +800,27 @@ pub fn is_printable(x: char) -> bool {
     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,
 ];
index ca718d29952d93bd1b6ec905fb2d9da7d393e1b4..2e08508de67f3ad1b887c8d922ae580e1360de94 100644 (file)
@@ -1307,54 +1307,68 @@ unsafe impl<I> TrustedLen for Enumerate<I>
 #[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)
     }
 }
 
@@ -1406,9 +1420,13 @@ impl<I: Iterator> Peekable<I> {
     #[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()
     }
 }
 
index 871b63145ca6d24c8981bae053aadc54bfee7a6c..ede45111ebbc587371980cd02e27129f2022d6ef 100644 (file)
@@ -983,7 +983,11 @@ fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
 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> {}
@@ -1107,7 +1111,11 @@ fn iter_nth(&mut self, n: usize) -> Option<&'a mut 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> {}
index 196750254af30eacadeb20f8594a0208dc319f92..b4cd52e59f658079a1be9f6e0ef86090b0a8c2a9 100644 (file)
@@ -424,6 +424,17 @@ fn next(&mut self) -> Option<char> {
         })
     }
 
+    #[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();
@@ -432,6 +443,12 @@ fn size_hint(&self) -> (usize, Option<usize>) {
         // `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")]
@@ -501,10 +518,21 @@ fn next(&mut self) -> Option<(usize, char)> {
         }
     }
 
+    #[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")]
index 7da0b6902f2717f5f6a584cd77d2c15eba74ed96..b4088ffbf89a952980558adde182ef1f6b6d8609 100644 (file)
@@ -162,6 +162,8 @@ fn string(c: char) -> String {
     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');
index 58b6444ef88cd95f278d4c0b458516573b1cc5c4..274539dfa6699ff2ae4be624b0d717fbdf769fd5 100644 (file)
@@ -274,6 +274,74 @@ fn test_iterator_peekable_last() {
     let mut it = ys.iter().peekable();
     assert_eq!(it.peek(), Some(&&0));
     assert_eq!(it.last(), Some(&0));
+
+    let mut it = ys.iter().peekable();
+    assert_eq!(it.next(), Some(&0));
+    assert_eq!(it.peek(), None);
+    assert_eq!(it.last(), None);
+}
+
+/// This is an iterator that follows the Iterator contract,
+/// but it is not fused. After having returned None once, it will start
+/// producing elements if .next() is called again.
+pub struct CycleIter<'a, T: 'a> {
+    index: usize,
+    data: &'a [T],
+}
+
+pub fn cycle<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]
index 79dcca7671a2d0215340f2185cc7338c41a62f60..08c2cd0a7326f27534db3fa5fe5d2c9e08700482 100644 (file)
@@ -11,7 +11,6 @@
 use std::prelude::v1::*;
 use std::{i16, f64};
 use super::super::*;
-use core::num::flt2dec::*;
 use core::num::bignum::Big32x40 as Big;
 use core::num::flt2dec::strategy::dragon::*;
 
index 2d4afceda191f1bbd2798ecf7e2a798636431b59..311bd252353c770b4b7d7fab1a529f5f72908495 100644 (file)
@@ -10,7 +10,6 @@
 
 use std::{i16, f64};
 use super::super::*;
-use core::num::flt2dec::*;
 use core::num::flt2dec::strategy::grisu::*;
 
 #[test]
index e5a3abc2ea982e01a8e06bd95d0905790c086ec3..1ae906e0aa4e013016661fda77517168ec7903d1 100644 (file)
@@ -34,8 +34,9 @@
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::ext::proc_macro_shim::build_block_emitter;
-use syntax::parse::token::{self, Token, gensym_ident, str_to_ident};
+use syntax::parse::token::{self, Token};
 use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax::tokenstream::{TokenTree, TokenStream};
 
 // ____________________________________________________________________________________________
@@ -124,7 +125,7 @@ fn qquote_iter<'cx>(cx: &'cx mut ExtCtxt, depth: i64, ts: TokenStream) -> (Bindi
                     } // produce an error or something first
                     let exp = vec![exp.unwrap().to_owned()];
                     debug!("RHS: {:?}", exp.clone());
-                    let new_id = gensym_ident("tmp");
+                    let new_id = Ident::with_empty_ctxt(Symbol::gensym("tmp"));
                     debug!("RHS TS: {:?}", TokenStream::from_tts(exp.clone()));
                     debug!("RHS TS TT: {:?}", TokenStream::from_tts(exp.clone()).to_vec());
                     bindings.push((new_id, TokenStream::from_tts(exp)));
@@ -179,7 +180,7 @@ fn unravel_concats(tss: Vec<TokenStream>) -> TokenStream {
     };
 
     while let Some(ts) = pushes.pop() {
-        output = build_fn_call(str_to_ident("concat"),
+        output = build_fn_call(Ident::from_str("concat"),
                                concat(concat(ts,
                                              from_tokens(vec![Token::Comma])),
                                       output));
@@ -209,18 +210,19 @@ fn convert_complex_tts<'cx>(cx: &'cx mut ExtCtxt, tts: Vec<QTT>) -> (Bindings, T
             // FIXME handle sequence repetition tokens
             QTT::QDL(qdl) => {
                 debug!("  QDL: {:?} ", qdl.tts);
-                let new_id = gensym_ident("qdl_tmp");
+                let new_id = Ident::with_empty_ctxt(Symbol::gensym("qdl_tmp"));
                 let mut cct_rec = convert_complex_tts(cx, qdl.tts);
                 bindings.append(&mut cct_rec.0);
                 bindings.push((new_id, cct_rec.1));
 
                 let sep = build_delim_tok(qdl.delim);
 
-                pushes.push(build_mod_call(vec![str_to_ident("proc_macro_tokens"),
-                                               str_to_ident("build"),
-                                               str_to_ident("build_delimited")],
-                                          concat(from_tokens(vec![Token::Ident(new_id)]),
-                                                 concat(lex(","), sep))));
+                pushes.push(build_mod_call(
+                    vec![Ident::from_str("proc_macro_tokens"),
+                         Ident::from_str("build"),
+                         Ident::from_str("build_delimited")],
+                    concat(from_tokens(vec![Token::Ident(new_id)]), concat(lex(","), sep)),
+                ));
             }
             QTT::QIdent(t) => {
                 pushes.push(TokenStream::from_tts(vec![t]));
@@ -250,13 +252,13 @@ fn unravel(binds: Bindings) -> TokenStream {
 
 /// Checks if the Ident is `unquote`.
 fn is_unquote(id: Ident) -> bool {
-    let qq = str_to_ident("unquote");
+    let qq = Ident::from_str("unquote");
     id.name == qq.name  // We disregard context; unquote is _reserved_
 }
 
 /// Checks if the Ident is `quote`.
 fn is_qquote(id: Ident) -> bool {
-    let qq = str_to_ident("qquote");
+    let qq = Ident::from_str("qquote");
     id.name == qq.name  // We disregard context; qquote is _reserved_
 }
 
@@ -266,7 +268,8 @@ mod int_build {
 
     use syntax::ast::{self, Ident};
     use syntax::codemap::{DUMMY_SP};
-    use syntax::parse::token::{self, Token, keywords, str_to_ident};
+    use syntax::parse::token::{self, Token, Lit};
+    use syntax::symbol::keywords;
     use syntax::tokenstream::{TokenTree, TokenStream};
 
     // ____________________________________________________________________________________________
@@ -277,19 +280,19 @@ pub fn emit_token(t: Token) -> 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"),
         };
 
@@ -388,9 +391,10 @@ pub fn build_token_tt(t: Token) -> TokenStream {
             Token::Underscore => lex("_"),
             Token::Literal(lit, sfx) => emit_lit(lit, sfx),
             // fix ident expansion information... somehow
-            Token::Ident(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))", ident.name)),
-            Token::Lifetime(ident) => lex(&format!("Token::Ident(str_to_ident(\"{}\"))",
-                                                   ident.name)),
+            Token::Ident(ident) =>
+                lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)),
+            Token::Lifetime(ident) =>
+                lex(&format!("Token::Ident(Ident::from_str(\"{}\"))", ident.name)),
             _ => panic!("Unhandled case!"),
         }
     }
@@ -408,7 +412,7 @@ pub fn as_tt(t: Token) -> TokenTree {
 
     /// 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()
     }
 
index 7b7590b863b71aa5e5eba1e63d13a5f707dea352..d39aba0aa7787a26854decbcca1675dbee84b9f3 100644 (file)
@@ -13,7 +13,8 @@
 
 use syntax::ast::Ident;
 use syntax::codemap::DUMMY_SP;
-use syntax::parse::token::{self, Token, keywords, str_to_ident};
+use syntax::parse::token::{self, Token};
+use syntax::symbol::keywords;
 use syntax::tokenstream::{self, TokenTree, TokenStream};
 use std::rc::Rc;
 
@@ -43,13 +44,13 @@ pub fn ident_eq(tident: &TokenTree, id: Ident) -> bool {
 
 /// Convert a `&str` into a Token.
 pub fn str_to_token_ident(s: &str) -> Token {
-    Token::Ident(str_to_ident(s))
+    Token::Ident(Ident::from_str(s))
 }
 
 /// Converts a keyword (from `syntax::parse::token::keywords`) into a Token that
 /// corresponds to it.
 pub fn keyword_to_token_ident(kw: keywords::Keyword) -> Token {
-    Token::Ident(str_to_ident(&kw.name().as_str()[..]))
+    Token::Ident(Ident::from_str(&kw.name().as_str()[..]))
 }
 
 // ____________________________________________________________________________________________
index 22c7d14be29d205dbe172c7a96ca322605d7df6d..c399623462b5d732368fe2fab0ac64b762521ee2 100644 (file)
@@ -223,7 +223,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
                 expr_exit
             }
 
-            hir::ExprLoop(ref body, _) => {
+            hir::ExprLoop(ref body, _, _) => {
                 //
                 //     [pred]
                 //       |
@@ -282,9 +282,10 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
                 self.add_unreachable_node()
             }
 
-            hir::ExprBreak(label) => {
+            hir::ExprBreak(label, ref opt_expr) => {
+                let v = self.opt_expr(opt_expr, pred);
                 let loop_scope = self.find_scope(expr, label.map(|l| l.node));
-                let b = self.add_ast_node(expr.id, &[pred]);
+                let b = self.add_ast_node(expr.id, &[v]);
                 self.add_exiting_edge(expr, b,
                                       loop_scope, loop_scope.break_index);
                 self.add_unreachable_node()
@@ -299,15 +300,15 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
             }
 
             hir::ExprArray(ref elems) => {
-                self.straightline(expr, pred, elems.iter().map(|e| &**e))
+                self.straightline(expr, pred, elems.iter().map(|e| &*e))
             }
 
             hir::ExprCall(ref func, ref args) => {
-                self.call(expr, pred, &func, args.iter().map(|e| &**e))
+                self.call(expr, pred, &func, args.iter().map(|e| &*e))
             }
 
             hir::ExprMethodCall(.., ref args) => {
-                self.call(expr, pred, &args[0], args[1..].iter().map(|e| &**e))
+                self.call(expr, pred, &args[0], args[1..].iter().map(|e| &*e))
             }
 
             hir::ExprIndex(ref l, ref r) |
@@ -320,7 +321,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
             }
 
             hir::ExprTup(ref exprs) => {
-                self.straightline(expr, pred, exprs.iter().map(|e| &**e))
+                self.straightline(expr, pred, exprs.iter().map(|e| &*e))
             }
 
             hir::ExprStruct(_, ref fields, ref base) => {
@@ -353,8 +354,8 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
             }
 
             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])
             }
 
index 8ba52cdb64f5fd83a6c274f2dfa3720f676fdfdd..abc35634d15f456e21372a311f77bff177392a6e 100644 (file)
@@ -64,7 +64,7 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
                 None => continue,
             };
 
-            let (message, label) = match &*name {
+            let (message, label) = match &*name.as_str() {
                 "C" => {
                     conflicting_reprs += 1;
                     if target != Target::Struct &&
@@ -120,7 +120,7 @@ fn check_repr(&self, attr: &ast::Attribute, target: Target) {
     }
 
     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),
index 4cfa889ec561676f7e1156bd7c55cb4afd51827a..7dd88e36dd1f55ca7fe93d2092f2f893e801fe8c 100644 (file)
@@ -882,7 +882,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_block(block);
             walk_opt_sp_name(visitor, opt_sp_name);
         }
-        ExprLoop(ref block, ref opt_sp_name) => {
+        ExprLoop(ref block, ref opt_sp_name, _) => {
             visitor.visit_block(block);
             walk_opt_sp_name(visitor, opt_sp_name);
         }
@@ -923,7 +923,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             }
             visitor.visit_path(path, expression.id)
         }
-        ExprBreak(ref opt_sp_name) | ExprAgain(ref opt_sp_name) => {
+        ExprBreak(ref opt_sp_name, ref opt_expr) => {
+            walk_opt_sp_name(visitor, opt_sp_name);
+            walk_list!(visitor, visit_expr, opt_expr);
+        }
+        ExprAgain(ref opt_sp_name) => {
             walk_opt_sp_name(visitor, opt_sp_name);
         }
         ExprRet(ref optional_expression) => {
index 05c4ae521803aa36f1425fff099ed21c2ce8193f..5af7c18e1a1078f4c9cc14849f59b0691d8b01ba 100644 (file)
@@ -53,8 +53,8 @@
 use syntax::errors;
 use syntax::ptr::P;
 use syntax::codemap::{respan, Spanned};
-use syntax::parse::token;
 use syntax::std_inject;
+use syntax::symbol::{Symbol, keywords};
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
 
@@ -149,7 +149,7 @@ fn diagnostic(&self) -> &errors::Handler {
     }
 
     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
@@ -210,8 +210,8 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
         hir::Arm {
             attrs: self.lower_attrs(&arm.attrs),
             pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
-            guard: arm.guard.as_ref().map(|ref x| self.lower_expr(x)),
-            body: self.lower_expr(&arm.body),
+            guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
+            body: P(self.lower_expr(&arm.body)),
         }
     }
 
@@ -262,10 +262,10 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                     hir::TyObjectSum(self.lower_ty(ty), self.lower_bounds(bounds))
                 }
                 TyKind::Array(ref ty, ref e) => {
-                    hir::TyArray(self.lower_ty(ty), self.lower_expr(e))
+                    hir::TyArray(self.lower_ty(ty), P(self.lower_expr(e)))
                 }
                 TyKind::Typeof(ref expr) => {
-                    hir::TyTypeof(self.lower_expr(expr))
+                    hir::TyTypeof(P(self.lower_expr(expr)))
                 }
                 TyKind::PolyTraitRef(ref bounds) => {
                     hir::TyPolyTraitRef(self.lower_bounds(bounds))
@@ -292,7 +292,7 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
                 name: v.node.name.name,
                 attrs: self.lower_attrs(&v.node.attrs),
                 data: self.lower_variant_data(&v.node.data),
-                disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_expr(e)),
+                disr_expr: v.node.disr_expr.as_ref().map(|e| P(self.lower_expr(e))),
             },
             span: v.span,
         }
@@ -350,7 +350,7 @@ fn lower_local(&mut self, l: &Local) -> P<hir::Local> {
             id: l.id,
             ty: l.ty.as_ref().map(|t| self.lower_ty(t)),
             pat: self.lower_pat(&l.pat),
-            init: l.init.as_ref().map(|e| self.lower_expr(e)),
+            init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
             span: l.span,
             attrs: l.attrs.clone(),
         })
@@ -400,8 +400,8 @@ fn lower_ty_param(&mut self, tp: &TyParam) -> hir::TyParam {
         // Don't expose `Self` (recovered "keyword used as ident" parse error).
         // `rustc::ty` expects `Self` to be only used for a trait's `Self`.
         // Instead, use gensym("Self") to create a distinct name that looks the same.
-        if name == token::keywords::SelfType.name() {
-            name = token::gensym("Self");
+        if name == keywords::SelfType.name() {
+            name = Symbol::gensym("Self");
         }
 
         hir::TyParam {
@@ -540,7 +540,7 @@ fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::Stru
         hir::StructField {
             span: f.span,
             id: f.id,
-            name: f.ident.map(|ident| ident.name).unwrap_or(token::intern(&index.to_string())),
+            name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
             vis: self.lower_visibility(&f.vis),
             ty: self.lower_ty(&f.ty),
             attrs: self.lower_attrs(&f.attrs),
@@ -550,7 +550,7 @@ fn lower_struct_field(&mut self, (index, f): (usize, &StructField)) -> hir::Stru
     fn lower_field(&mut self, f: &Field) -> hir::Field {
         hir::Field {
             name: respan(f.ident.span, f.ident.node.name),
-            expr: self.lower_expr(&f.expr),
+            expr: P(self.lower_expr(&f.expr)),
             span: f.span,
             is_shorthand: f.is_shorthand,
         }
@@ -599,10 +599,10 @@ fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ {
             ItemKind::Static(ref t, m, ref e) => {
                 hir::ItemStatic(self.lower_ty(t),
                                 self.lower_mutability(m),
-                                self.lower_expr(e))
+                                P(self.lower_expr(e)))
             }
             ItemKind::Const(ref t, ref e) => {
-                hir::ItemConst(self.lower_ty(t), self.lower_expr(e))
+                hir::ItemConst(self.lower_ty(t), P(self.lower_expr(e)))
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
                 let body = self.lower_block(body);
@@ -611,7 +611,7 @@ fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ {
                             self.lower_constness(constness),
                             abi,
                             self.lower_generics(generics),
-                            self.expr_block(body, ThinVec::new()))
+                            P(self.expr_block(body, ThinVec::new())))
             }
             ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
@@ -672,13 +672,13 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                 node: match i.node {
                     TraitItemKind::Const(ref ty, ref default) => {
                         hir::ConstTraitItem(this.lower_ty(ty),
-                                            default.as_ref().map(|x| this.lower_expr(x)))
+                                            default.as_ref().map(|x| P(this.lower_expr(x))))
                     }
                     TraitItemKind::Method(ref sig, ref body) => {
                         hir::MethodTraitItem(this.lower_method_sig(sig),
                                              body.as_ref().map(|x| {
                             let body = this.lower_block(x);
-                            this.expr_block(body, ThinVec::new())
+                            P(this.expr_block(body, ThinVec::new()))
                         }))
                     }
                     TraitItemKind::Type(ref bounds, ref default) => {
@@ -702,12 +702,12 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
                 defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
                 node: match i.node {
                     ImplItemKind::Const(ref ty, ref expr) => {
-                        hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr))
+                        hir::ImplItemKind::Const(this.lower_ty(ty), P(this.lower_expr(expr)))
                     }
                     ImplItemKind::Method(ref sig, ref body) => {
                         let body = this.lower_block(body);
                         hir::ImplItemKind::Method(this.lower_method_sig(sig),
-                                                  this.expr_block(body, ThinVec::new()))
+                                                  P(this.expr_block(body, ThinVec::new())))
                     }
                     ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)),
                     ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
@@ -885,7 +885,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                         }
                     })
                 }
-                PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
+                PatKind::Lit(ref e) => hir::PatKind::Lit(P(self.lower_expr(e))),
                 PatKind::TupleStruct(ref path, ref pats, ddpos) => {
                     hir::PatKind::TupleStruct(self.lower_path(path),
                                         pats.iter().map(|x| self.lower_pat(x)).collect(), ddpos)
@@ -920,7 +920,7 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
                     hir::PatKind::Ref(self.lower_pat(inner), self.lower_mutability(mutbl))
                 }
                 PatKind::Range(ref e1, ref e2) => {
-                    hir::PatKind::Range(self.lower_expr(e1), self.lower_expr(e2))
+                    hir::PatKind::Range(P(self.lower_expr(e1)), P(self.lower_expr(e2)))
                 }
                 PatKind::Slice(ref before, ref slice, ref after) => {
                     hir::PatKind::Slice(before.iter().map(|x| self.lower_pat(x)).collect(),
@@ -933,8 +933,8 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
         })
     }
 
-    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:
@@ -954,7 +954,7 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                 //
                 // But for now there are type-inference issues doing that.
                 ExprKind::Box(ref e) => {
-                    hir::ExprBox(self.lower_expr(e))
+                    hir::ExprBox(P(self.lower_expr(e)))
                 }
 
                 // Desugar ExprBox: `in (PLACE) EXPR`
@@ -968,8 +968,8 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::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");
@@ -983,7 +983,7 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                     let make_call = |this: &mut LoweringContext, p, args| {
                         let path = this.std_path(e.span, p);
                         let path = this.expr_path(path, ThinVec::new());
-                        this.expr_call(e.span, path, args)
+                        P(this.expr_call(e.span, path, args))
                     };
 
                     let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
@@ -996,11 +996,11 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::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)
                     };
 
@@ -1013,7 +1013,7 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::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)
@@ -1021,11 +1021,11 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
 
                     // pop_unsafe!(EXPR));
                     let pop_unsafe_expr = {
-                        let value_expr = self.signal_block_expr(hir_vec![],
-                                                                value_expr,
-                                                                e.span,
-                                                                hir::PopUnstableBlock,
-                                                                ThinVec::new());
+                        let value_expr = P(self.signal_block_expr(hir_vec![],
+                                                                  value_expr,
+                                                                  e.span,
+                                                                  hir::PopUnstableBlock,
+                                                                  ThinVec::new()));
                         self.signal_block_expr(hir_vec![],
                                                value_expr,
                                                e.span,
@@ -1047,11 +1047,11 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
 
                         let place = self.expr_ident(e.span, place_ident, place_binding);
                         let call = make_call(self, &inplace_finalize, hir_vec![place]);
-                        self.signal_block_expr(hir_vec![call_move_val_init],
-                                               call,
-                                               e.span,
-                                               hir::PushUnsafeBlock(hir::CompilerGenerated),
-                                               ThinVec::new())
+                        P(self.signal_block_expr(hir_vec![call_move_val_init],
+                                                 call,
+                                                 e.span,
+                                                 hir::PushUnsafeBlock(hir::CompilerGenerated),
+                                                 ThinVec::new()))
                     };
 
                     return self.signal_block_expr(hir_vec![s1, s2, s3],
@@ -1065,15 +1065,15 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                     hir::ExprArray(exprs.iter().map(|x| self.lower_expr(x)).collect())
                 }
                 ExprKind::Repeat(ref expr, ref count) => {
-                    let expr = self.lower_expr(expr);
-                    let count = self.lower_expr(count);
+                    let expr = P(self.lower_expr(expr));
+                    let count = P(self.lower_expr(count));
                     hir::ExprRepeat(expr, count)
                 }
                 ExprKind::Tup(ref elts) => {
                     hir::ExprTup(elts.iter().map(|x| self.lower_expr(x)).collect())
                 }
                 ExprKind::Call(ref f, ref args) => {
-                    let f = self.lower_expr(f);
+                    let f = P(self.lower_expr(f));
                     hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
                 }
                 ExprKind::MethodCall(i, ref tps, ref args) => {
@@ -1083,27 +1083,27 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                 }
                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
                     let binop = self.lower_binop(binop);
-                    let lhs = self.lower_expr(lhs);
-                    let rhs = self.lower_expr(rhs);
+                    let lhs = P(self.lower_expr(lhs));
+                    let rhs = P(self.lower_expr(rhs));
                     hir::ExprBinary(binop, lhs, rhs)
                 }
                 ExprKind::Unary(op, ref ohs) => {
                     let op = self.lower_unop(op);
-                    let ohs = self.lower_expr(ohs);
+                    let ohs = P(self.lower_expr(ohs));
                     hir::ExprUnary(op, ohs)
                 }
                 ExprKind::Lit(ref l) => hir::ExprLit(P((**l).clone())),
                 ExprKind::Cast(ref expr, ref ty) => {
-                    let expr = self.lower_expr(expr);
+                    let expr = P(self.lower_expr(expr));
                     hir::ExprCast(expr, self.lower_ty(ty))
                 }
                 ExprKind::Type(ref expr, ref ty) => {
-                    let expr = self.lower_expr(expr);
+                    let expr = P(self.lower_expr(expr));
                     hir::ExprType(expr, self.lower_ty(ty))
                 }
                 ExprKind::AddrOf(m, ref ohs) => {
                     let m = self.lower_mutability(m);
-                    let ohs = self.lower_expr(ohs);
+                    let ohs = P(self.lower_expr(ohs));
                     hir::ExprAddrOf(m, ohs)
                 }
                 // More complicated than you might expect because the else branch
@@ -1114,7 +1114,7 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                             ExprKind::IfLet(..) => {
                                 // wrap the if-let expr in a block
                                 let span = els.span;
-                                let els = self.lower_expr(els);
+                                let els = P(self.lower_expr(els));
                                 let id = self.next_id();
                                 let blk = P(hir::Block {
                                     stmts: hir_vec![],
@@ -1123,23 +1123,25 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                                     rules: hir::DefaultBlock,
                                     span: span,
                                 });
-                                self.expr_block(blk, ThinVec::new())
+                                P(self.expr_block(blk, ThinVec::new()))
                             }
-                            _ => self.lower_expr(els),
+                            _ => P(self.lower_expr(els)),
                         }
                     });
 
-                    hir::ExprIf(self.lower_expr(cond), self.lower_block(blk), else_opt)
+                    hir::ExprIf(P(self.lower_expr(cond)), self.lower_block(blk), else_opt)
                 }
                 ExprKind::While(ref cond, ref body, opt_ident) => {
-                    hir::ExprWhile(self.lower_expr(cond), self.lower_block(body),
+                    hir::ExprWhile(P(self.lower_expr(cond)), self.lower_block(body),
                                    self.lower_opt_sp_ident(opt_ident))
                 }
                 ExprKind::Loop(ref body, opt_ident) => {
-                    hir::ExprLoop(self.lower_block(body), self.lower_opt_sp_ident(opt_ident))
+                    hir::ExprLoop(self.lower_block(body),
+                                  self.lower_opt_sp_ident(opt_ident),
+                                  hir::LoopSource::Loop)
                 }
                 ExprKind::Match(ref expr, ref arms) => {
-                    hir::ExprMatch(self.lower_expr(expr),
+                    hir::ExprMatch(P(self.lower_expr(expr)),
                                    arms.iter().map(|x| self.lower_arm(x)).collect(),
                                    hir::MatchSource::Normal)
                 }
@@ -1147,33 +1149,33 @@ fn lower_expr(&mut self, e: &Expr) -> P<hir::Expr> {
                     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)
@@ -1183,13 +1185,13 @@ fn make_struct(this: &mut LoweringContext,
                             this.expr_path(struct_path, ast_expr.attrs.clone())
                         } else {
                             let fields = fields.into_iter().map(|&(s, e)| {
-                                let expr = this.lower_expr(&e);
-                                let signal_block = this.signal_block_expr(hir_vec![],
-                                                                          expr,
-                                                                          e.span,
-                                                                          hir::PopUnstableBlock,
-                                                                          ThinVec::new());
-                                this.field(token::intern(s), signal_block, ast_expr.span)
+                                let expr = P(this.lower_expr(&e));
+                                let signal_block = P(this.signal_block_expr(hir_vec![],
+                                                                            expr,
+                                                                            e.span,
+                                                                            hir::PopUnstableBlock,
+                                                                            ThinVec::new()));
+                                this.field(Symbol::intern(s), signal_block, ast_expr.span)
                             }).collect();
                             let attrs = ast_expr.attrs.clone();
 
@@ -1242,9 +1244,12 @@ fn make_struct(this: &mut LoweringContext,
                     });
                     hir::ExprPath(hir_qself, self.lower_path(path))
                 }
-                ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
+                ExprKind::Break(opt_ident, ref opt_expr) => {
+                    hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
+                                   opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
+                }
                 ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
-                ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
+                ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
                 ExprKind::InlineAsm(ref asm) => {
                     let hir_asm = hir::InlineAsm {
                         inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
@@ -1272,20 +1277,19 @@ fn make_struct(this: &mut LoweringContext,
                 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
@@ -1302,13 +1306,13 @@ fn make_struct(this: &mut LoweringContext,
                     // `<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 {
@@ -1322,7 +1326,7 @@ fn make_struct(this: &mut LoweringContext,
                                                 attrs: hir_vec![],
                                                 pats: hir_vec![pat_under],
                                                 guard: Some(cond),
-                                                body: self.expr_block(then, ThinVec::new()),
+                                                body: P(self.expr_block(then, ThinVec::new())),
                                             });
                                             else_opt.map(|else_opt| (else_opt, true))
                                         }
@@ -1362,7 +1366,7 @@ fn make_struct(this: &mut LoweringContext,
                     arms.extend(else_if_arms);
                     arms.push(else_arm);
 
-                    let sub_expr = self.lower_expr(sub_expr);
+                    let sub_expr = P(self.lower_expr(sub_expr));
                     // add attributes to the outer returned expr node
                     return self.expr(e.span,
                                      hir::ExprMatch(sub_expr,
@@ -1388,7 +1392,7 @@ fn make_struct(this: &mut LoweringContext,
                     // `<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)
                     };
@@ -1402,7 +1406,7 @@ fn make_struct(this: &mut LoweringContext,
 
                     // `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,
@@ -1410,11 +1414,12 @@ fn make_struct(this: &mut LoweringContext,
                                                ThinVec::new());
 
                     // `[opt_ident]: loop { ... }`
-                    let loop_block = self.block_expr(match_expr);
-                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
+                    let loop_block = P(self.block_expr(P(match_expr)));
+                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
+                                                  hir::LoopSource::WhileLet);
                     // add attributes to the outer returned expr node
                     let attrs = e.attrs.clone();
-                    return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
+                    return hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs };
                 }
 
                 // Desugar ExprForLoop
@@ -1471,20 +1476,23 @@ fn make_struct(this: &mut LoweringContext,
                     // `match ::std::iter::Iterator::next(&mut iter) { ... }`
                     let match_expr = {
                         let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
-                        let iter = self.expr_ident(e.span, iter, iter_pat.id);
+                        let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
                         let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
                         let next_path = self.expr_path(next_path, ThinVec::new());
-                        let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]);
+                        let next_expr = P(self.expr_call(e.span, next_path,
+                                          hir_vec![ref_mut_iter]));
                         let arms = hir_vec![pat_arm, break_arm];
 
-                        self.expr(e.span,
-                                  hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar),
-                                  ThinVec::new())
+                        P(self.expr(e.span,
+                                    hir::ExprMatch(next_expr, arms,
+                                                   hir::MatchSource::ForLoopDesugar),
+                                    ThinVec::new()))
                     };
 
                     // `[opt_ident]: loop { ... }`
-                    let loop_block = self.block_expr(match_expr);
-                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
+                    let loop_block = P(self.block_expr(match_expr));
+                    let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
+                                                  hir::LoopSource::ForLoop);
                     let loop_expr = P(hir::Expr {
                         id: e.id,
                         node: loop_expr,
@@ -1501,13 +1509,13 @@ fn make_struct(this: &mut LoweringContext,
                                                            &["iter", "IntoIterator", "into_iter"]);
 
                         let into_iter = self.expr_path(into_iter_path, ThinVec::new());
-                        self.expr_call(e.span, into_iter, hir_vec![head])
+                        P(self.expr_call(e.span, into_iter, hir_vec![head]))
                     };
 
-                    let match_expr = self.expr_match(e.span,
-                                                     into_iter_expr,
-                                                     hir_vec![iter_arm],
-                                                     hir::MatchSource::ForLoopDesugar);
+                    let match_expr = P(self.expr_match(e.span,
+                                                       into_iter_expr,
+                                                       hir_vec![iter_arm],
+                                                       hir::MatchSource::ForLoopDesugar));
 
                     // `{ let _result = ...; _result }`
                     // underscore prevents an unused_variables lint if the head diverges
@@ -1515,8 +1523,8 @@ fn make_struct(this: &mut LoweringContext,
                     let (let_stmt, let_stmt_binding) =
                         self.stmt_let(e.span, false, result_ident, match_expr);
 
-                    let result = self.expr_ident(e.span, result_ident, let_stmt_binding);
-                    let block = self.block_all(e.span, hir_vec![let_stmt], Some(result));
+                    let result = P(self.expr_ident(e.span, result_ident, let_stmt_binding));
+                    let block = P(self.block_all(e.span, hir_vec![let_stmt], Some(result)));
                     // add the attributes to the outer returned expr node
                     return self.expr_block(block, e.attrs.clone());
                 }
@@ -1536,7 +1544,7 @@ fn make_struct(this: &mut LoweringContext,
                     // { 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,
@@ -1545,20 +1553,20 @@ fn make_struct(this: &mut LoweringContext,
 
                         let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
                         let path = self.expr_path(path, ThinVec::new());
-                        let call = self.expr_call(e.span, path, hir_vec![sub_expr]);
+                        let call = P(self.expr_call(e.span, path, hir_vec![sub_expr]));
 
-                        self.signal_block_expr(hir_vec![],
-                                               call,
-                                               e.span,
-                                               hir::PushUnstableBlock,
-                                               ThinVec::new())
+                        P(self.signal_block_expr(hir_vec![],
+                                                 call,
+                                                 e.span,
+                                                 hir::PushUnstableBlock,
+                                                 ThinVec::new()))
                     };
 
                     // Ok(val) => val
                     let ok_arm = {
                         let val_ident = self.str_to_ident("val");
                         let val_pat = self.pat_ident(e.span, val_ident);
-                        let val_expr = self.expr_ident(e.span, val_ident, val_pat.id);
+                        let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
                         let ok_pat = self.pat_ok(e.span, val_pat);
 
                         self.arm(hir_vec![ok_pat], val_expr)
@@ -1578,15 +1586,16 @@ fn make_struct(this: &mut LoweringContext,
                         let from_err_expr = {
                             let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
                             let from_err = self.expr_path(path, ThinVec::new());
-                            self.expr_call(e.span, from_err, hir_vec![from_expr])
+                            P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
                         };
 
-                        let ret_expr = self.expr(e.span,
-                                                 hir::Expr_::ExprRet(Some(from_err_expr)),
-                                                                     ThinVec::new());
+                        let ret_expr = P(self.expr(e.span,
+                                                   hir::Expr_::ExprRet(Some(from_err_expr)),
+                                                                       ThinVec::new()));
                         let ret_stmt = self.stmt_expr(ret_expr);
-                        let block = self.signal_block_stmt(ret_stmt, e.span,
-                                                           hir::PushUnstableBlock, ThinVec::new());
+                        let block = P(self.signal_block_stmt(ret_stmt, e.span,
+                                                             hir::PushUnstableBlock,
+                                                             ThinVec::new()));
 
                         let err_pat = self.pat_err(e.span, err_local);
                         self.arm(hir_vec![err_pat], block)
@@ -1600,7 +1609,7 @@ fn make_struct(this: &mut LoweringContext,
             },
             span: e.span,
             attrs: e.attrs.clone(),
-        })
+        }
     }
 
     fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
@@ -1621,13 +1630,13 @@ 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,
                 }
             }
@@ -1721,15 +1730,15 @@ fn field(&mut self, name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
     }
 
     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());
 
@@ -1742,13 +1751,13 @@ fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P<hir::Expr>
         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
     }
@@ -1758,16 +1767,16 @@ fn expr_match(&mut self,
                   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,
@@ -1777,18 +1786,18 @@ 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>)
@@ -1820,19 +1829,19 @@ fn stmt_expr(&self, expr: P<hir::Expr>) -> hir::Stmt {
         }
     }
 
-    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> {
@@ -1953,9 +1962,9 @@ fn path_all(&mut self,
     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;
     }
 
@@ -1972,7 +1981,7 @@ fn signal_block_expr(&mut self,
                          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,
@@ -1989,7 +1998,7 @@ fn signal_block_stmt(&mut self,
                          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,
index 51a378a08336e93c22a4a2d5e2a10bc4589818f8..89217e83ca22eeaf3be3dd317a4c64553cb3f40d 100644 (file)
@@ -9,9 +9,7 @@
 // except according to those terms.
 
 use super::*;
-use super::MapEntry::*;
 
-use hir::*;
 use hir::intravisit::Visitor;
 use hir::def_id::DefId;
 use middle::cstore::InlinedItem;
index 421843a7f11d8752af6ac3bfa71126a14d68d097..7486d954c480233fde7058411c821c964a26a25f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::*;
+use hir::map::definitions::*;
 
 use hir;
 use hir::intravisit;
@@ -19,7 +19,7 @@
 use syntax::ast::*;
 use syntax::ext::hygiene::Mark;
 use syntax::visit;
-use syntax::parse::token::{self, keywords};
+use syntax::symbol::{Symbol, keywords};
 
 /// Creates def ids for nodes in the HIR.
 pub struct DefCollector<'a> {
@@ -169,7 +169,7 @@ fn visit_item(&mut self, i: &Item) {
                         this.with_parent(variant_def_index, |this| {
                             for (index, field) in v.node.data.fields().iter().enumerate() {
                                 let name = field.ident.map(|ident| ident.name)
-                                    .unwrap_or_else(|| token::intern(&index.to_string()));
+                                    .unwrap_or_else(|| Symbol::intern(&index.to_string()));
                                 this.create_def(field.id, DefPathData::Field(name.as_str()));
                             }
 
@@ -188,7 +188,7 @@ fn visit_item(&mut self, i: &Item) {
 
                     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));
                     }
                 }
index 38157c7e565646c45b21a5dc985ad32606c56998..83d3627d8e61643e4b3b4f88ea56d40ef1fe0f8f 100644 (file)
@@ -14,7 +14,7 @@
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
 use syntax::ast;
-use syntax::parse::token::{self, InternedString};
+use syntax::symbol::{Symbol, InternedString};
 use ty::TyCtxt;
 use util::nodemap::NodeMap;
 
@@ -115,9 +115,9 @@ pub fn make<FN>(start_krate: CrateNum,
     pub fn to_string(&self, tcx: TyCtxt) -> String {
         let mut s = String::with_capacity(self.data.len() * 16);
 
-        s.push_str(&tcx.original_crate_name(self.krate));
+        s.push_str(&tcx.original_crate_name(self.krate).as_str());
         s.push_str("/");
-        s.push_str(&tcx.crate_disambiguator(self.krate));
+        s.push_str(&tcx.crate_disambiguator(self.krate).as_str());
 
         for component in &self.data {
             write!(s,
@@ -137,8 +137,8 @@ pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
     }
 
     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);
     }
 }
@@ -328,7 +328,7 @@ pub fn get_opt_name(&self) -> Option<ast::Name> {
             LifetimeDef(ref name) |
             EnumVariant(ref name) |
             Binding(ref name) |
-            Field(ref name) => Some(token::intern(name)),
+            Field(ref name) => Some(Symbol::intern(name)),
 
             Impl |
             CrateRoot |
@@ -343,7 +343,7 @@ pub fn get_opt_name(&self) -> Option<ast::Name> {
 
     pub fn as_interned_str(&self) -> InternedString {
         use self::DefPathData::*;
-        match *self {
+        let s = match *self {
             TypeNs(ref name) |
             ValueNs(ref name) |
             Module(ref name) |
@@ -353,43 +353,24 @@ pub fn as_interned_str(&self) -> InternedString {
             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 {
index 06cfc8aee8c9d382b69c04d3f2b7f197e540bce9..a90577b34261c4e7c8338052aac83f4823511dda 100644 (file)
@@ -765,7 +765,7 @@ fn suffix_matches(&self, parent: NodeId) -> bool {
                 None => return false,
                 Some((node_id, name)) => (node_id, name),
             };
-            if &part[..] != mod_name.as_str() {
+            if mod_name != &**part {
                 return false;
             }
             cursor = self.map.get_parent(mod_id);
@@ -803,8 +803,7 @@ fn item_is_mod(item: &Item) -> bool {
     // 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)
     }
 }
 
index 9f5ff6914b0cc0b2b29b5064db5943bd4ca5588a..31648765224254796ca75be5e292b5035ac9470b 100644 (file)
@@ -40,8 +40,8 @@
 use syntax::abi::Abi;
 use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
-use syntax::parse::token::{keywords, InternedString};
 use syntax::ptr::P;
+use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenTree;
 use syntax::util::ThinVec;
 
@@ -867,12 +867,12 @@ pub enum Expr_ {
     /// A `box x` expression.
     ExprBox(P<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.
@@ -885,9 +885,9 @@ pub enum Expr_ {
     ///
     /// 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`)
@@ -908,7 +908,7 @@ pub enum Expr_ {
     /// 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),
@@ -944,14 +944,14 @@ pub enum Expr_ {
     /// 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.
     ///
@@ -1002,6 +1002,18 @@ pub enum MatchSource {
     TryDesugar,
 }
 
+/// The loop type that yielded an ExprLoop
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub enum LoopSource {
+    /// A `loop { .. }` loop
+    Loop,
+    /// A `while let _ = _ { .. }` loop
+    WhileLet,
+    /// A `for _ in _ { .. }` loop
+    ForLoop,
+}
+
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum CaptureClause {
     CaptureByValue,
@@ -1163,18 +1175,18 @@ pub enum Ty_ {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsmOutput {
-    pub constraint: InternedString,
+    pub constraint: Symbol,
     pub is_rw: bool,
     pub is_indirect: bool,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsm {
-    pub asm: InternedString,
+    pub asm: Symbol,
     pub asm_str_style: StrStyle,
     pub outputs: HirVec<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,
index 807bbec3b58888e36f0037d8df436ded6db16063..c109e84bf6186a65ee7b224d962e5d3b982b6a31 100644 (file)
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::codemap::{CodeMap, Spanned};
-use syntax::parse::token::{self, keywords, BinOpToken};
+use syntax::parse::token::{self, BinOpToken};
 use syntax::parse::lexer::comments;
 use syntax::print::pp::{self, break_offset, word, space, hardbreak};
 use syntax::print::pp::{Breaks, eof};
 use syntax::print::pp::Breaks::{Consistent, Inconsistent};
 use syntax::print::pprust::{self as ast_pp, PrintState};
 use syntax::ptr::P;
+use syntax::symbol::keywords;
 use syntax_pos::{self, BytePos};
 use errors;
 
@@ -451,7 +452,7 @@ pub fn commasep_cmnt<T, F, G>(&mut self,
         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)
     }
 
@@ -1199,7 +1200,7 @@ pub fn print_if_let(&mut self,
     }
 
 
-    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()
@@ -1217,10 +1218,10 @@ pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr) -> io::Result<()> {
         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()
     }
@@ -1273,16 +1274,16 @@ fn print_expr_struct(&mut self,
         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)
     }
@@ -1290,7 +1291,7 @@ fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Re
     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])?;
@@ -1339,7 +1340,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 self.print_expr(expr)?;
             }
             hir::ExprArray(ref exprs) => {
-                self.print_expr_vec(&exprs[..])?;
+                self.print_expr_vec(exprs)?;
             }
             hir::ExprRepeat(ref element, ref count) => {
                 self.print_expr_repeat(&element, &count)?;
@@ -1348,13 +1349,13 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 self.print_expr_struct(path, &fields[..], wth)?;
             }
             hir::ExprTup(ref exprs) => {
-                self.print_expr_tup(&exprs[..])?;
+                self.print_expr_tup(exprs)?;
             }
             hir::ExprCall(ref func, ref args) => {
-                self.print_expr_call(&func, &args[..])?;
+                self.print_expr_call(&func, args)?;
             }
             hir::ExprMethodCall(name, ref tys, ref args) => {
-                self.print_expr_method_call(name, &tys[..], &args[..])?;
+                self.print_expr_method_call(name, &tys[..], args)?;
             }
             hir::ExprBinary(op, ref lhs, ref rhs) => {
                 self.print_expr_binary(op, &lhs, &rhs)?;
@@ -1392,7 +1393,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 space(&mut self.s)?;
                 self.print_block(&blk)?;
             }
-            hir::ExprLoop(ref blk, opt_sp_name) => {
+            hir::ExprLoop(ref blk, opt_sp_name, _) => {
                 if let Some(sp_name) = opt_sp_name {
                     self.print_name(sp_name.node)?;
                     self.word_space(":")?;
@@ -1470,13 +1471,17 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             hir::ExprPath(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, true)?
             }
-            hir::ExprBreak(opt_name) => {
+            hir::ExprBreak(opt_name, ref opt_expr) => {
                 word(&mut self.s, "break")?;
                 space(&mut self.s)?;
                 if let Some(name) = opt_name {
                     self.print_name(name.node)?;
                     space(&mut self.s)?;
                 }
+                if let Some(ref expr) = *opt_expr {
+                    self.print_expr(expr)?;
+                    space(&mut self.s)?;
+                }
             }
             hir::ExprAgain(opt_name) => {
                 word(&mut self.s, "continue")?;
@@ -1499,19 +1504,19 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
             hir::ExprInlineAsm(ref a, ref outputs, ref inputs) => {
                 word(&mut self.s, "asm!")?;
                 self.popen()?;
-                self.print_string(&a.asm, a.asm_str_style)?;
+                self.print_string(&a.asm.as_str(), a.asm_str_style)?;
                 self.word_space(":")?;
 
                 let mut out_idx = 0;
                 self.commasep(Inconsistent, &a.outputs, |s, out| {
-                    let mut ch = out.constraint.chars();
+                    let constraint = out.constraint.as_str();
+                    let mut ch = constraint.chars();
                     match ch.next() {
                         Some('=') if out.is_rw => {
                             s.print_string(&format!("+{}", ch.as_str()),
                                            ast::StrStyle::Cooked)?
                         }
-                        _ => s.print_string(&out.constraint,
-                                            ast::StrStyle::Cooked)?,
+                        _ => s.print_string(&constraint, ast::StrStyle::Cooked)?,
                     }
                     s.popen()?;
                     s.print_expr(&outputs[out_idx])?;
@@ -1524,7 +1529,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
 
                 let mut in_idx = 0;
                 self.commasep(Inconsistent, &a.inputs, |s, co| {
-                    s.print_string(&co, ast::StrStyle::Cooked)?;
+                    s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
                     s.popen()?;
                     s.print_expr(&inputs[in_idx])?;
                     s.pclose()?;
@@ -1535,7 +1540,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
                 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(())
                 })?;
 
index 58caac4034e34a1144e70ec4e06c08e645c5cb75..8db09d0b73d32485d1e2ba0f48f56e26f4a48a4c 100644 (file)
@@ -91,8 +91,8 @@
 use std::char::from_u32;
 use std::fmt;
 use syntax::ast;
-use syntax::parse::token;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::{self, Pos, Span};
 use errors::DiagnosticBuilder;
 
@@ -1219,7 +1219,7 @@ fn pick_lifetime(&self,
                 names.push(lt_name);
             }
             names.sort();
-            let name = token::intern(&names[0]);
+            let name = Symbol::intern(&names[0]);
             return (name_to_dummy_lifetime(name), Kept);
         }
         return (self.life_giver.give_lifetime(), Fresh);
@@ -1931,7 +1931,7 @@ fn give_lifetime(&self) -> hir::Lifetime {
             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;
             }
index 8c0d70c6d602b731b054452e74799357bb3a8887..0942ce79a6b49787e209d8f1ac348c13d22f9649 100644 (file)
@@ -33,6 +33,7 @@
 #![feature(core_intrinsics)]
 #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))]
 #![feature(enumset)]
+#![cfg_attr(stage0, feature(item_like_imports))]
 #![feature(libc)]
 #![feature(nonzero)]
 #![feature(quote)]
index 82a46f76401d52a2a559bc6edd0fce550069009a..96aee04b6b7ab826f172d3d390378e52992b9d82 100644 (file)
 
 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)]
@@ -242,7 +249,8 @@ fn get_lints(&self) -> LintArray {
             LIFETIME_UNDERSCORE,
             SAFE_EXTERN_STATICS,
             PATTERNS_IN_FNS_WITHOUT_BODY,
-            EXTRA_REQUIREMENT_IN_IMPL
+            EXTRA_REQUIREMENT_IN_IMPL,
+            LEGACY_DIRECTORY_OWNERSHIP
         )
     }
 }
index a490b58964a71f04c67a589e018ff61faf7bd0d4..4a082944010b2838fb73d12cc26d84f9d7bea0eb 100644 (file)
@@ -40,7 +40,6 @@
 use std::mem;
 use std::fmt;
 use syntax::attr;
-use syntax::parse::token::InternedString;
 use syntax::ast;
 use syntax_pos::{MultiSpan, Span};
 use errors::{self, Diagnostic, DiagnosticBuilder};
@@ -384,8 +383,7 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({
 /// Parse the lint attributes into a vector, with `Err`s for malformed lint
 /// attributes. Writing this as an iterator is an enormous mess.
 // See also the hir version just below.
-pub fn gather_attrs(attrs: &[ast::Attribute])
-                    -> Vec<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);
@@ -394,18 +392,17 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
     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 {
@@ -414,9 +411,7 @@ pub fn gather_attr(attr: &ast::Attribute)
     };
 
     for li in metas {
-        out.push(li.word().map_or(Err(li.span), |word| {
-            Ok((word.name().clone(), level, word.span))
-        }));
+        out.push(li.word().map_or(Err(li.span), |word| Ok((word.name(), level, word.span))));
     }
 
     out
@@ -629,10 +624,10 @@ fn with_lint_attrs<F>(&mut self,
                     continue;
                 }
                 Ok((lint_name, level, span)) => {
-                    match self.lints().find_lint(&lint_name, &self.sess(), Some(span)) {
+                    match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) {
                         Ok(lint_id) => vec![(lint_id, level, span)],
                         Err(FindLintError::NotFound) => {
-                            match self.lints().lint_groups.get(&lint_name[..]) {
+                            match self.lints().lint_groups.get(&*lint_name.as_str()) {
                                 Some(&(ref v, _)) => v.iter()
                                                       .map(|lint_id: &LintId|
                                                            (*lint_id, level, span))
@@ -1193,8 +1188,7 @@ fn check_lint_name_attribute(cx: &LateContext, attr: &ast::Attribute) {
                 continue;
             }
             Ok((lint_name, _, span)) => {
-                match check_lint_name(&cx.lints,
-                                      &lint_name[..]) {
+                match check_lint_name(&cx.lints, &lint_name.as_str()) {
                     CheckLintNameResult::Ok => (),
                     CheckLintNameResult::Warning(ref msg) => {
                         cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS,
index 3482971cd1999c0507abc2b959d498534a950766..9677082a43a3c2d03dcef9faa383e804abc54c8b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::parse::token::InternedString;
+use syntax::symbol::InternedString;
 use syntax::ast;
 use std::rc::Rc;
 use hir::def_id::DefId;
index f61978271e7f6c34e1bb095e9e8dca16c0c23ffb..a7f28dd6d58c4009711d14d1cefdafc1b47761ef 100644 (file)
@@ -39,7 +39,7 @@
 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)]
@@ -76,6 +77,30 @@ pub enum DepKind {
     Explicit,
 }
 
+#[derive(PartialEq, Clone, Debug)]
+pub enum LibSource {
+    Some(PathBuf),
+    MetadataOnly,
+    None,
+}
+
+impl LibSource {
+    pub fn is_some(&self) -> bool {
+        if let LibSource::Some(_) = *self {
+            true
+        } else {
+            false
+        }
+    }
+
+    pub fn option(&self) -> Option<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,
@@ -92,8 +117,8 @@ pub enum NativeLibraryKind {
 #[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
@@ -205,11 +230,11 @@ fn dylib_dependency_formats(&self, cnum: CrateNum)
     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>;
@@ -244,7 +269,7 @@ fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: 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>,
@@ -375,13 +400,13 @@ fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
         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>
@@ -427,7 +452,7 @@ fn used_link_args(&self) -> Vec<String> { vec![] }
     // 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 }
index 991398813752f8a5991536259f804b0d1a8f0749..f47eab013c2b216a4789e40e54d1031c10132340 100644 (file)
@@ -309,8 +309,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
     let dead_code = lint::builtin::DEAD_CODE.name_lower();
     for attr in lint::gather_attrs(attrs) {
         match attr {
-            Ok((ref name, lint::Allow, _))
-                if &name[..] == dead_code => return true,
+            Ok((name, lint::Allow, _)) if name == &*dead_code => return true,
             _ => (),
         }
     }
@@ -499,8 +498,7 @@ fn warn_dead_code(&mut self,
                       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,
index 92d1ab85c5a05afcf806eb14e7330c9d595b22a1..ee7f13f9e6e2266ddfafe6e0aa8b4dc629e6b560 100644 (file)
@@ -114,7 +114,7 @@ fn calculate_type(sess: &session::Session,
 
         // No linkage happens with rlibs, we just needed the metadata (which we
         // got long ago), so don't bother with anything.
-        config::CrateTypeRlib => return Vec::new(),
+        config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(),
 
         // Staticlibs and cdylibs must have all static dependencies. If any fail
         // to be found, we generate some nice pretty errors.
@@ -192,7 +192,7 @@ fn calculate_type(sess: &session::Session,
         if src.dylib.is_none() &&
            !formats.contains_key(&cnum) &&
            sess.cstore.dep_kind(cnum) == DepKind::Explicit {
-            assert!(src.rlib.is_some());
+            assert!(src.rlib.is_some() || src.rmeta.is_some());
             info!("adding staticlib: {}", sess.cstore.crate_name(cnum));
             add_library(sess, cnum, RequireStatic, &mut formats);
             ret[cnum.as_usize() - 1] = Linkage::Static;
index 9dd54457a3499b442952af6a82939692b10b9584..65aedae347a8d0cd4538f6d824f1c7d495448e35 100644 (file)
@@ -92,7 +92,7 @@ fn entry_point_type(item: &Item, at_root: bool) -> EntryPointType {
                 EntryPointType::Start
             } else if attr::contains_name(&item.attrs, "main") {
                 EntryPointType::MainAttr
-            } else if item.name.as_str() == "main" {
+            } else if item.name == "main" {
                 if at_root {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
index 231da576f2b99d8f821a1d2aeed6480fac018a05..594ed408d8cd48efed2a73c9c87873d96f384e4c 100644 (file)
@@ -327,7 +327,7 @@ fn delegate_consume(&mut self,
         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);
         }
@@ -472,11 +472,10 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 self.consume_exprs(inputs);
             }
 
-            hir::ExprBreak(..) |
             hir::ExprAgain(..) |
             hir::ExprLit(..) => {}
 
-            hir::ExprLoop(ref blk, _) => {
+            hir::ExprLoop(ref blk, _, _) => {
                 self.walk_block(&blk);
             }
 
@@ -514,7 +513,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 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);
                 }
index cf08b59312d50a55d38f8e8fc401a70334799b73..80cf64865abea7043ded3f20e2c5575c52a85d49 100644 (file)
@@ -55,7 +55,7 @@ fn def_id_is_transmute(&self, def_id: DefId) -> bool {
             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) {
index 9b4b1396669a3a6ab5242977b2bed3d74bddc788..5af9a2f02742effbe3d4a5663a4fd177b654a7ed 100644 (file)
@@ -30,7 +30,7 @@
 use util::nodemap::FxHashMap;
 
 use syntax::ast;
-use syntax::parse::token::InternedString;
+use syntax::symbol::Symbol;
 use hir::itemlikevisit::ItemLikeVisitor;
 use hir;
 
@@ -152,7 +152,7 @@ struct LanguageItemCollector<'a, 'tcx: 'a> {
 impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
         if let Some(value) = extract(&item.attrs) {
-            let item_index = self.item_refs.get(&value[..]).cloned();
+            let item_index = self.item_refs.get(&*value.as_str()).cloned();
 
             if let Some(item_index) = item_index {
                 self.collect_item(item_index, self.ast_map.local_def_id(item.id))
@@ -160,7 +160,7 @@ fn visit_item(&mut self, item: &hir::Item) {
                 let span = self.ast_map.span(item.id);
                 span_err!(self.session, span, E0522,
                           "definition of an unknown language item: `{}`.",
-                          &value[..]);
+                          value);
             }
         }
     }
@@ -243,12 +243,10 @@ pub fn collect(&mut self, krate: &hir::Crate) {
     }
 }
 
-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),
             _ => {}
         }
     }
index d381188d56b542de5cb8e146264623835b8cec28..4b1787ba593cbcae173ec7b63239e4293e3c2983 100644 (file)
 use std::io;
 use std::rc::Rc;
 use syntax::ast::{self, NodeId};
-use syntax::parse::token::keywords;
-use syntax::ptr::P;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 
 use hir::Expr;
@@ -491,7 +490,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       hir::ExprIndex(..) | hir::ExprField(..) | hir::ExprTupField(..) |
       hir::ExprArray(..) | hir::ExprCall(..) | hir::ExprMethodCall(..) |
       hir::ExprTup(..) | hir::ExprBinary(..) | hir::ExprAddrOf(..) |
-      hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(_) |
+      hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprBreak(..) |
       hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) |
       hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
       hir::ExprStruct(..) | hir::ExprRepeat(..) |
@@ -902,7 +901,7 @@ fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
         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)
@@ -991,7 +990,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
           // Note that labels have been resolved, so we don't need to look
           // at the label ident
-          hir::ExprLoop(ref blk, _) => {
+          hir::ExprLoop(ref blk, _, _) => {
             self.propagate_through_loop(expr, LoopLoop, &blk, succ)
           }
 
@@ -1036,7 +1035,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
           }
 
-          hir::ExprBreak(opt_label) => {
+          hir::ExprBreak(opt_label, ref opt_expr) => {
               // Find which label this break jumps to
               let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
 
@@ -1044,7 +1043,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
               // look it up in the break loop nodes table
 
               match self.break_ln.get(&sc) {
-                  Some(&b) => b,
+                  Some(&b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
                   None => span_bug!(expr.span, "break to unknown label")
               }
           }
@@ -1058,7 +1057,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
 
               match self.cont_ln.get(&sc) {
                   Some(&b) => b,
-                  None => span_bug!(expr.span, "loop to unknown label")
+                  None => span_bug!(expr.span, "continue to unknown label")
               }
           }
 
@@ -1087,7 +1086,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
           // Uninteresting cases: just propagate in rev exec order
 
           hir::ExprArray(ref exprs) => {
-            self.propagate_through_exprs(&exprs[..], succ)
+            self.propagate_through_exprs(exprs, succ)
           }
 
           hir::ExprRepeat(ref element, ref count) => {
@@ -1111,7 +1110,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             } else {
                 succ
             };
-            let succ = self.propagate_through_exprs(&args[..], succ);
+            let succ = self.propagate_through_exprs(args, succ);
             self.propagate_through_expr(&f, succ)
           }
 
@@ -1124,11 +1123,11 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
             } 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() => {
index ac614494355a26c37277ebc4f7e1a8aca87d1c4d..35e0e494771ba131a46b6a488beb2b7a5147e823 100644 (file)
@@ -140,7 +140,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> {
         let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
             *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
-            *ty == config::CrateTypeProcMacro
+            *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata
         });
         ReachableContext {
             tcx: tcx,
index 0764e817f4307be588e51c8da31f67864b288cf4..7f89461a3f4b6823718ec24788f9f06381747f6d 100644 (file)
@@ -25,7 +25,7 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
         }
 
         if let Some(s) = attr.value_str() {
-            if let Some(n) = s.parse().ok() {
+            if let Some(n) = s.as_str().parse().ok() {
                 sess.recursion_limit.set(n);
                 return;
             }
index 5f9a6b283c6a06c42c921b9d8afd951851dc752a..0dbde2d21caf5607bd145920a88874abe85407f3 100644 (file)
@@ -805,7 +805,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &hir::Expr) {
                 terminating(then.id);
             }
 
-            hir::ExprLoop(ref body, _) => {
+            hir::ExprLoop(ref body, _, _) => {
                 terminating(body.id);
             }
 
index f682dfbf1be9526550bed9b052bb611d154549be..41da5562e23fa4f488bda5112ba63367fa810284 100644 (file)
@@ -27,7 +27,7 @@
 use ty;
 use std::mem::replace;
 use syntax::ast;
-use syntax::parse::token::keywords;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 use util::nodemap::NodeMap;
 
@@ -462,7 +462,7 @@ fn visit_item(&mut self, _: &hir::Item) {
     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,
         }
     }
index 7e4efc7ddca06382c7c25e482399dbd661f542fb..86a89eff3a476a9cd5c54a8432250738ba642a2d 100644 (file)
@@ -21,7 +21,7 @@
 use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
 use ty::{self, TyCtxt, AdtKind};
 use middle::privacy::AccessLevels;
-use syntax::parse::token::InternedString;
+use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::ast;
 use syntax::ast::{NodeId, Attribute};
@@ -36,7 +36,6 @@
 
 use std::mem::replace;
 use std::cmp::Ordering;
-use std::ops::Deref;
 
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)]
 pub enum StabilityLevel {
@@ -151,10 +150,11 @@ fn annotate<F>(&mut self, id: NodeId, attrs: &[Attribute],
 
                 // 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 => {
@@ -356,7 +356,7 @@ pub fn new(hir_map: &hir_map::Map) -> Index<'tcx> {
 /// features and possibly prints errors. Returns a list of all
 /// features used.
 pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                          -> FxHashMap<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;
 
@@ -376,8 +376,8 @@ pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
 
 struct Checker<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    active_features: FxHashSet<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,
 }
@@ -407,10 +407,10 @@ fn check(&mut self, id: DefId, span: Span,
                 if !self.active_features.contains(feature) {
                     let msg = match *reason {
                         Some(ref r) => format!("use of unstable library feature '{}': {}",
-                                               &feature, &r),
+                                               &feature.as_str(), &r),
                         None => format!("use of unstable library feature '{}'", &feature)
                     };
-                    emit_feature_err(&self.tcx.sess.parse_sess, &feature, span,
+                    emit_feature_err(&self.tcx.sess.parse_sess, &feature.as_str(), span,
                                      GateIssue::Library(Some(issue)), &msg);
                 }
             }
@@ -455,7 +455,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         // When compiling with --test we don't enforce stability on the
         // compiler-generated test module, demarcated with `DUMMY_SP` plus the
         // name `__test`
-        if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
+        if item.span == DUMMY_SP && item.name == "__test" { return }
 
         check_item(self.tcx, item, true,
                    &mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
@@ -735,10 +735,10 @@ fn lookup_deprecation_uncached(self, id: DefId) -> Option<DeprecationEntry> {
 /// 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 {
@@ -746,7 +746,7 @@ 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,
@@ -761,7 +761,7 @@ fn format_stable_since_msg(version: &str) -> String {
                     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 */ )
index 12d32bf31b13dee60224341e288a6652bd5c35f8..30690c099194f644308b86cff6153a9a8f7a311e 100644 (file)
@@ -16,7 +16,7 @@
 
 use rustc_back::PanicStrategy;
 use syntax::ast;
-use syntax::parse::token::InternedString;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use hir::intravisit::Visitor;
 use hir::intravisit;
@@ -55,10 +55,10 @@ pub fn check_crate(krate: &hir::Crate,
     verify(sess, items);
 }
 
-pub fn link_name(attrs: &[ast::Attribute]) -> Option<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
         }
@@ -75,7 +75,8 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
             config::CrateTypeCdylib |
             config::CrateTypeExecutable |
             config::CrateTypeStaticlib => true,
-            config::CrateTypeRlib => false,
+            config::CrateTypeRlib |
+            config::CrateTypeMetadata => false,
         }
     });
     if !needs_check {
@@ -126,7 +127,7 @@ fn register(&mut self, name: &str, span: Span) {
 impl<'a, 'v> Visitor<'v> for Context<'a> {
     fn visit_foreign_item(&mut self, i: &hir::ForeignItem) {
         if let Some(lang_item) = lang_items::extract(&i.attrs) {
-            self.register(&lang_item, i.span);
+            self.register(&lang_item.as_str(), i.span);
         }
         intravisit::walk_foreign_item(self, i)
     }
diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs
new file mode 100644 (file)
index 0000000..8308c54
--- /dev/null
@@ -0,0 +1,173 @@
+// 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);
+            }
+        }
+    }
+}
index 16522a73f56a514fa2b551f47545edc00014753f..26dafed7019ed7b9e25c8f6732fb222636aa4ab6 100644 (file)
@@ -25,9 +25,8 @@
 use middle::cstore;
 
 use syntax::ast::{self, IntTy, UintTy};
-use syntax::attr;
 use syntax::parse;
-use syntax::parse::token::InternedString;
+use syntax::symbol::Symbol;
 use syntax::feature_gate::UnstableFeatures;
 
 use errors::{ColorConfig, FatalError, Handler};
@@ -41,6 +40,7 @@
 use std::fmt;
 use std::hash::Hasher;
 use std::collections::hash_map::DefaultHasher;
+use std::collections::HashSet;
 use std::iter::FromIterator;
 use std::path::PathBuf;
 
@@ -78,18 +78,6 @@ pub enum OutputType {
     DepInfo,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum ErrorOutputType {
-    HumanReadable(ColorConfig),
-    Json,
-}
-
-impl Default for ErrorOutputType {
-    fn default() -> ErrorOutputType {
-        ErrorOutputType::HumanReadable(ColorConfig::Auto)
-    }
-}
-
 impl OutputType {
     fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
         match *self {
@@ -125,6 +113,18 @@ pub fn extension(&self) -> &'static str {
     }
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum ErrorOutputType {
+    HumanReadable(ColorConfig),
+    Json,
+}
+
+impl Default for ErrorOutputType {
+    fn default() -> ErrorOutputType {
+        ErrorOutputType::HumanReadable(ColorConfig::Auto)
+    }
+}
+
 // Use tree-based collections to cheaply get a deterministic Hash implementation.
 // DO NOT switch BTreeMap out for an unsorted container type! That would break
 // dependency tracking for commandline arguments.
@@ -483,6 +483,7 @@ pub enum CrateType {
     CrateTypeStaticlib,
     CrateTypeCdylib,
     CrateTypeProcMacro,
+    CrateTypeMetadata,
 }
 
 #[derive(Clone, Hash)]
@@ -908,6 +909,8 @@ fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bo
           "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],
@@ -927,8 +930,6 @@ pub fn default_lib_output() -> CrateType {
 }
 
 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
-    use syntax::parse::token::intern_and_get_ident as intern;
-
     let end = &sess.target.target.target_endian;
     let arch = &sess.target.target.arch;
     let wordsz = &sess.target.target.target_pointer_width;
@@ -938,55 +939,46 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let max_atomic_width = sess.target.target.max_atomic_width();
 
     let fam = if let Some(ref fam) = sess.target.target.options.target_family {
-        intern(fam)
+        Symbol::intern(fam)
     } else if sess.target.target.options.is_like_windows {
-        InternedString::new("windows")
+        Symbol::intern("windows")
     } else {
-        InternedString::new("unix")
+        Symbol::intern("unix")
     };
 
-    let mk = attr::mk_name_value_item_str;
-    let mut ret = vec![ // Target bindings.
-        mk(InternedString::new("target_os"), intern(os)),
-        mk(InternedString::new("target_family"), fam.clone()),
-        mk(InternedString::new("target_arch"), intern(arch)),
-        mk(InternedString::new("target_endian"), intern(end)),
-        mk(InternedString::new("target_pointer_width"), intern(wordsz)),
-        mk(InternedString::new("target_env"), intern(env)),
-        mk(InternedString::new("target_vendor"), intern(vendor)),
-    ];
-    match &fam[..] {
-        "windows" | "unix" => ret.push(attr::mk_word_item(fam)),
-        _ => (),
+    let mut ret = HashSet::new();
+    // Target bindings.
+    ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
+    ret.insert((Symbol::intern("target_family"), Some(fam)));
+    ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch))));
+    ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end))));
+    ret.insert((Symbol::intern("target_pointer_width"), Some(Symbol::intern(wordsz))));
+    ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env))));
+    ret.insert((Symbol::intern("target_vendor"), Some(Symbol::intern(vendor))));
+    if fam == "windows" || fam == "unix" {
+        ret.insert((fam, None));
     }
     if sess.target.target.options.has_elf_tls {
-        ret.push(attr::mk_word_item(InternedString::new("target_thread_local")));
+        ret.insert((Symbol::intern("target_thread_local"), None));
     }
     for &i in &[8, 16, 32, 64, 128] {
         if i <= max_atomic_width {
             let s = i.to_string();
-            ret.push(mk(InternedString::new("target_has_atomic"), intern(&s)));
+            ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s))));
             if &s == wordsz {
-                ret.push(mk(InternedString::new("target_has_atomic"), intern("ptr")));
+                ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern("ptr"))));
             }
         }
     }
     if sess.opts.debug_assertions {
-        ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
+        ret.insert((Symbol::intern("debug_assertions"), None));
     }
     if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
-        ret.push(attr::mk_word_item(InternedString::new("proc_macro")));
+        ret.insert((Symbol::intern("proc_macro"), None));
     }
     return ret;
 }
 
-pub fn append_configuration(cfg: &mut ast::CrateConfig,
-                            name: InternedString) {
-    if !cfg.iter().any(|mi| mi.name() == name) {
-        cfg.push(attr::mk_word_item(name))
-    }
-}
-
 pub fn build_configuration(sess: &Session,
                            mut user_cfg: ast::CrateConfig)
                            -> ast::CrateConfig {
@@ -995,11 +987,10 @@ pub fn build_configuration(sess: &Session,
     let default_cfg = default_configuration(sess);
     // If the user wants a test runner, then add the test cfg
     if sess.opts.test {
-        append_configuration(&mut user_cfg, InternedString::new("test"))
+        user_cfg.insert((Symbol::intern("test"), None));
     }
-    let mut v = user_cfg.into_iter().collect::<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 {
@@ -1159,7 +1150,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                              assumed.", "[KIND=]NAME"),
         opt::multi_s("", "crate-type", "Comma separated list of types of crates
                                     for the compiler to emit",
-                   "[bin|lib|rlib|dylib|cdylib|staticlib]"),
+                   "[bin|lib|rlib|dylib|cdylib|staticlib|metadata]"),
         opt::opt_s("", "crate-name", "Specify the name of the crate being built",
                "NAME"),
         opt::multi_s("", "emit", "Comma separated list of types of output for \
@@ -1245,11 +1236,14 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
         let meta_item = panictry!(parser.parse_meta_item());
 
         if !parser.reader.is_eof() {
-            early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}",
-                                                             s))
+            early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", s))
+        } else if meta_item.is_meta_item_list() {
+            let msg =
+                format!("invalid predicate in --cfg command line argument: `{}`", meta_item.name());
+            early_error(ErrorOutputType::default(), &msg)
         }
 
-        meta_item
+        (meta_item.name(), meta_item.value_str())
     }).collect::<ast::CrateConfig>()
 }
 
@@ -1548,6 +1542,7 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
                 "cdylib"    => CrateTypeCdylib,
                 "bin"       => CrateTypeExecutable,
                 "proc-macro" => CrateTypeProcMacro,
+                "metadata"  => CrateTypeMetadata,
                 _ => {
                     return Err(format!("unknown crate type: `{}`",
                                        part));
@@ -1632,6 +1627,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             CrateTypeStaticlib => "staticlib".fmt(f),
             CrateTypeCdylib => "cdylib".fmt(f),
             CrateTypeProcMacro => "proc-macro".fmt(f),
+            CrateTypeMetadata => "metadata".fmt(f),
         }
     }
 }
@@ -1773,9 +1769,7 @@ mod tests {
     use std::rc::Rc;
     use super::{OutputType, OutputTypes, Externs};
     use rustc_back::PanicStrategy;
-    use syntax::{ast, attr};
-    use syntax::parse::token::InternedString;
-    use syntax::codemap::dummy_spanned;
+    use syntax::symbol::Symbol;
 
     fn optgroups() -> Vec<OptGroup> {
         super::rustc_optgroups().into_iter()
@@ -1804,9 +1798,7 @@ fn test_switch_implies_cfg_test() {
         let (sessopts, cfg) = build_session_options_and_crate_config(matches);
         let sess = build_session(sessopts, &dep_graph, None, registry, Rc::new(DummyCrateStore));
         let cfg = build_configuration(&sess, cfg);
-        assert!(attr::contains(&cfg, &dummy_spanned(ast::MetaItemKind::Word({
-            InternedString::new("test")
-        }))));
+        assert!(cfg.contains(&(Symbol::intern("test"), None)));
     }
 
     // When the user supplies --test and --cfg test, don't implicitly add
@@ -1827,7 +1819,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
         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());
     }
index 9becbd99eb33a2a6fb56bf01c4822d7d735c57a6..3d8cfd199615e491c916909e0c81cc10e12b5b82 100644 (file)
@@ -8,6 +8,9 @@
 // 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;
@@ -28,7 +31,7 @@
 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};
@@ -49,6 +52,7 @@
 use std::time::Duration;
 use libc::c_int;
 
+mod code_stats;
 pub mod config;
 pub mod filesearch;
 pub mod search_paths;
@@ -89,7 +93,7 @@ pub struct Session {
     // forms a unique global identifier for the crate. It is used to allow
     // multiple crates with the same name to coexist. See the
     // trans::back::symbol_names module for more information.
-    pub crate_disambiguator: RefCell<token::InternedString>,
+    pub crate_disambiguator: RefCell<Symbol>,
     pub features: RefCell<feature_gate::Features>,
 
     /// The maximum recursion limit for potentially infinitely recursive
@@ -112,6 +116,9 @@ pub struct Session {
     /// 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>,
 }
 
@@ -129,8 +136,8 @@ pub struct PerfStats {
 }
 
 impl Session {
-    pub fn local_crate_disambiguator(&self) -> token::InternedString {
-        self.crate_disambiguator.borrow().clone()
+    pub fn local_crate_disambiguator(&self) -> Symbol {
+        *self.crate_disambiguator.borrow()
     }
     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
                                                     sp: S,
@@ -610,7 +617,7 @@ pub fn build_session_(sopts: config::Options,
         plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         dependency_formats: RefCell::new(FxHashMap()),
-        crate_disambiguator: RefCell::new(token::intern("").as_str()),
+        crate_disambiguator: RefCell::new(Symbol::intern("")),
         features: RefCell::new(feature_gate::Features::new()),
         recursion_limit: Cell::new(64),
         next_node_id: Cell::new(NodeId::new(1)),
@@ -624,7 +631,8 @@ pub fn build_session_(sopts: config::Options,
             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);
index e0a397ad28fbd28f6946efa405907bef712c11df..21009711cb18ae61a17cf486142d75a5d6b609f8 100644 (file)
@@ -246,12 +246,13 @@ fn on_unimplemented_note(&self,
                 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 {
index a2d45fa271499a02405732e49f83f364c8fb2b5b..76bead99343a7f01daa0b586ce348c2fcdcd7483 100644 (file)
@@ -26,8 +26,8 @@
 use hir::def_id::DefId;
 use infer::InferOk;
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
-use syntax::parse::token;
 use syntax::ast;
+use syntax::symbol::Symbol;
 use ty::subst::Subst;
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder};
@@ -1245,7 +1245,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
     let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
         projection_ty: ty::ProjectionTy {
             trait_ref: trait_ref,
-            item_name: token::intern(FN_OUTPUT_NAME),
+            item_name: Symbol::intern(FN_OUTPUT_NAME),
         },
         ty: ret_type
     });
index 45450456e8a6583e1b9e93861df9b1c627ce6103..20855c46b68002453844f0b2169ba979b4d242cf 100644 (file)
@@ -49,7 +49,7 @@
 use std::iter;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
-use syntax::parse::token::{self, keywords};
+use syntax::symbol::{Symbol, keywords};
 
 use hir;
 
@@ -561,7 +561,7 @@ pub struct GlobalCtxt<'tcx> {
 
     /// The definite name of the current crate after taking into account
     /// attributes, commandline parameters, etc.
-    pub crate_name: token::InternedString,
+    pub crate_name: Symbol,
 
     /// Data layout specification for the current target.
     pub data_layout: TargetDataLayout,
@@ -574,7 +574,7 @@ pub struct GlobalCtxt<'tcx> {
 
     /// Map from function to the `#[derive]` mode that it's defining. Only used
     /// by `proc-macro` crates.
-    pub derive_macros: RefCell<NodeMap<token::InternedString>>,
+    pub derive_macros: RefCell<NodeMap<Symbol>>,
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
@@ -588,15 +588,15 @@ pub fn global_tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn crate_name(self, cnum: CrateNum) -> token::InternedString {
+    pub fn crate_name(self, cnum: CrateNum) -> Symbol {
         if cnum == LOCAL_CRATE {
-            self.crate_name.clone()
+            self.crate_name
         } else {
             self.sess.cstore.crate_name(cnum)
         }
     }
 
-    pub fn original_crate_name(self, cnum: CrateNum) -> token::InternedString {
+    pub fn original_crate_name(self, cnum: CrateNum) -> Symbol {
         if cnum == LOCAL_CRATE {
             self.crate_name.clone()
         } else {
@@ -604,7 +604,7 @@ pub fn original_crate_name(self, cnum: CrateNum) -> token::InternedString {
         }
     }
 
-    pub fn crate_disambiguator(self, cnum: CrateNum) -> token::InternedString {
+    pub fn crate_disambiguator(self, cnum: CrateNum) -> Symbol {
         if cnum == LOCAL_CRATE {
             self.sess.local_crate_disambiguator()
         } else {
@@ -835,7 +835,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             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),
index 8222583d9a7da8162e232ac5e269d05033fe3ce5..b93a8698f603c1196a130ca4e1041b55ea1c7afd 100644 (file)
@@ -12,7 +12,7 @@
 use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use ty::{self, Ty, TyCtxt};
 use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 
 use std::cell::Cell;
 
@@ -94,14 +94,14 @@ pub fn push_krate_path<T>(self, buffer: &mut T, cnum: CrateNum)
                     if let Some(extern_crate_def_id) = opt_extern_crate {
                         self.push_item_path(buffer, extern_crate_def_id);
                     } else {
-                        buffer.push(&self.crate_name(cnum));
+                        buffer.push(&self.crate_name(cnum).as_str());
                     }
                 }
             }
             RootMode::Absolute => {
                 // In absolute mode, just write the crate name
                 // unconditionally.
-                buffer.push(&self.original_crate_name(cnum));
+                buffer.push(&self.original_crate_name(cnum).as_str());
             }
         }
     }
@@ -126,7 +126,7 @@ pub fn try_push_visible_item_path<T>(self, buffer: &mut T, external_def_id: DefI
                         return true;
                     }
                     None => {
-                        buffer.push(&self.crate_name(cur_def.krate));
+                        buffer.push(&self.crate_name(cur_def.krate).as_str());
                         cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
                         return true;
                     }
@@ -136,7 +136,7 @@ pub fn try_push_visible_item_path<T>(self, buffer: &mut T, external_def_id: DefI
 
             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,
index 5ee1c3678d675df1aba5a4567112dd7a986b40ee..bc3c5d6ed4e203d845ae3e6c3697d0a8394175ab 100644 (file)
@@ -559,11 +559,14 @@ pub fn extend<I>(&mut self, dl: &TargetDataLayout,
 
             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(())
@@ -707,12 +710,16 @@ pub fn extend<I>(&mut self, dl: &TargetDataLayout,
                      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(())
     }
 
index f5c23401a4e679785a31547ba91d9f9c3f4ffcba..7982c641ede5cbefbbef80337319e3976f478b8a 100644 (file)
@@ -30,7 +30,7 @@
 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;
@@ -1389,6 +1390,22 @@ fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 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 }
 
@@ -1531,11 +1548,6 @@ pub fn all_fields(&self) ->
         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
@@ -1795,6 +1807,22 @@ pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
     }
 }
 
+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,
@@ -1820,6 +1848,18 @@ pub fn fulfill_ty(&self, ty: Ty<'container>) {
     }
 }
 
+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)]
@@ -1887,7 +1927,7 @@ pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
     /// 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)
     }
 
@@ -2344,7 +2384,7 @@ pub fn item_name(self, id: DefId) -> ast::Name {
         if let Some(id) = self.map.as_local_node_id(id) {
             self.map.name(id)
         } else if id.index == CRATE_DEF_INDEX {
-            token::intern(&self.sess.cstore.original_crate_name(id.krate))
+            self.sess.cstore.original_crate_name(id.krate)
         } else {
             let def_key = self.sess.cstore.def_key(id);
             // The name of a StructCtor is that of its struct parent.
@@ -2747,7 +2787,7 @@ pub fn visit_all_item_likes_in_krate<V,F>(self,
 
     /// 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))
index 56466d596829804ecb89bc77c2355979b0a2d13e..cb3176cce10bd468e747db63596e2f0691205e21 100644 (file)
@@ -22,8 +22,9 @@
 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;
 
@@ -929,19 +930,27 @@ pub fn is_never(&self) -> bool {
         }
     }
 
-    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,
         }
     }
index a6ecfd2fb70668405327f35d7ba2eb6064bc7d35..2f9468dbe5887e532203a67afb07be4c64d16e98 100644 (file)
 //! 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
@@ -61,8 +66,8 @@ fn next(&mut self) -> Option<Ty<'tcx>> {
     }
 }
 
-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()
 }
@@ -73,7 +78,7 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
 // 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 => {
@@ -112,7 +117,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
     }
 }
 
-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());
 }
index 7cd5fd78df528981329792c6f9585bf522e6d81a..e01856b2a476265b161671e78b5760d249e545ae 100644 (file)
 use std::path::Path;
 use std::time::{Duration, Instant};
 
-use hir;
-use hir::intravisit;
-use hir::intravisit::Visitor;
-
 // The name of the associated type for `Fn` return types
 pub const FN_OUTPUT_NAME: &'static str = "Output";
 
@@ -186,57 +182,6 @@ pub fn indenter() -> Indenter {
     Indenter { _cannot_construct_outside_of_this_module: () }
 }
 
-struct LoopQueryVisitor<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;
index a63c7ba6a25ce9fd093ac59754e692372e2c66c9..d04825d560444facbc47d19960a4fb9b0b26f306 100644 (file)
@@ -25,8 +25,8 @@
 use std::usize;
 
 use syntax::abi::Abi;
-use syntax::parse::token;
 use syntax::ast::CRATE_NODE_ID;
+use syntax::symbol::Symbol;
 use hir;
 
 pub fn verbose() -> bool {
@@ -284,7 +284,7 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
             ty::BrAnon(_) |
             ty::BrFresh(_) |
             ty::BrEnv => {
-                let name = token::intern("'r");
+                let name = Symbol::intern("'r");
                 let _ = write!(f, "{}", name);
                 ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID),
                             name,
index b8c26a0512ff8e835d79c78c3e819e8892b12640..916d17dcc91deff5b598dd9d7f5f7dab7a3c915b 100644 (file)
@@ -169,7 +169,7 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 {
                     let name = tcx.item_name(def_id);
                     if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-                        if name.as_str() == "rustc_peek" {
+                        if name == "rustc_peek" {
                             return Some((args, source_info.span));
                         }
                     }
index 836832de5b9c40f52d55daba45721962135764a7..9035c2ab3c236e05cf85fb26813a69dab174bbee 100644 (file)
@@ -11,7 +11,6 @@
 use borrowck::BorrowckCtxt;
 
 use syntax::ast::{self, MetaItem};
-use syntax::ptr::P;
 use syntax_pos::{Span, DUMMY_SP};
 
 use rustc::hir;
@@ -35,7 +34,7 @@
 use self::dataflow::{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();
index f63a27e0d7563fd5df3af52c4d8000f7de7c1c48..3c94d7d6fd5d14919824d55b931de929616ce987 100644 (file)
@@ -204,7 +204,7 @@ fn check_match(
             // 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 {} \
index 5f0c94744a1185f78b63246241a8c395fec2d734..b594fe9853a43ac35a2b5bf8ca247300fd18fdde 100644 (file)
@@ -297,7 +297,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => bug!()
             };
             let pats = args.iter()
-                           .map(|expr| const_expr_to_pat(tcx, &**expr, pat_id, span))
+                           .map(|expr| const_expr_to_pat(tcx, &*expr, pat_id, span))
                            .collect::<Result<_, _>>()?;
             PatKind::TupleStruct(path, pats, None)
         }
@@ -1221,7 +1221,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
     use syntax::ast::*;
     use syntax::ast::LitIntType::*;
     match *lit {
-        LitKind::Str(ref s, _) => Ok(Str((*s).clone())),
+        LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
         LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
         LitKind::Byte(n) => Ok(Integral(U8(n))),
         LitKind::Int(n, Signed(ity)) => {
@@ -1249,15 +1249,15 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
             infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral)
         },
 
-        LitKind::Float(ref n, fty) => {
-            parse_float(n, Some(fty)).map(Float)
+        LitKind::Float(n, fty) => {
+            parse_float(&n.as_str(), Some(fty)).map(Float)
         }
-        LitKind::FloatUnsuffixed(ref n) => {
+        LitKind::FloatUnsuffixed(n) => {
             let fty_hint = match ty_hint.map(|t| &t.sty) {
                 Some(&ty::TyFloat(fty)) => Some(fty),
                 _ => None
             };
-            parse_float(n, fty_hint).map(Float)
+            parse_float(&n.as_str(), fty_hint).map(Float)
         }
         LitKind::Bool(b) => Ok(Bool(b)),
         LitKind::Char(c) => Ok(Char(c)),
index 565a3c443a34ab0581c33bdb6cd1045c33c0d24f..4e2b3786021026bf85b6821724ee0cfe3612201b 100644 (file)
@@ -130,6 +130,18 @@ pub fn insert(&mut self, index: usize, element: A::Element) {
             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> {
index 1f4d09a92247eb9765d218a192b5d9dc7b54024c..e2d3a4f453749aafb0822d4224f20f8d3b759b33 100644 (file)
@@ -344,7 +344,7 @@ pub fn has_value(&mut self, id: K) -> bool {
     }
 
     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> {
index 5466c8871d49177073442e88de47d83195e82261..9a4ecef0c0ebd16d91aa36670a9a6835e2bb4248 100644 (file)
@@ -53,7 +53,8 @@
 use syntax::{ast, diagnostics, visit};
 use syntax::attr;
 use syntax::ext::base::ExtCtxt;
-use syntax::parse::{self, PResult, token};
+use syntax::parse::{self, PResult};
+use syntax::symbol::Symbol;
 use syntax::util::node_count::NodeCounter;
 use syntax;
 use syntax_ext;
@@ -210,13 +211,14 @@ macro_rules! controller_entry_point {
                 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,
@@ -563,8 +565,7 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
     *sess.features.borrow_mut() = features;
 
     *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
-    *sess.crate_disambiguator.borrow_mut() =
-        token::intern(&compute_crate_disambiguator(sess)).as_str();
+    *sess.crate_disambiguator.borrow_mut() = Symbol::intern(&compute_crate_disambiguator(sess));
 
     time(time_passes, "recursion limit", || {
         middle::recursion_limit::update_recursion_limit(sess, &krate);
@@ -709,10 +710,12 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
             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())
@@ -856,7 +859,7 @@ macro_rules! try_with_f {
 
     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",
@@ -1105,7 +1108,7 @@ pub fn phase_6_link_output(sess: &Session,
                            outputs: &OutputFilenames) {
     time(sess.time_passes(),
          "linking",
-         || link::link_binary(sess, trans, outputs, &trans.link.crate_name));
+         || link::link_binary(sess, trans, outputs, &trans.link.crate_name.as_str()));
 }
 
 fn escape_dep_filename(filename: &str) -> String {
@@ -1183,6 +1186,9 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
                          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)
                          }
@@ -1356,11 +1362,3 @@ pub fn build_output_filenames(input: &Input,
         }
     }
 }
-
-// For use by the `rusti` project (https://github.com/murarth/rusti).
-pub fn reset_thread_local_state() {
-    // These may be left in an incoherent state after a previous compile.
-    syntax::ext::hygiene::reset_hygiene_data();
-    // `clear_ident_interner` can be used to free memory, but it does not restore the initial state.
-    token::reset_ident_interner();
-}
index 7e60c40220f84eed8acb55dac747dc42f71be9c6..a0863e0d29422b7dbbf214e0f3372f3f8f1053d9 100644 (file)
 use std::sync::{Arc, Mutex};
 use std::thread;
 
-use syntax::{ast, json};
+use syntax::ast;
 use syntax::codemap::{CodeMap, FileLoader, RealFileLoader};
 use syntax::feature_gate::{GatedCfg, UnstableFeatures};
 use syntax::parse::{self, PResult};
-use syntax_pos::MultiSpan;
-use errors::emitter::Emitter;
+use syntax_pos::{DUMMY_SP, MultiSpan};
 
 #[cfg(test)]
 pub mod test;
@@ -374,37 +373,11 @@ fn handle_explain(code: &str,
     }
 }
 
-fn check_cfg(cfg: &ast::CrateConfig,
-             output: ErrorOutputType) {
-    let emitter: Box<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 {
@@ -413,7 +386,6 @@ fn early_callback(&mut self,
             return Compilation::Stop;
         }
 
-        check_cfg(cfg, output);
         Compilation::Continue
     }
 
@@ -640,24 +612,27 @@ fn print_crate_info(sess: &Session,
                     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 => {
index ecbf28c1082f989e2e58f19d2065efe38095e6ea..6c99c9d71b81585da2090b0be656b88873703bf5 100644 (file)
@@ -450,15 +450,15 @@ fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn {
 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(()),
         }
index 57a9edc5c586b532081f0eba7c3c34c9d8224982..876323d599e857bc3f30f867b3c07b36a84daab3 100644 (file)
@@ -8,13 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::{ast, attr};
+use syntax::ast;
 use llvm::LLVMRustHasFeature;
 use rustc::session::Session;
 use rustc_trans::back::write::create_target_machine;
 use syntax::feature_gate::UnstableFeatures;
-use syntax::parse::token::InternedString;
-use syntax::parse::token::intern_and_get_ident as intern;
+use syntax::symbol::Symbol;
 use libc::c_char;
 
 // WARNING: the features must be known to LLVM or the feature
@@ -41,11 +40,11 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
         _ => &[],
     };
 
-    let tf = InternedString::new("target_feature");
+    let tf = Symbol::intern("target_feature");
     for feat in whitelist {
         assert_eq!(feat.chars().last(), Some('\0'));
         if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
-            cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(&feat[..feat.len() - 1])))
+            cfg.insert((tf, Some(Symbol::intern(&feat[..feat.len() - 1]))));
         }
     }
 
@@ -74,6 +73,6 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
     }
 
     if crt_static {
-        cfg.push(attr::mk_name_value_item_str(tf.clone(), intern("crt-static")));
+        cfg.insert((tf, Some(Symbol::intern("crt-static"))));
     }
 }
index 782c74c8c78c75b17c294458f33ae2a9caace1e9..a4f0e2903847765b197d0685564fda2bc83b9919 100644 (file)
@@ -34,8 +34,8 @@
 use errors;
 use errors::emitter::Emitter;
 use errors::{Level, DiagnosticBuilder};
-use syntax::parse::token;
 use syntax::feature_gate::UnstableFeatures;
+use syntax::symbol::Symbol;
 
 use rustc::hir;
 
@@ -288,11 +288,11 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, token::intern(&name[..]))
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name[..]))
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> &'tcx ty::Region {
-        let name = token::intern(name);
+        let name = Symbol::intern(name);
         self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
             index: index,
             name: name,
index 998cbae2cce150b94bace00a20f21653a69520c1..87e6b2befdc3281fcbbb9359c11bf499d4eaccfd 100644 (file)
@@ -57,7 +57,6 @@
 use std::fs::File;
 use std::io::Write;
 use syntax::ast;
-use syntax::parse::token::InternedString;
 use syntax_pos::Span;
 use {ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
 
@@ -97,7 +96,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 }
 
 type Sources = Vec<(Span, DefId, DepNode<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>,
@@ -106,7 +105,7 @@ struct IfThisChanged<'a, 'tcx:'a> {
 }
 
 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() {
@@ -127,8 +126,8 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
                     None => DepNode::Hir(def_id),
-                    Some(ref n) => {
-                        match DepNode::from_label_string(&n[..], def_id) {
+                    Some(n) => {
+                        match DepNode::from_label_string(&n.as_str(), def_id) {
                             Ok(n) => n,
                             Err(()) => {
                                 self.tcx.sess.span_fatal(
@@ -142,8 +141,8 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
             } else if attr.check_name(ATTR_THEN_THIS_WOULD_NEED) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
-                    Some(ref n) => {
-                        match DepNode::from_label_string(&n[..], def_id) {
+                    Some(n) => {
+                        match DepNode::from_label_string(&n.as_str(), def_id) {
                             Ok(n) => n,
                             Err(()) => {
                                 self.tcx.sess.span_fatal(
@@ -159,7 +158,7 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
                     }
                 };
                 self.then_this_would_need.push((attr.span,
-                                                dep_node_interned.clone().unwrap(),
+                                                dep_node_interned.unwrap(),
                                                 node_id,
                                                 dep_node));
             }
index f98e698a1c9d416b740457a4cfb8f0150977c0da..250ef061e5109305f9ff50ed1dde0db074685a43 100644 (file)
@@ -172,8 +172,8 @@ fn compute_crate_hash(&mut self) {
 
         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.
index a1ece48462b14fad8ae288dc67d3628580899c1f..fd0856393fc1b3b9c8b39bbe0d9a5e5cd73f3568 100644 (file)
@@ -18,6 +18,7 @@
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
 use syntax::parse::token;
+use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
 use syntax::tokenstream;
 use rustc::hir;
@@ -169,8 +170,8 @@ enum SawAbiComponent<'a> {
 
     // FIXME (#14132): should we include (some function of)
     // ident.ctxt as well?
-    SawIdent(token::InternedString),
-    SawStructDef(token::InternedString),
+    SawIdent(InternedString),
+    SawStructDef(InternedString),
 
     SawLifetime,
     SawLifetimeDef(usize),
@@ -232,11 +233,11 @@ enum SawAbiComponent<'a> {
 #[derive(Hash)]
 enum SawExprComponent<'a> {
 
-    SawExprLoop(Option<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,
@@ -246,6 +247,8 @@ enum SawExprComponent<'a> {
     SawExprBinary(hir::BinOp_),
     SawExprUnary(hir::UnOp),
     SawExprLit(ast::LitKind),
+    SawExprLitStr(InternedString, ast::StrStyle),
+    SawExprLitFloat(InternedString, Option<ast::FloatTy>),
     SawExprCast,
     SawExprType,
     SawExprIf,
@@ -314,12 +317,12 @@ fn saw_expr<'a>(node: &'a Expr_,
         ExprUnary(op, _)         => {
             (SawExprUnary(op), unop_can_panic_at_runtime(op))
         }
-        ExprLit(ref lit)         => (SawExprLit(lit.node.clone()), false),
+        ExprLit(ref lit)         => (saw_lit(lit), false),
         ExprCast(..)             => (SawExprCast, false),
         ExprType(..)             => (SawExprType, false),
         ExprIf(..)               => (SawExprIf, false),
         ExprWhile(..)            => (SawExprWhile, false),
-        ExprLoop(_, id)          => (SawExprLoop(id.map(|id| id.node.as_str())), false),
+        ExprLoop(_, id, _)       => (SawExprLoop(id.map(|id| id.node.as_str())), false),
         ExprMatch(..)            => (SawExprMatch, false),
         ExprClosure(cc, _, _, _) => (SawExprClosure(cc), false),
         ExprBlock(..)            => (SawExprBlock, false),
@@ -332,7 +335,7 @@ fn saw_expr<'a>(node: &'a Expr_,
         ExprIndex(..)            => (SawExprIndex, true),
         ExprPath(ref qself, _)   => (SawExprPath(qself.as_ref().map(|q| q.position)), false),
         ExprAddrOf(m, _)         => (SawExprAddrOf(m), false),
-        ExprBreak(id)            => (SawExprBreak(id.map(|id| id.node.as_str())), false),
+        ExprBreak(id, _)         => (SawExprBreak(id.map(|id| id.node.as_str())), false),
         ExprAgain(id)            => (SawExprAgain(id.map(|id| id.node.as_str())), false),
         ExprRet(..)              => (SawExprRet, false),
         ExprInlineAsm(ref a,..)  => (SawExprInlineAsm(a), false),
@@ -341,6 +344,15 @@ fn saw_expr<'a>(node: &'a Expr_,
     }
 }
 
+fn saw_lit(lit: &ast::Lit) -> SawExprComponent<'static> {
+    match lit.node {
+        ast::LitKind::Str(s, style) => SawExprLitStr(s.as_str(), style),
+        ast::LitKind::Float(s, ty) => SawExprLitFloat(s.as_str(), Some(ty)),
+        ast::LitKind::FloatUnsuffixed(s) => SawExprLitFloat(s.as_str(), None),
+        ref node @ _ => SawExprLit(node.clone()),
+    }
+}
+
 #[derive(Hash)]
 enum SawItemComponent {
     SawItemExternCrate,
@@ -874,22 +886,16 @@ fn hash_meta_item(&mut self, meta_item: &ast::MetaItem) {
 
         // ignoring span information, it doesn't matter here
         self.hash_discriminant(&meta_item.node);
+        meta_item.name.as_str().len().hash(self.st);
+        meta_item.name.as_str().hash(self.st);
+
         match meta_item.node {
-            ast::MetaItemKind::Word(ref s) => {
-                s.len().hash(self.st);
-                s.hash(self.st);
-            }
-            ast::MetaItemKind::NameValue(ref s, ref lit) => {
-                s.len().hash(self.st);
-                s.hash(self.st);
-                lit.node.hash(self.st);
-            }
-            ast::MetaItemKind::List(ref s, ref items) => {
-                s.len().hash(self.st);
-                s.hash(self.st);
+            ast::MetaItemKind::Word => {}
+            ast::MetaItemKind::NameValue(ref lit) => saw_lit(lit).hash(self.st),
+            ast::MetaItemKind::List(ref items) => {
                 // Sort subitems so the hash does not depend on their order
                 let indices = self.indices_sorted_by(&items, |p| {
-                    (p.name(), fnv::hash(&p.literal().map(|i| &i.node)))
+                    (p.name().map(Symbol::as_str), fnv::hash(&p.literal().map(saw_lit)))
                 });
                 items.len().hash(self.st);
                 for (index, &item_index) in indices.iter().enumerate() {
@@ -901,7 +907,7 @@ fn hash_meta_item(&mut self, meta_item: &ast::MetaItem) {
                             self.hash_meta_item(meta_item);
                         }
                         ast::NestedMetaItemKind::Literal(ref lit) => {
-                            lit.node.hash(self.st);
+                            saw_lit(lit).hash(self.st);
                         }
                     }
                 }
@@ -914,11 +920,11 @@ pub fn hash_attributes(&mut self, attributes: &[ast::Attribute]) {
         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);
             }
         }
     }
index d238121872be67131f8a2a206e4c20cbd456e68e..546feb212243aca2c3d629ae8a7e89345356481d 100644 (file)
@@ -84,8 +84,8 @@ pub fn krate_still_valid(&self,
             assert_eq!(old_info.krate, krate);
             let old_name: &str = &old_info.name;
             let old_disambiguator: &str = &old_info.disambiguator;
-            let new_name: &str = &tcx.crate_name(krate);
-            let new_disambiguator: &str = &tcx.crate_disambiguator(krate);
+            let new_name: &str = &tcx.crate_name(krate).as_str();
+            let new_disambiguator: &str = &tcx.crate_disambiguator(krate).as_str();
             old_name == new_name && old_disambiguator == new_disambiguator
         }
     }
@@ -99,8 +99,8 @@ fn make_key(name: &str, disambiguator: &str) -> String {
         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()
index 0cd1c88fb877bb7e007444b2e63cd0d3c4da0344..85c35bf79ce81347a4273e82b83200d94fc301b9 100644 (file)
@@ -48,7 +48,6 @@
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use syntax::ast::{self, Attribute, NestedMetaItem};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use syntax::parse::token::InternedString;
 use syntax_pos::Span;
 use rustc::ty::TyCtxt;
 use ich::Fingerprint;
@@ -88,12 +87,11 @@ pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
 }
 
 impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
-
     fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<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(
@@ -276,13 +274,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
         if item.check_name(CFG) {
             let value = expect_associated_value(tcx, item);
             debug!("check_config: searching for cfg {:?}", value);
-            for cfg in &config[..] {
-                if cfg.check_name(&value[..]) {
-                    debug!("check_config: matched {:?}", cfg);
-                    return true;
-                }
-            }
-            return false;
+            return config.contains(&(value, None));
         }
     }
 
@@ -291,7 +283,7 @@ fn check_config(tcx: TyCtxt, attr: &ast::Attribute) -> bool {
         &format!("no cfg attribute"));
 }
 
-fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> InternedString {
+fn expect_associated_value(tcx: TyCtxt, item: &NestedMetaItem) -> ast::Name {
     if let Some(value) = item.value_str() {
         value
     } else {
index 2572a9c1d78f6ea91e8d0d909de15022aff01e84..26181dbaf50ff243b0501514c03abe059f4d5570 100644 (file)
@@ -604,7 +604,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
 }
 
 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
index 6320a923d690c720004d972187252c76e93729e7..4440cb41dc5f20051a8a4c883d4d41a1185f6bfc 100644 (file)
@@ -81,19 +81,12 @@ fn to_camel_case(s: &str) -> String {
                 .concat()
         }
 
-        let s = name.as_str();
-
         if !is_camel_case(name) {
-            let c = to_camel_case(&s);
+            let c = to_camel_case(&name.as_str());
             let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`",
-                        sort,
-                        s)
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, name)
             } else {
-                format!("{} `{}` should have a camel case name such as `{}`",
-                        sort,
-                        s,
-                        c)
+                format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
             };
             cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
         }
@@ -241,8 +234,8 @@ fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
             .and_then(|at| at.value_str().map(|s| (at, s)));
         if let Some(ref name) = cx.tcx.sess.opts.crate_name {
             self.check_snake_case(cx, "crate", name, None);
-        } else if let Some((attr, ref name)) = attr_crate_name {
-            self.check_snake_case(cx, "crate", name, Some(attr.span));
+        } else if let Some((attr, name)) = attr_crate_name {
+            self.check_snake_case(cx, "crate", &name.as_str(), Some(attr.span));
         }
     }
 
@@ -326,21 +319,19 @@ fn check_struct_def(&mut self,
 
 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));
             }
         }
     }
index 51ffb1ebc8e99ae1d687fa5c8cfe99e1b1198890..0b2ae58852300806d9ec81392a42a0d183c27d53 100644 (file)
@@ -45,6 +45,7 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use rustc::hir::{self, PatKind};
@@ -633,9 +634,9 @@ fn lint(&self,
             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) {
@@ -643,10 +644,10 @@ fn lint(&self,
                 }
             }
 
-            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 {
@@ -772,9 +773,9 @@ fn get_lints(&self) -> LintArray {
 
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) {
-        let name = &*attr.name();
+        let name = attr.name();
         for &&(n, _, ref g) in &self.depr_attrs {
-            if n == name {
+            if name == n {
                 if let &AttributeGate::Gated(Stability::Deprecated(link),
                                              ref name,
                                              ref reason,
@@ -1228,7 +1229,7 @@ fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
                 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"
         }
     }
 }
index 114c0ea556ef5f6b712721da87b618f3da336977..1a3ea5db871ebedc1363cba4e1f9550f9623fcbc 100644 (file)
@@ -232,6 +232,10 @@ macro_rules! add_lint_group {
             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
index 4155d3e67a26deef03b823810001c13df12d81d4..8aa5e9e0a9460afb18d08531d44fc44577a0f1f7 100644 (file)
@@ -219,9 +219,9 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
                     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,
                                 }
index 0668d362037dd3450a3f98c37086cde0f35b1eba..fa452017f0cf1d7fecbdb7a1ddbdc6fcf4ae3e97 100644 (file)
@@ -20,7 +20,7 @@
 use syntax::ast;
 use syntax::attr;
 use syntax::feature_gate::{BUILTIN_ATTRIBUTES, AttributeType};
-use syntax::parse::token::keywords;
+use syntax::symbol::keywords;
 use syntax::ptr::P;
 use syntax_pos::Span;
 
@@ -48,7 +48,7 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
                 let name = path1.node;
                 if let hir::BindByValue(hir::MutMutable) = mode {
                     if !name.as_str().starts_with("_") {
-                        match mutables.entry(name.0 as usize) {
+                        match mutables.entry(name) {
                             Vacant(entry) => {
                                 entry.insert(vec![id]);
                             }
@@ -162,7 +162,7 @@ fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool
                     // check for #[must_use="..."]
                     if let Some(s) = attr.value_str() {
                         msg.push_str(": ");
-                        msg.push_str(&s);
+                        msg.push_str(&s.as_str());
                     }
                     cx.span_lint(UNUSED_MUST_USE, sp, &msg);
                     return true;
@@ -274,10 +274,10 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
             // 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]"
index f97daa22ff6624c26487dfe8b9a5e1d1a1c43fb0..88f8c0553adca4ead988b7914ec7e8b425436c3b 100644 (file)
@@ -12,9 +12,6 @@ crate-type = ["dylib"]
 [features]
 static-libstdcpp = []
 
-[dependencies]
-rustc_bitflags = { path = "../librustc_bitflags" }
-
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 gcc = "0.3.27"
index 6be3d1172dc2380e4cce02dcedb4a9d886818b70..50bc3e7b6243f8d8743cb0da1a07398724b918e2 100644 (file)
@@ -145,6 +145,9 @@ fn main() {
         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")
index 2173adf2e6e2d129e1df47f42cde20e2a437d7a1..470e8d1fd4578d75eb2bb86274f4674713abfba0 100644 (file)
@@ -83,59 +83,31 @@ pub enum DLLStorageClass {
     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
@@ -530,6 +502,9 @@ pub enum DIDescriptorFlags {
     /// 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;
@@ -810,16 +785,12 @@ pub fn LLVMRustGetOrInsertFunction(M: ModuleRef,
     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;
@@ -830,9 +801,6 @@ pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef,
     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
@@ -876,7 +844,7 @@ pub fn LLVMInsertBasicBlockInContext(C: ContextRef,
     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)
index 65e0dbcad3a6a8eb7615a08f53fa498bd5de2c8c..c4ec418f224b579c00fad7ab0d755d06def05f57 100644 (file)
 #![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::*;
@@ -68,54 +64,6 @@ pub fn into_result(self) -> Result<(), ()> {
     }
 }
 
-#[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,
@@ -140,7 +88,7 @@ pub fn ReturnValue() -> Self {
         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,
@@ -229,15 +177,15 @@ pub fn set_thread_local(global: ValueRef, is_thread_local: bool) {
 
 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) {
index 5384535024e537f23e8c3ec1d119389be26a0f57..27c00481bfd3adad17006212acada0650b339915 100644 (file)
 use syntax::attr;
 use syntax::ext::base::SyntaxExtension;
 use syntax::feature_gate::{self, GateIssue};
-use syntax::parse::token::{InternedString, intern};
+use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 use log;
 
 pub struct Library {
     pub dylib: Option<(PathBuf, PathKind)>,
     pub rlib: Option<(PathBuf, PathKind)>,
+    pub rmeta: Option<(PathBuf, PathKind)>,
     pub metadata: MetadataBlob,
 }
 
@@ -52,7 +53,7 @@ pub struct CrateLoader<'a> {
     cstore: &'a CStore,
     next_crate_num: CrateNum,
     foreign_item_map: FxHashMap<String, Vec<ast::NodeId>>,
-    local_crate_name: String,
+    local_crate_name: Symbol,
 }
 
 fn dump_crates(cstore: &CStore) {
@@ -62,16 +63,17 @@ fn dump_crates(cstore: &CStore) {
         info!("  cnum: {}", data.cnum);
         info!("  hash: {}", data.hash());
         info!("  reqd: {:?}", data.dep_kind.get());
-        let CrateSource { dylib, rlib } = data.source.clone();
+        let CrateSource { dylib, rlib, rmeta } = data.source.clone();
         dylib.map(|dl| info!("  dylib: {}", dl.0.display()));
         rlib.map(|rl|  info!("   rlib: {}", rl.0.display()));
-    })
+        rmeta.map(|rl| info!("   rmeta: {}", rl.0.display()));
+    });
 }
 
 #[derive(Debug)]
 struct ExternCrateInfo {
-    ident: String,
-    name: String,
+    ident: Symbol,
+    name: Symbol,
     id: ast::NodeId,
     dep_kind: DepKind,
 }
@@ -80,7 +82,7 @@ fn register_native_lib(sess: &Session,
                        cstore: &CStore,
                        span: Option<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,
@@ -147,7 +149,7 @@ pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Sel
             cstore: cstore,
             next_crate_num: cstore.next_crate_num(),
             foreign_item_map: FxHashMap(),
-            local_crate_name: local_crate_name.to_owned(),
+            local_crate_name: Symbol::intern(local_crate_name),
         }
     }
 
@@ -160,12 +162,12 @@ fn extract_crate_info(&self, i: &ast::Item) -> Option<ExternCrateInfo> {
                     Some(name) => {
                         validate_crate_name(Some(self.sess), &name.as_str(),
                                             Some(i.span));
-                        name.to_string()
+                        name
                     }
-                    None => i.ident.to_string(),
+                    None => i.ident.name,
                 };
                 Some(ExternCrateInfo {
-                    ident: i.ident.to_string(),
+                    ident: i.ident.name,
                     name: name,
                     id: i.id,
                     dep_kind: if attr::contains_name(&i.attrs, "no_link") {
@@ -179,7 +181,7 @@ fn extract_crate_info(&self, i: &ast::Item) -> Option<ExternCrateInfo> {
         }
     }
 
-    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| {
@@ -201,7 +203,7 @@ fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
             // `source` stores paths which are normalized which may be different
             // from the strings on the command line.
             let source = self.cstore.used_crate_source(cnum);
-            if let Some(locs) = self.sess.opts.externs.get(name) {
+            if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
                 let found = locs.iter().any(|l| {
                     let l = fs::canonicalize(l).ok();
                     source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
@@ -233,7 +235,7 @@ fn verify_no_symbol_conflicts(&self,
                                   root: &CrateRoot) {
         // Check for (potential) conflicts with the local crate
         if self.local_crate_name == root.name &&
-           self.sess.local_crate_disambiguator() == &root.disambiguator[..] {
+           self.sess.local_crate_disambiguator() == root.disambiguator {
             span_fatal!(self.sess, span, E0519,
                         "the current crate is indistinguishable from one of its \
                          dependencies: it has the same crate-name `{}` and was \
@@ -258,8 +260,8 @@ fn verify_no_symbol_conflicts(&self,
 
     fn register_crate(&mut self,
                       root: &Option<CratePaths>,
-                      ident: &str,
-                      name: &str,
+                      ident: Symbol,
+                      name: Symbol,
                       span: Span,
                       lib: Library,
                       dep_kind: DepKind)
@@ -278,6 +280,7 @@ fn register_crate(&mut self,
                 ident: ident.to_string(),
                 dylib: lib.dylib.clone().map(|p| p.0),
                 rlib:  lib.rlib.clone().map(|p| p.0),
+                rmeta: lib.rmeta.clone().map(|p| p.0),
             })
         } else {
             None
@@ -285,12 +288,12 @@ fn register_crate(&mut self,
         // Maintain a reference to the top most crate.
         let root = if root.is_some() { root } else { &crate_paths };
 
-        let Library { dylib, rlib, metadata } = lib;
+        let Library { dylib, rlib, rmeta, metadata } = lib;
 
         let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
 
         let cmeta = Rc::new(cstore::CrateMetadata {
-            name: name.to_string(),
+            name: name,
             extern_crate: Cell::new(None),
             key_map: metadata.load_key_map(crate_root.index),
             proc_macros: crate_root.macro_derive_registrar.map(|_| {
@@ -305,6 +308,7 @@ fn register_crate(&mut self,
             source: cstore::CrateSource {
                 dylib: dylib,
                 rlib: rlib,
+                rmeta: rmeta,
             },
         });
 
@@ -314,8 +318,8 @@ fn register_crate(&mut self,
 
     fn resolve_crate(&mut self,
                      root: &Option<CratePaths>,
-                     ident: &str,
-                     name: &str,
+                     ident: Symbol,
+                     name: Symbol,
                      hash: Option<&Svh>,
                      span: Span,
                      path_kind: PathKind,
@@ -366,6 +370,9 @@ fn resolve_crate(&mut self,
         match result {
             LoadResult::Previous(cnum) => {
                 let data = self.cstore.get_crate_data(cnum);
+                if data.root.macro_derive_registrar.is_some() {
+                    dep_kind = DepKind::MacrosOnly;
+                }
                 data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
                 (cnum, data)
             }
@@ -456,13 +463,12 @@ fn resolve_crate_deps(&mut self,
         let deps = crate_root.crate_deps.decode(metadata);
         let map: FxHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
             debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
-            let dep_name = &dep.name.as_str();
             let dep_kind = match dep_kind {
                 DepKind::MacrosOnly => DepKind::MacrosOnly,
                 _ => dep.kind,
             };
             let (local_cnum, ..) = self.resolve_crate(
-                root, dep_name, dep_name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
+                root, dep.name, dep.name, Some(&dep.hash), span, PathKind::Dependency, dep_kind,
             );
             (CrateNum::new(crate_num + 1), local_cnum)
         }).collect();
@@ -482,13 +488,11 @@ fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> Extens
         let target_triple = &self.sess.opts.target_triple[..];
         let is_cross = target_triple != config::host_triple();
         let mut target_only = false;
-        let ident = info.ident.clone();
-        let name = info.name.clone();
         let mut locate_ctxt = locator::Context {
             sess: self.sess,
             span: span,
-            ident: &ident[..],
-            crate_name: &name[..],
+            ident: info.ident,
+            crate_name: info.name,
             hash: None,
             filesearch: self.sess.host_filesearch(PathKind::Crate),
             target: &self.sess.host,
@@ -582,11 +586,11 @@ fn register_custom_derive(&mut self,
                                       trait_name: &str,
                                       expand: fn(TokenStream) -> TokenStream,
                                       attributes: &[&'static str]) {
-                let attrs = attributes.iter().map(|s| InternedString::new(s)).collect();
+                let attrs = attributes.iter().cloned().map(Symbol::intern).collect();
                 let derive = SyntaxExtension::CustomDerive(
                     Box::new(CustomDerive::new(expand, attrs))
                 );
-                self.0.push((intern(trait_name), Rc::new(derive)));
+                self.0.push((Symbol::intern(trait_name), Rc::new(derive)));
             }
         }
 
@@ -604,8 +608,8 @@ fn register_custom_derive(&mut self,
     pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
                                  -> Option<(PathBuf, Svh, DefIndex)> {
         let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
-             name: name.to_string(),
-             ident: name.to_string(),
+             name: Symbol::intern(name),
+             ident: Symbol::intern(name),
              id: ast::DUMMY_NODE_ID,
              dep_kind: DepKind::MacrosOnly,
         });
@@ -642,7 +646,7 @@ fn register_statically_included_foreign_items(&mut self) {
         let libs = self.cstore.get_used_libraries();
         for (foreign_lib, list) in self.foreign_item_map.iter() {
             let is_static = libs.borrow().iter().any(|lib| {
-                *foreign_lib == lib.name && lib.kind == cstore::NativeStatic
+                lib.name == &**foreign_lib && lib.kind == cstore::NativeStatic
             });
             if is_static {
                 for id in list {
@@ -705,8 +709,8 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // in terms of everyone has a compatible panic runtime format, that's
         // performed later as part of the `dependency_format` module.
         let name = match desired_strategy {
-            PanicStrategy::Unwind => "panic_unwind",
-            PanicStrategy::Abort => "panic_abort",
+            PanicStrategy::Unwind => Symbol::intern("panic_unwind"),
+            PanicStrategy::Abort => Symbol::intern("panic_abort"),
         };
         info!("panic runtime not found -- loading {}", name);
 
@@ -767,7 +771,8 @@ fn inject_allocator_crate(&mut self) {
                 config::CrateTypeProcMacro |
                 config::CrateTypeCdylib |
                 config::CrateTypeStaticlib => need_lib_alloc = true,
-                config::CrateTypeRlib => {}
+                config::CrateTypeRlib |
+                config::CrateTypeMetadata => {}
             }
         }
         if !need_lib_alloc && !need_exe_alloc { return }
@@ -788,9 +793,9 @@ fn inject_allocator_crate(&mut self) {
         // * Staticlibs and Rust dylibs use system malloc
         // * Rust dylibs used as dependencies to rust use jemalloc
         let name = if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
-            &self.sess.target.target.options.lib_allocation_crate
+            Symbol::intern(&self.sess.target.target.options.lib_allocation_crate)
         } else {
-            &self.sess.target.target.options.exe_allocation_crate
+            Symbol::intern(&self.sess.target.target.options.exe_allocation_crate)
         };
         let dep_kind = DepKind::Implicit;
         let (cnum, data) =
@@ -852,8 +857,8 @@ fn inject_dependency_if(&self,
 impl<'a> CrateLoader<'a> {
     pub fn preprocess(&mut self, krate: &ast::Crate) {
         for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
-            if let Some(ref linkarg) = attr.value_str() {
-                self.cstore.add_used_link_args(&linkarg);
+            if let Some(linkarg) = attr.value_str() {
+                self.cstore.add_used_link_args(&linkarg.as_str());
             }
         }
     }
@@ -866,7 +871,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
         // First, add all of the custom #[link_args] attributes
         for m in i.attrs.iter().filter(|a| a.check_name("link_args")) {
             if let Some(linkarg) = m.value_str() {
-                self.cstore.add_used_link_args(&linkarg);
+                self.cstore.add_used_link_args(&linkarg.as_str());
             }
         }
 
@@ -878,7 +883,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
             };
             let kind = items.iter().find(|k| {
                 k.check_name("kind")
-            }).and_then(|a| a.value_str());
+            }).and_then(|a| a.value_str()).map(Symbol::as_str);
             let kind = match kind.as_ref().map(|s| &s[..]) {
                 Some("static") => cstore::NativeStatic,
                 Some("dylib") => cstore::NativeUnknown,
@@ -900,7 +905,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
                     struct_span_err!(self.sess, m.span, E0459,
                                      "#[link(...)] specified without `name = \"foo\"`")
                         .span_label(m.span, &format!("missing `name` argument")).emit();
-                    InternedString::new("foo")
+                    Symbol::intern("foo")
                 }
             };
             let cfg = items.iter().find(|k| {
@@ -910,7 +915,7 @@ fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
                 list[0].meta_item().unwrap().clone()
             });
             let lib = NativeLibrary {
-                name: n.to_string(),
+                name: n,
                 kind: kind,
                 cfg: cfg,
             };
@@ -941,7 +946,7 @@ fn postprocess(&mut self, krate: &ast::Crate) {
 
         for &(ref name, kind) in &self.sess.opts.libs {
             let lib = NativeLibrary {
-                name: name.clone(),
+                name: Symbol::intern(name),
                 kind: kind,
                 cfg: None,
             };
@@ -959,7 +964,7 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
 
         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();
index 37853b7473a6500d05e3e42b7f346fdf5b574d33..7c1834c1576a8f1f5e8d5318a5c92121652e960b 100644 (file)
 
 use std::cell::{RefCell, Cell};
 use std::rc::Rc;
-use std::path::PathBuf;
 use flate::Bytes;
 use syntax::{ast, attr};
 use syntax::ext::base::SyntaxExtension;
+use syntax::symbol::Symbol;
 use syntax_pos;
 
 pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference};
 pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
-pub use rustc::middle::cstore::{CrateSource, LinkMeta};
+pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
 
 // A map from external crate numbers (as decoded from some crate file) to
 // local crate numbers (as generated during this session). Each external
@@ -44,6 +44,7 @@
 pub enum MetadataBlob {
     Inflated(Bytes),
     Archive(locator::ArchiveMetadata),
+    Raw(Vec<u8>),
 }
 
 /// Holds information about a syntax_pos::FileMap imported from another crate.
@@ -58,7 +59,7 @@ pub struct ImportedFileMap {
 }
 
 pub struct CrateMetadata {
-    pub name: String,
+    pub name: Symbol,
 
     /// Information about the extern crate that caused this crate to
     /// be loaded. If this is `None`, then the crate was injected
@@ -185,7 +186,7 @@ pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate
     // 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);
@@ -201,6 +202,16 @@ pub fn do_get_used_crates(&self,
                     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<_>>();
@@ -213,7 +224,7 @@ pub fn do_get_used_crates(&self,
     }
 
     pub fn add_used_library(&self, lib: NativeLibrary) {
-        assert!(!lib.name.is_empty());
+        assert!(!lib.name.as_str().is_empty());
         self.used_libraries.borrow_mut().push(lib);
     }
 
@@ -249,14 +260,14 @@ pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
 }
 
 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 {
index 2018d829597d43bb280799594efe1343a737f07e..ead933384b96d9b4e18bbfbe807270c406e83c02 100644 (file)
@@ -13,7 +13,7 @@
 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;
@@ -262,14 +262,14 @@ fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
         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>
@@ -282,9 +282,9 @@ fn crate_hash(&self, cnum: CrateNum) -> Svh
         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>
@@ -544,7 +544,7 @@ fn metadata_section_name(&self, target: &Target) -> &str
         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)
     }
index 3af9d291ae55a4056c2d153eae2195d7bef5b92c..f59f2bcc074764c42bf61f55e5da3a6729239536 100644 (file)
@@ -88,8 +88,9 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
 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,
         }
     }
 }
@@ -420,6 +421,10 @@ pub fn is_compatible(&self) -> bool {
         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();
@@ -934,7 +939,7 @@ fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
             .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()
index 3ab542442a1fbe4fbf1eca6b4d224f6f3e956462..665f3de0a3ba7fda9a389cc3c257d19f4ae19708 100644 (file)
@@ -34,7 +34,7 @@
 use std::u32;
 use syntax::ast::{self, CRATE_NODE_ID};
 use syntax::attr;
-use syntax;
+use syntax::symbol::Symbol;
 use syntax_pos;
 
 use rustc::hir::{self, PatKind};
@@ -600,7 +600,7 @@ fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq<ast::Name> {
             if let PatKind::Binding(_, ref path1, _) = arg.pat.node {
                 path1.node
             } else {
-                syntax::parse::token::intern("")
+                Symbol::intern("")
             }
         }))
     }
@@ -1119,7 +1119,7 @@ fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<(CrateNum, Rc<cstore::CrateM
         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(),
             }
@@ -1278,11 +1278,10 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
         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
@@ -1368,7 +1367,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // 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,
@@ -1378,8 +1378,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             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.
index b677a63edc06458c6e50247dd22281535175dfd2..868bc363791350d53e322af81e3e99c426157579 100644 (file)
 //! 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;
@@ -249,8 +257,8 @@ pub struct CrateMismatch {
 pub struct Context<'a> {
     pub sess: &'a Session,
     pub span: Span,
-    pub ident: &'a str,
-    pub crate_name: &'a str,
+    pub ident: Symbol,
+    pub crate_name: Symbol,
     pub hash: Option<&'a Svh>,
     // points to either self.sess.target.target or self.sess.host, must match triple
     pub target: &'a Target,
@@ -275,6 +283,7 @@ pub struct CratePaths {
     pub ident: String,
     pub dylib: Option<PathBuf>,
     pub rlib: Option<PathBuf>,
+    pub rmeta: Option<PathBuf>,
 }
 
 pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
@@ -282,6 +291,7 @@ pub struct CratePaths {
 #[derive(Copy, Clone, PartialEq)]
 enum CrateFlavor {
     Rlib,
+    Rmeta,
     Dylib,
 }
 
@@ -289,6 +299,7 @@ impl fmt::Display for CrateFlavor {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(match *self {
             CrateFlavor::Rlib => "rlib",
+            CrateFlavor::Rmeta => "rmeta",
             CrateFlavor::Dylib => "dylib",
         })
     }
@@ -296,12 +307,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 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()
     }
 }
 
@@ -422,7 +428,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
         // must be loaded via -L plus some filtering.
         if self.hash.is_none() {
             self.should_match_name = false;
-            if let Some(s) = self.sess.opts.externs.get(self.crate_name) {
+            if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
                 return self.find_commandline_library(s.iter());
             }
             self.should_match_name = true;
@@ -457,32 +463,35 @@ fn find_library_crate(&mut self) -> Option<Library> {
                 None => return FileDoesntMatch,
                 Some(file) => file,
             };
-            let (hash, rlib) = if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
-                (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], true)
-            } else if file.starts_with(&dylib_prefix) &&
-                                         file.ends_with(&dypair.1) {
-                (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], false)
-            } else {
-                if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
-                    staticlibs.push(CrateMismatch {
-                        path: path.to_path_buf(),
-                        got: "static".to_string(),
-                    });
-                }
-                return FileDoesntMatch;
-            };
+            let (hash, found_kind) =
+                if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
+                    (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
+                } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
+                    (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
+                } else if file.starts_with(&dylib_prefix) &&
+                                             file.ends_with(&dypair.1) {
+                    (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
+                } else {
+                    if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
+                        staticlibs.push(CrateMismatch {
+                            path: path.to_path_buf(),
+                            got: "static".to_string(),
+                        });
+                    }
+                    return FileDoesntMatch;
+                };
             info!("lib candidate: {}", path.display());
 
             let hash_str = hash.to_string();
             let slot = candidates.entry(hash_str)
-                .or_insert_with(|| (FxHashMap(), FxHashMap()));
-            let (ref mut rlibs, ref mut dylibs) = *slot;
+                .or_insert_with(|| (FxHashMap(), FxHashMap(), FxHashMap()));
+            let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot;
             fs::canonicalize(path)
                 .map(|p| {
-                    if rlib {
-                        rlibs.insert(p, kind);
-                    } else {
-                        dylibs.insert(p, kind);
+                    match found_kind {
+                        CrateFlavor::Rlib => { rlibs.insert(p, kind); }
+                        CrateFlavor::Rmeta => { rmetas.insert(p, kind); }
+                        CrateFlavor::Dylib => { dylibs.insert(p, kind); }
                     }
                     FileMatches
                 })
@@ -499,15 +508,17 @@ fn find_library_crate(&mut self) -> Option<Library> {
         // libraries corresponds to the crate id and hash criteria that this
         // search is being performed for.
         let mut libraries = FxHashMap();
-        for (_hash, (rlibs, dylibs)) in candidates {
+        for (_hash, (rlibs, rmetas, dylibs)) in candidates {
             let mut slot = None;
             let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
+            let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
             let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
             if let Some((h, m)) = slot {
                 libraries.insert(h,
                                  Library {
                                      dylib: dylib,
                                      rlib: rlib,
+                                     rmeta: rmeta,
                                      metadata: m,
                                  });
             }
@@ -533,7 +544,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
                     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
@@ -628,25 +639,26 @@ fn extract_one(&mut self,
     }
 
     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");
@@ -703,6 +715,7 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
         let sess = self.sess;
         let dylibname = self.dylibname();
         let mut rlibs = FxHashMap();
+        let mut rmetas = FxHashMap();
         let mut dylibs = FxHashMap();
         {
             let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| {
@@ -721,7 +734,8 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
                         return false;
                     }
                 };
-                if file.starts_with("lib") && file.ends_with(".rlib") {
+                if file.starts_with("lib") &&
+                   (file.ends_with(".rlib") || file.ends_with(".rmeta")) {
                     return true;
                 } else {
                     let (ref prefix, ref suffix) = dylibname;
@@ -744,6 +758,8 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
             for loc in locs {
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
                     rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+                } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
+                    rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
                 } else {
                     dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
                 }
@@ -753,9 +769,10 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
         // Extract the rlib/dylib pair.
         let mut slot = None;
         let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
+        let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
         let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
 
-        if rlib.is_none() && dylib.is_none() {
+        if rlib.is_none() && rmeta.is_none() && dylib.is_none() {
             return None;
         }
         match slot {
@@ -763,6 +780,7 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
                 Some(Library {
                     dylib: dylib,
                     rlib: rlib,
+                    rmeta: rmeta,
                     metadata: metadata,
                 })
             }
@@ -850,6 +868,15 @@ fn get_metadata_section_imp(target: &Target,
                 Ok(blob)
             }
         };
+    } else if flavor == CrateFlavor::Rmeta {
+        let mut file = File::open(filename).map_err(|_|
+            format!("could not open file: '{}'", filename.display()))?;
+        let mut buf = vec![];
+        file.read_to_end(&mut buf).map_err(|_|
+            format!("failed to read rlib metadata: '{}'", filename.display()))?;
+        let blob = MetadataBlob::Raw(buf);
+        verify_decompressed_encoding_version(&blob, filename)?;
+        return Ok(blob);
     }
     unsafe {
         let buf = common::path2cstr(filename);
@@ -933,6 +960,8 @@ pub fn list_file_metadata(target: &Target, path: &Path, out: &mut io::Write) ->
     let filename = path.file_name().unwrap().to_str().unwrap();
     let flavor = if filename.ends_with(".rlib") {
         CrateFlavor::Rlib
+    } else if filename.ends_with(".rmeta") {
+        CrateFlavor::Rmeta
     } else {
         CrateFlavor::Dylib
     };
index 32c8c5e2ee87996536b634662fd3c1ce209fbe76..32e89f64f0ec1516b2049e8f5a46bafefde83342 100644 (file)
@@ -22,6 +22,7 @@
 
 use rustc_serialize as serialize;
 use syntax::{ast, attr};
+use syntax::symbol::Symbol;
 use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
@@ -33,15 +34,17 @@ pub fn rustc_version() -> String {
 
 /// 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];
 
@@ -162,11 +165,10 @@ pub enum LazyState {
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct CrateRoot {
-    pub rustc_version: String,
-    pub name: String,
+    pub name: Symbol,
     pub triple: String,
     pub hash: hir::svh::Svh,
-    pub disambiguator: String,
+    pub disambiguator: Symbol,
     pub panic_strategy: PanicStrategy,
     pub plugin_registrar_fn: Option<DefIndex>,
     pub macro_derive_registrar: Option<DefIndex>,
index 5fa08442221001cce28bbcab1d6f6ab93121d010..5a77de08070281763ba800cc6796895a5cd353fb 100644 (file)
@@ -169,41 +169,39 @@ pub fn into_expr(&mut self,
                 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 } => {
index 4a1926e7c57d4ec59886a4b4fcfb1503ccac540b..f04d630379a35c99ed6dfdb27b3515190fe9daf1 100644 (file)
@@ -11,9 +11,7 @@
 use build::{BlockAnd, BlockAndExtension, Builder};
 use build::scope::LoopScope;
 use hair::*;
-use rustc::middle::region::CodeExtent;
 use rustc::mir::*;
-use syntax_pos::Span;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
@@ -79,14 +77,28 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 block.unit()
             }
             ExprKind::Continue { label } => {
-                this.break_or_continue(expr_span, label, block,
-                                       |loop_scope| loop_scope.continue_block)
+                let LoopScope { continue_block, extent, .. } =
+                    *this.find_loop_scope(expr_span, label);
+                this.exit_scope(expr_span, extent, block, continue_block);
+                this.cfg.start_new_block().unit()
             }
-            ExprKind::Break { label } => {
-                this.break_or_continue(expr_span, label, block, |loop_scope| {
-                    loop_scope.might_break = true;
-                    loop_scope.break_block
-                })
+            ExprKind::Break { label, value } => {
+                let (break_block, extent, destination) = {
+                    let LoopScope {
+                        break_block,
+                        extent,
+                        ref break_destination,
+                        ..
+                    } = *this.find_loop_scope(expr_span, label);
+                    (break_block, extent, break_destination.clone())
+                };
+                if let Some(value) = value {
+                    unpack!(block = this.into(&destination, block, value))
+                } else {
+                    this.cfg.push_assign_unit(block, source_info, &destination)
+                }
+                this.exit_scope(expr_span, extent, block, break_block);
+                this.cfg.start_new_block().unit()
             }
             ExprKind::Return { value } => {
                 block = match value {
@@ -115,20 +127,4 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
         }
     }
 
-    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()
-    }
-
 }
index 458a952543e4008090c0375df9ec54bd58275f72..5713ee45b9d8f4c5927285d84ea993567b1f7053 100644 (file)
@@ -18,7 +18,7 @@
 use rustc::hir;
 use syntax::abi::Abi;
 use syntax::ast;
-use syntax::parse::token::keywords;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -38,7 +38,7 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     /// the current set of loops; see the `scope` module for more
     /// details
-    loop_scopes: Vec<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
index 4d9b6c0e05a4250345e82fc8277f8b2b863a642b..e5fac94a8a494eb2f344a6fb5ae6964b01cae69a 100644 (file)
@@ -177,7 +177,7 @@ struct FreeData<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub struct LoopScope {
+pub struct LoopScope<'tcx> {
     /// Extent of the loop
     pub extent: CodeExtent,
     /// Where the body of the loop begins
@@ -185,8 +185,9 @@ pub struct LoopScope {
     /// Block to branch into when the loop terminates (either by being `break`-en out from, or by
     /// having its condition to become false)
     pub break_block: BasicBlock,
-    /// Indicates the reachability of the break_block for this loop
-    pub might_break: bool
+    /// The destination of the loop expression itself (i.e. where to put the result of a `break`
+    /// expression)
+    pub break_destination: Lvalue<'tcx>,
 }
 
 impl<'tcx> Scope<'tcx> {
@@ -246,10 +247,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     ///
     /// Returns the might_break attribute of the LoopScope used.
     pub fn in_loop_scope<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();
@@ -257,13 +258,12 @@ pub fn in_loop_scope<F>(&mut self,
             extent: extent.clone(),
             continue_block: loop_block,
             break_block: break_block,
-            might_break: false
+            break_destination: break_destination,
         };
         self.loop_scopes.push(loop_scope);
         f(self);
         let loop_scope = self.loop_scopes.pop().unwrap();
         assert!(loop_scope.extent == extent);
-        loop_scope.might_break
     }
 
     /// Convenience wrapper that pushes a scope and then executes `f`
@@ -386,7 +386,7 @@ pub fn new_visibility_scope(&mut self, span: Span) -> VisibilityScope {
     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 => {
index 24c1ca574a01baf6731adc2fefcb8cdf700a52a7..6fa2672593587b2f0885fa08f4e1cc73e67ff58b 100644 (file)
@@ -21,7 +21,6 @@
 use rustc::middle::region::CodeExtent;
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::cast::CastKind as TyCastKind;
-use rustc::mir::*;
 use rustc::hir;
 use syntax::ptr::P;
 
@@ -559,8 +558,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         },
         hir::ExprRet(ref v) =>
             ExprKind::Return { value: v.to_ref() },
-        hir::ExprBreak(label) =>
-            ExprKind::Break { label: label.map(|_| loop_label(cx, expr)) },
+        hir::ExprBreak(label, ref value) =>
+            ExprKind::Break { label: label.map(|_| loop_label(cx, expr)),
+                              value: value.to_ref() },
         hir::ExprAgain(label) =>
             ExprKind::Continue { label: label.map(|_| loop_label(cx, expr)) },
         hir::ExprMatch(ref discr, ref arms, _) =>
@@ -573,7 +573,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         hir::ExprWhile(ref cond, ref body, _) =>
             ExprKind::Loop { condition: Some(cond.to_ref()),
                              body: block::to_expr_ref(cx, body) },
-        hir::ExprLoop(ref body, _) =>
+        hir::ExprLoop(ref body, _, _) =>
             ExprKind::Loop { condition: None,
                              body: block::to_expr_ref(cx, body) },
         hir::ExprField(ref source, name) => {
index 038300068fce1c6d402362f0da189d992e2083f1..cfeac606f03d0c45cb8264a2ad1b6e78076b09c7 100644 (file)
@@ -16,7 +16,6 @@
  */
 
 use hair::*;
-use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 
 use rustc::middle::const_val::ConstVal;
@@ -29,7 +28,7 @@
 use rustc::infer::InferCtxt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-use syntax::parse::token;
+use syntax::symbol::{Symbol, InternedString};
 use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
 
@@ -121,7 +120,7 @@ pub fn unit_ty(&mut self) -> Ty<'tcx> {
         self.tcx.mk_nil()
     }
 
-    pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> {
+    pub fn str_literal(&mut self, value: InternedString) -> Literal<'tcx> {
         Literal::Value { value: ConstVal::Str(value) }
     }
 
@@ -145,7 +144,7 @@ pub fn trait_method(&mut self,
                         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 {
index e211334e5473ae5e43616916de6a189dc64f724e..50eee7723964e0cc18b346b9ba12e6420eb518dd 100644 (file)
@@ -202,6 +202,7 @@ pub enum ExprKind<'tcx> {
     },
     Break {
         label: Option<CodeExtent>,
+        value: Option<ExprRef<'tcx>>,
     },
     Continue {
         label: Option<CodeExtent>,
index aa56daf88894483d48e6768689d0115b1f66faf8..62e405564dbb72b10a444302bc59d8284f5fb6e6 100644 (file)
@@ -23,6 +23,7 @@
 #![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)]
index 828efbf373131d9e005e91177b88dce0c94ca075..a3916e7eca35104b8bbd246630ec45db25e85c06 100644 (file)
@@ -21,7 +21,8 @@
 use syntax::ast::*;
 use syntax::attr;
 use syntax::codemap::Spanned;
-use syntax::parse::token::{self, keywords};
+use syntax::parse::token;
+use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
 use errors;
@@ -39,7 +40,7 @@ fn check_label(&self, label: Ident, span: Span, id: NodeId) {
         if label.name == keywords::StaticLifetime.name() {
             self.err_handler().span_err(span, &format!("invalid label name `{}`", label.name));
         }
-        if label.name.as_str() == "'_" {
+        if label.name == "'_" {
             self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE,
                                   id,
                                   span,
@@ -89,7 +90,7 @@ fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
 
 impl<'a> Visitor for AstValidator<'a> {
     fn visit_lifetime(&mut self, lt: &Lifetime) {
-        if lt.name.as_str() == "'_" {
+        if lt.name == "'_" {
             self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE,
                                   lt.id,
                                   lt.span,
@@ -105,7 +106,7 @@ fn visit_expr(&mut self, expr: &Expr) {
             ExprKind::Loop(_, Some(ident)) |
             ExprKind::WhileLet(.., Some(ident)) |
             ExprKind::ForLoop(.., Some(ident)) |
-            ExprKind::Break(Some(ident)) |
+            ExprKind::Break(Some(ident), _) |
             ExprKind::Continue(Some(ident)) => {
                 self.check_label(ident.node, ident.span, expr.id);
             }
@@ -206,6 +207,13 @@ fn visit_item(&mut self, item: &Item) {
             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() {
index 5df8accd8cef13d024cf039be3a2b176e578c785..4d8520ed0440a1259fc0124ad9160bf27c2da03b 100644 (file)
@@ -610,7 +610,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprLoop(..) |
 
         // More control flow (also not very meaningful).
-        hir::ExprBreak(_) |
+        hir::ExprBreak(..) |
         hir::ExprAgain(_) |
         hir::ExprRet(_) |
 
index 89b8aa81411b381ed7b1de79470440acb81e2be0..b2ef1abd2a4e78eca2c7f6ad44737a4538bfefff 100644 (file)
@@ -228,4 +228,5 @@ pub fn foo() {}
 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
 }
index 3bdaf276b40cef489bc43a4514b63f07847186e6..dafb7bc6e60996d67482cb982f4e83b19071e9cf 100644 (file)
@@ -240,7 +240,7 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) {
         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);
index 724100e02237f74304c0f79ab1188df519e37b58..c909e75afc1f579c5328a528266d3dbd035005e3 100644 (file)
 use rustc::session::Session;
 
 use rustc::dep_graph::DepNode;
+use rustc::hir::def::{Def, DefMap};
 use rustc::hir::map::Map;
 use rustc::hir::intravisit::{self, Visitor};
 use rustc::hir;
 use syntax_pos::Span;
 
+#[derive(Clone, Copy, PartialEq)]
+enum LoopKind {
+    Loop(hir::LoopSource),
+    WhileLoop,
+}
+
+impl LoopKind {
+    fn name(self) -> &'static str {
+        match self {
+            LoopKind::Loop(hir::LoopSource::Loop) => "loop",
+            LoopKind::Loop(hir::LoopSource::WhileLet) => "while let",
+            LoopKind::Loop(hir::LoopSource::ForLoop) => "for",
+            LoopKind::WhileLoop => "while",
+        }
+    }
+}
+
 #[derive(Clone, Copy, PartialEq)]
 enum Context {
     Normal,
-    Loop,
+    Loop(LoopKind),
     Closure,
 }
 
 #[derive(Copy, Clone)]
-struct CheckLoopVisitor<'a> {
+struct CheckLoopVisitor<'a, 'ast: 'a> {
     sess: &'a Session,
+    def_map: &'a DefMap,
+    hir_map: &'a Map<'ast>,
     cx: Context,
 }
 
-pub fn check_crate(sess: &Session, map: &Map) {
+pub fn check_crate(sess: &Session, def_map: &DefMap, map: &Map) {
     let _task = map.dep_graph.in_task(DepNode::CheckLoops);
     let krate = map.krate();
     krate.visit_all_item_likes(&mut CheckLoopVisitor {
         sess: sess,
+        def_map: def_map,
+        hir_map: map,
         cx: Normal,
     }.as_deep_visitor());
 }
 
-impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
+impl<'a, 'ast, 'v> Visitor<'v> for CheckLoopVisitor<'a, 'ast> {
     fn visit_item(&mut self, i: &hir::Item) {
         self.with_context(Normal, |v| intravisit::walk_item(v, i));
     }
@@ -51,25 +73,62 @@ fn visit_impl_item(&mut self, i: &hir::ImplItem) {
     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;
@@ -79,7 +138,7 @@ fn with_context<F>(&mut self, cx: Context, f: F)
 
     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"))
index 4438241999a3940e4f6c289d0032f0bb473569fc..1bfc445fca98d72ca4f7c8f03a92b63dda875fc1 100644 (file)
@@ -69,9 +69,9 @@ pub fn load_plugins(sess: &Session,
             for plugin in plugins {
                 // plugins must have a name and can't be key = value
                 match plugin.name() {
-                    Some(ref name) if !plugin.is_value_str() => {
+                    Some(name) if !plugin.is_value_str() => {
                         let args = plugin.meta_item_list().map(ToOwned::to_owned);
-                        loader.load_plugin(plugin.span, name, args.unwrap_or_default());
+                        loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default());
                     },
                     _ => call_malformed_plugin_attribute(sess, attr.span),
                 }
index 88e248e2efa3878eb90eefbd90cc2f68ae7ac227..fe2f9713d1beb29ae0cafd35af921d9fb1711572 100644 (file)
@@ -17,7 +17,7 @@
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
 use syntax::ext::base::MacroExpanderFn;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax::ast;
 use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
@@ -101,7 +101,7 @@ pub fn args<'b>(&'b self) -> &'b [ast::NestedMetaItem] {
     ///
     /// This is the most general hook into `libsyntax`'s expansion behavior.
     pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
-        if name.as_str() == "macro_rules" {
+        if name == "macro_rules" {
             panic!("user-defined macros may not be named `macro_rules`");
         }
         self.syntax_exts.push((name, match extension {
@@ -121,7 +121,7 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
     /// 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));
     }
 
index 627c72ff8c92572c9169f57423c7eca9387c4fbc..ff2f25a12fc8607874a99d4c945a6a59eb38233e 100644 (file)
@@ -31,7 +31,6 @@
 
 use syntax::ast::Name;
 use syntax::attr;
-use syntax::parse::token;
 
 use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind};
 use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind};
@@ -41,7 +40,7 @@
 use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
-use syntax::parse::token::keywords;
+use syntax::symbol::keywords;
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -139,7 +138,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 match view_path.node {
                     ViewPathSimple(binding, ref full_path) => {
                         let mut source = full_path.segments.last().unwrap().identifier;
-                        let source_name = source.name.as_str();
+                        let source_name = source.name;
                         if source_name == "mod" || source_name == "self" {
                             resolve_error(self,
                                           view_path.span,
@@ -582,7 +581,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'b>, expa
             });
         } else {
             for (name, span) in legacy_imports.imports {
-                let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
+                let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
                 if let Success(binding) = result {
                     self.legacy_import_macro(name, binding, span, allow_shadowing);
                 } else {
@@ -592,7 +591,7 @@ fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'b>, expa
         }
         for (name, span) in legacy_imports.reexports {
             self.used_crates.insert(module.def_id().unwrap().krate);
-            let result = self.resolve_name_in_module(module, name, MacroNS, false, false, None);
+            let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
             if let Success(binding) = result {
                 self.macro_exports.push(Export { name: name, def: binding.def() });
             } else {
@@ -607,7 +606,7 @@ fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
             if attr.check_name("macro_escape") {
                 let msg = "macro_escape is a deprecated synonym for macro_use";
                 let mut err = self.session.struct_span_warn(attr.span, msg);
-                if let ast::AttrStyle::Inner = attr.node.style {
+                if let ast::AttrStyle::Inner = attr.style {
                     err.help("consider an outer attribute, #[macro_use] mod ...").emit();
                 } else {
                     err.emit();
@@ -632,7 +631,7 @@ fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImpor
                 match attr.meta_item_list() {
                     Some(names) => for attr in names {
                         if let Some(word) = attr.word() {
-                            imports.imports.push((token::intern(&word.name()), attr.span()));
+                            imports.imports.push((word.name(), attr.span()));
                         } else {
                             span_err!(self.session, attr.span(), E0466, "bad macro import");
                         }
@@ -646,7 +645,7 @@ fn legacy_macro_imports(&mut self, attrs: &[ast::Attribute]) -> LegacyMacroImpor
                 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());
                         }
index 5eb269030a004fa2b1ce8b2d43ee9809cf027321..d54f4e7b20c7a709fe2972823ee177c23dfc1f2d 100644 (file)
@@ -59,7 +59,7 @@ fn f() {
 
 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
 
index a3a60e4f6d7548abe5d2f6787ba0bab13437a381..ab3d361a940f9ed9dba097742ff07302db613b76 100644 (file)
@@ -57,7 +57,7 @@
 use syntax::ast::{self, FloatTy};
 use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
-use syntax::parse::token::{self, keywords};
+use syntax::symbol::{Symbol, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 
 use syntax::visit::{self, FnKind, Visitor};
@@ -90,7 +90,7 @@
 
 enum SuggestionType {
     Macro(String),
-    Function(token::InternedString),
+    Function(Symbol),
     NotFound,
 }
 
@@ -1039,7 +1039,7 @@ fn new() -> PrimitiveTypeTable {
     }
 
     fn intern(&mut self, string: &str, primitive_type: PrimTy) {
-        self.primitive_types.insert(token::intern(string), primitive_type);
+        self.primitive_types.insert(Symbol::intern(string), primitive_type);
     }
 }
 
@@ -1131,7 +1131,6 @@ pub struct Resolver<'a> {
 
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
-    new_import_semantics: bool, // true if `#![feature(item_like_imports)]`
     use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
 
     pub exported_macros: Vec<ast::MacroDef>,
@@ -1333,7 +1332,6 @@ pub fn new(session: &'a Session,
                 span: DUMMY_SP,
                 vis: ty::Visibility::Public,
             }),
-            new_import_semantics: session.features.borrow().item_like_imports,
             use_extern_macros: session.features.borrow().use_extern_macros,
 
             exported_macros: Vec::new(),
@@ -1442,7 +1440,7 @@ fn resolve_module_path_from_root(&mut self,
                                      -> 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)
@@ -1460,9 +1458,8 @@ fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Mo
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index].name;
-            match self.resolve_name_in_module(search_module, name, TypeNS, false, false, span) {
+            match self.resolve_name_in_module(search_module, name, TypeNS, false, span) {
                 Failed(_) => {
-                    let segment_name = name.as_str();
                     let module_name = module_to_string(search_module);
                     let msg = if "???" == &module_name {
                         let current_module = self.current_module;
@@ -1480,10 +1477,10 @@ fn search_parent_externals<'a>(this: &mut Resolver<'a>, needle: Name, module: Mo
 
                                 format!("Did you mean `{}{}`?", prefix, path_str)
                             }
-                            None => format!("Maybe a missing `extern crate {};`?", segment_name),
+                            None => format!("Maybe a missing `extern crate {};`?", name),
                         }
                     } else {
-                        format!("Could not find `{}` in `{}`", segment_name, module_name)
+                        format!("Could not find `{}` in `{}`", name, module_name)
                     };
 
                     return Failed(span.map(|span| (span, msg)));
@@ -1617,7 +1614,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
 
             if let ModuleRibKind(module) = self.ribs[ns][i].kind {
                 let name = ident.name;
-                let item = self.resolve_name_in_module(module, name, ns, true, false, record_used);
+                let item = self.resolve_name_in_module(module, name, ns, false, record_used);
                 if let Success(binding) = item {
                     // The ident resolves to an item.
                     return Some(LexicalScopeBinding::Item(binding));
@@ -1626,7 +1623,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
                 if let ModuleKind::Block(..) = module.kind { // We can see through blocks
                 } else if !module.no_implicit_prelude {
                     return self.prelude.and_then(|prelude| {
-                        self.resolve_name_in_module(prelude, name, ns, false, false, None).success()
+                        self.resolve_name_in_module(prelude, name, ns, false, None).success()
                     }).map(LexicalScopeBinding::Item)
                 } else {
                     return None;
@@ -1651,7 +1648,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
     /// 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));
         }
 
@@ -1667,7 +1664,7 @@ fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option<Span>)
             self.module_map[&self.current_module.normal_ancestor_id.unwrap()];
 
         // Now loop through all the `super`s we find.
-        while i < module_path.len() && "super" == module_path[i].name.as_str() {
+        while i < module_path.len() && module_path[i].name == "super" {
             debug!("(resolving module prefix) resolving `super` at {}",
                    module_to_string(&containing_module));
             if let Some(parent) = containing_module.parent {
@@ -2635,7 +2632,7 @@ fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace
         let qualified_binding = self.resolve_module_relative_path(span, segments, namespace);
         match (qualified_binding, unqualified_def) {
             (Ok(binding), Some(ref ud)) if binding.def() == ud.def &&
-                                           segments[0].identifier.name.as_str() != "$crate" => {
+                                           segments[0].identifier.name != "$crate" => {
                 self.session
                     .add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
                               id,
@@ -2772,7 +2769,7 @@ fn resolve_module_relative_path(&mut self,
         };
 
         let name = segments.last().unwrap().identifier.name;
-        let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
+        let result = self.resolve_name_in_module(module, name, namespace, false, Some(span));
         result.success().ok_or(false)
     }
 
@@ -2800,7 +2797,7 @@ fn resolve_crate_relative_path<T>(&mut self, span: Span, segments: &[T], namespa
         };
 
         let name = segments.last().unwrap().ident().name;
-        let result = self.resolve_name_in_module(module, name, namespace, false, false, Some(span));
+        let result = self.resolve_name_in_module(module, name, namespace, false, Some(span));
         result.success().ok_or(false)
     }
 
@@ -2881,7 +2878,7 @@ fn extract_node_id(t: &Ty) -> Option<NodeId> {
     }
 
     fn find_best_match(&mut self, name: &str) -> SuggestionType {
-        if let Some(macro_name) = self.macro_names.iter().find(|n| n.as_str() == name) {
+        if let Some(macro_name) = self.macro_names.iter().find(|&n| n == &name) {
             return SuggestionType::Macro(format!("{}!", macro_name));
         }
 
@@ -2891,7 +2888,7 @@ fn find_best_match(&mut self, name: &str) -> SuggestionType {
                     .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name));
 
         if let Some(found) = find_best_match_for_name(names, name, None) {
-            if name != found {
+            if found != name {
                 return SuggestionType::Function(found);
             }
         } SuggestionType::NotFound
@@ -3000,8 +2997,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                                 false // Stop advancing
                             });
 
-                            if method_scope &&
-                                    &path_name[..] == keywords::SelfValue.name().as_str() {
+                            if method_scope && keywords::SelfValue.name() == &*path_name {
                                 resolve_error(self,
                                               expr.span,
                                               ResolutionError::SelfNotAvailableInStaticMethod);
@@ -3078,22 +3074,25 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 visit::walk_expr(self, expr);
             }
 
-            ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => {
+            ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
                 match self.search_label(label.node) {
                     None => {
                         self.record_def(expr.id, err_path_resolution());
                         resolve_error(self,
                                       label.span,
-                                      ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
+                                      ResolutionError::UndeclaredLabel(&label.node.name.as_str()));
                     }
                     Some(def @ Def::Label(_)) => {
                         // Since this def is a label, it is never read.
-                        self.record_def(expr.id, PathResolution::new(def))
+                        self.record_def(expr.id, PathResolution::new(def));
                     }
                     Some(_) => {
-                        span_bug!(expr.span, "label wasn't mapped to a label def!")
+                        span_bug!(expr.span, "label wasn't mapped to a label def!");
                     }
                 }
+
+                // visit `break` argument if any
+                visit::walk_expr(self, expr);
             }
 
             ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
@@ -3606,7 +3605,7 @@ fn collect_mod(names: &mut Vec<Ident>, module: Module) {
             }
         } 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());
         }
     }
index 524d491a464e2525e178cb531e830edd5befa535..62adf382a69add955ddddc8125e83a7785f9124f 100644 (file)
@@ -27,7 +27,6 @@
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::fold::Folder;
-use syntax::parse::token::intern;
 use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::Visitor;
@@ -116,7 +115,7 @@ fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
         impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
             fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
                 let ident = path.segments[0].identifier;
-                if &ident.name.as_str() == "$crate" {
+                if ident.name == "$crate" {
                     path.global = true;
                     let module = self.0.resolve_crate_var(ident.ctxt);
                     if module.is_local() {
@@ -152,7 +151,7 @@ fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
     }
 
     fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) {
-        if &def.ident.name.as_str() == "macro_rules" {
+        if def.ident.name == "macro_rules" {
             self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
         }
 
@@ -207,8 +206,7 @@ fn resolve_imports(&mut self) {
 
     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))
@@ -272,7 +270,7 @@ fn resolve_in_item_lexical_scope(&mut self,
         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,
index d0ce1acaadf62128434b5b2f2469f981eec80977..47bd1f71084aa3ae24b494b2fd42ffe8cc856b3d 100644 (file)
@@ -75,7 +75,6 @@ pub struct NameResolution<'a> {
     single_imports: SingleImports<'a>,
     /// The least shadowable known binding for this name, or None if there are no known bindings.
     pub binding: Option<&'a NameBinding<'a>>,
-    duplicate_globs: Vec<&'a NameBinding<'a>>,
 }
 
 #[derive(Clone, Debug)]
@@ -141,7 +140,6 @@ pub fn resolve_name_in_module(&mut self,
                                   module: Module<'a>,
                                   name: Name,
                                   ns: Namespace,
-                                  allow_private_imports: bool,
                                   ignore_unresolved_invocations: bool,
                                   record_used: Option<Span>)
                                   -> ResolveResult<&'a NameBinding<'a>> {
@@ -153,18 +151,8 @@ pub fn resolve_name_in_module(&mut self,
             _ => return Failed(None), // This happens when there is a cycle of imports
         };
 
-        let new_import_semantics = self.new_import_semantics;
-        let is_disallowed_private_import = |binding: &NameBinding| {
-            !new_import_semantics && !allow_private_imports && // disallowed
-            binding.vis != ty::Visibility::Public && binding.is_import() && // non-`pub` import
-            !binding.is_extern_crate() // not an `extern crate`
-        };
-
         if let Some(span) = record_used {
             if let Some(binding) = resolution.binding {
-                if is_disallowed_private_import(binding) {
-                    return Failed(None);
-                }
                 if self.record_use(name, ns, binding, span) {
                     return Success(self.dummy_binding);
                 }
@@ -177,9 +165,8 @@ pub fn resolve_name_in_module(&mut self,
         }
 
         let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
-            let usable =
-                this.is_accessible(binding.vis) && !is_disallowed_private_import(binding) ||
-                binding.is_extern_crate(); // c.f. issue #37020
+            // `extern crate` are always usable for backwards compatability, see issue #37020.
+            let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
             if usable { Success(binding) } else { Failed(None) }
         };
 
@@ -202,7 +189,7 @@ pub fn resolve_name_in_module(&mut self,
                     SingleImport { source, .. } => source,
                     _ => unreachable!(),
                 };
-                match self.resolve_name_in_module(module, name, ns, true, false, None) {
+                match self.resolve_name_in_module(module, name, ns, false, None) {
                     Failed(_) => {}
                     _ => return Indeterminate,
                 }
@@ -224,7 +211,7 @@ pub fn resolve_name_in_module(&mut self,
         for directive in module.globs.borrow().iter() {
             if self.is_accessible(directive.vis.get()) {
                 if let Some(module) = directive.imported_module.get() {
-                    let result = self.resolve_name_in_module(module, name, ns, true, false, None);
+                    let result = self.resolve_name_in_module(module, name, ns, false, None);
                     if let Indeterminate = result {
                         return Indeterminate;
                     }
@@ -311,10 +298,8 @@ pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, b
         self.update_resolution(module, name, ns, |this, resolution| {
             if let Some(old_binding) = resolution.binding {
                 if binding.is_glob_import() {
-                    if !this.new_import_semantics {
-                        resolution.duplicate_globs.push(binding);
-                    } else if !old_binding.is_glob_import() &&
-                              !(ns == MacroNS && old_binding.expansion != Mark::root()) {
+                    if !old_binding.is_glob_import() &&
+                       !(ns == MacroNS && old_binding.expansion != Mark::root()) {
                     } else if binding.def() != old_binding.def() {
                         resolution.binding = Some(this.ambiguity(old_binding, binding));
                     } else if !old_binding.vis.is_at_least(binding.vis, this) {
@@ -322,11 +307,8 @@ pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, b
                         resolution.binding = Some(binding);
                     }
                 } else if old_binding.is_glob_import() {
-                    if !this.new_import_semantics {
-                        resolution.duplicate_globs.push(old_binding);
-                        resolution.binding = Some(binding);
-                    } else if ns == MacroNS && binding.expansion != Mark::root() &&
-                              binding.def() != old_binding.def() {
+                    if ns == MacroNS && binding.expansion != Mark::root() &&
+                       binding.def() != old_binding.def() {
                         resolution.binding = Some(this.ambiguity(binding, old_binding));
                     } else {
                         resolution.binding = Some(binding);
@@ -366,7 +348,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
             let t = f(self, resolution);
 
             match resolution.binding() {
-                _ if !self.new_import_semantics && old_binding.is_some() => return t,
+                _ if old_binding.is_some() => return t,
                 None => return t,
                 Some(binding) => match old_binding {
                     Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
@@ -377,10 +359,7 @@ fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namesp
 
         // Define `binding` in `module`s glob importers.
         for directive in module.glob_importers.borrow_mut().iter() {
-            if match self.new_import_semantics {
-                true => self.is_accessible_from(binding.vis, directive.parent),
-                false => binding.vis == ty::Visibility::Public,
-            } {
+            if self.is_accessible_from(binding.vis, directive.parent) {
                 let imported_binding = self.import(binding, directive);
                 let _ = self.try_define(directive.parent, name, ns, imported_binding);
             }
@@ -528,7 +507,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
         self.per_ns(|this, ns| {
             if let Err(Undetermined) = result[ns].get() {
                 result[ns].set({
-                    match this.resolve_name_in_module(module, source, ns, false, false, None) {
+                    match this.resolve_name_in_module(module, source, ns, false, None) {
                         Success(binding) => Ok(binding),
                         Indeterminate => Err(Undetermined),
                         Failed(_) => Err(Determined),
@@ -624,7 +603,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResu
         if all_ns_err {
             let mut all_ns_failed = true;
             self.per_ns(|this, ns| {
-                match this.resolve_name_in_module(module, name, ns, false, false, Some(span)) {
+                match this.resolve_name_in_module(module, name, ns, false, Some(span)) {
                     Success(_) => all_ns_failed = false,
                     _ => {}
                 }
@@ -729,8 +708,7 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
             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);
             }
@@ -761,20 +739,6 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
                 None => continue,
             };
 
-            // Report conflicts
-            if !self.new_import_semantics {
-                for duplicate_glob in resolution.duplicate_globs.iter() {
-                    // FIXME #31337: We currently allow items to shadow glob-imported re-exports.
-                    if !binding.is_import() {
-                        if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind {
-                            if binding.is_import() { continue }
-                        }
-                    }
-
-                    self.report_conflict(module, name, ns, duplicate_glob, binding);
-                }
-            }
-
             if binding.vis == ty::Visibility::Public &&
                (binding.is_import() || binding.is_extern_crate()) {
                 let def = binding.def();
index e83c2359979c057466fec319fcdd533094343eb3..53b05051deb6e78a6f2f85c2acb01b1815e92a00 100644 (file)
@@ -39,7 +39,8 @@
 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;
@@ -275,7 +276,7 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
     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()),
             }
         })
@@ -357,7 +358,10 @@ fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str) {
             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);
@@ -987,7 +991,13 @@ fn process_pat(&mut self, p: &ast::Pat) {
         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 {
@@ -1353,7 +1363,13 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
             }
             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)
             }
@@ -1379,7 +1395,13 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                         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);
index 778f0184141651061552c44dbe7e0d655d84962f..3c6f67f0c88e1837a3767534bd88cbab11e4e6d7 100644 (file)
@@ -54,7 +54,8 @@
 
 use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
 use syntax::parse::lexer::comments::strip_doc_comment_decoration;
-use syntax::parse::token::{self, keywords, InternedString};
+use syntax::parse::token;
+use syntax::symbol::{Symbol, keywords};
 use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{ty_to_string, arg_to_string};
 use syntax::codemap::MacroAttribute;
@@ -119,7 +120,7 @@ pub fn get_external_crates(&self) -> Vec<CrateData> {
                 }
             };
             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,
             });
@@ -497,7 +498,12 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
     }
 
     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 {
@@ -728,16 +734,16 @@ fn visit_pat(&mut self, p: &ast::Pat) {
 }
 
 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');
             }
index 9ec764b82f869bf1c9c90795b717dd8303e9a024..e06aefd865f1ba6486c1dadf5ab4bb10081f0f84 100644 (file)
@@ -18,7 +18,8 @@
 
 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)]
index 38f9e7ab0c51cce9537b5e3822487ef1d84cc86a..796a80d0809441044c6d7ecf9c455166560da55e 100644 (file)
@@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" }
 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" }
index cb06fac2c674e22ca4c21c0f6007c2bb00398e51..07f53466b4975e1769fc0a01beacfd5c0c9caff6 100644 (file)
@@ -8,7 +8,7 @@
 // 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};
@@ -50,6 +50,93 @@ enum ArgKind {
     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
 ///
@@ -81,7 +168,7 @@ pub struct ArgType {
     /// 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 {
@@ -93,7 +180,7 @@ fn new(original_ty: Type, ty: Type) -> ArgType {
             signedness: None,
             cast: None,
             pad: None,
-            attrs: llvm::Attributes::default()
+            attrs: ArgAttributes::default()
         }
     }
 
@@ -101,15 +188,15 @@ pub fn make_indirect(&mut self, ccx: &CrateContext) {
         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;
@@ -125,9 +212,9 @@ pub fn extend_integer_width_to(&mut self, bits: u64) {
         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
                 });
             }
         }
@@ -315,7 +402,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             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),
@@ -350,7 +437,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             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
@@ -372,7 +459,7 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         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)
             }
 
@@ -387,18 +474,18 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 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)
@@ -418,9 +505,9 @@ pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 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);
@@ -491,7 +578,7 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
                 fixup(arg);
             }
             if self.ret.is_indirect() {
-                self.ret.attrs.set(llvm::Attribute::StructRet);
+                self.ret.attrs.set(ArgAttribute::StructRet);
             }
             return;
         }
@@ -526,7 +613,7 @@ pub fn adjust_for_abi<'a, 'tcx>(&mut self,
         }
 
         if self.ret.is_indirect() {
-            self.ret.attrs.set(llvm::Attribute::StructRet);
+            self.ret.attrs.set(ArgAttribute::StructRet);
         }
     }
 
index c3340281d073254a08a9420dc5e34df0191e23cd..e091ba07d4feaffd7f76dae85eedb3934f8e362c 100644 (file)
@@ -247,6 +247,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // 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);
index 8c704cc32993c4e170c5c4c0664cfdb93ee88363..665e12cbe87955e624cfeb2ef7e5b03e297718db 100644 (file)
@@ -88,7 +88,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         AsmDialect::Intel => llvm::AsmDialect::Intel,
     };
 
-    let asm = CString::new(ia.asm.as_bytes()).unwrap();
+    let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
     let constraint_cstr = CString::new(all_constraints).unwrap();
     let r = InlineAsmCall(bcx,
                           asm.as_ptr(),
index 264ed4cd12fc1a419cbad0b13d6500559cfc992e..898e65ce391e609dd295dc29971a85cb09075f42 100644 (file)
@@ -29,7 +29,6 @@
 
 use rustc::ty::TyCtxt;
 use syntax::ast;
-use syntax::parse::token::InternedString;
 
 use {ModuleSource, ModuleTranslation};
 
@@ -77,7 +76,7 @@ fn check_attr(&self, attr: &ast::Attribute) {
         }
 
         let mname = self.field(attr, MODULE);
-        let mtrans = self.modules.iter().find(|mtrans| &mtrans.name[..] == &mname[..]);
+        let mtrans = self.modules.iter().find(|mtrans| *mtrans.name == *mname.as_str());
         let mtrans = match mtrans {
             Some(m) => m,
             None => {
@@ -113,7 +112,7 @@ fn disposition(&self, mtrans: &ModuleTranslation) -> Disposition {
         }
     }
 
-    fn field(&self, attr: &ast::Attribute, name: &str) -> InternedString {
+    fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name {
         for item in attr.meta_item_list().unwrap_or(&[]) {
             if item.check_name(name) {
                 if let Some(value) = item.value_str() {
@@ -137,7 +136,7 @@ fn check_config(&self, attr: &ast::Attribute) -> bool {
         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;
         }
index 62eac35e0abd9766d64b7b471c6cf2022e15e182..f1e90419a49e2070508781b2f55821458598f295 100644 (file)
@@ -24,10 +24,9 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
         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);
         },
     };
 }
index df8dd7750ae0ca69a7bffb994c91be56acf36097..11ab6dcaa87f99fa02a99fac8d9068d8c462d2c1 100644 (file)
@@ -231,7 +231,7 @@ pub fn build(&mut self) {
     }
 
     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)
     }
 
index 95d63311ee6e47aade6099c70b2d95d1e96adce0..648dc4c24c9a658c79426f2b53d2f5c707ca7f6a 100644 (file)
@@ -19,7 +19,7 @@
 use session::filesearch;
 use session::search_paths::PathKind;
 use session::Session;
-use middle::cstore::{self, LinkMeta, NativeLibrary};
+use middle::cstore::{self, LinkMeta, NativeLibrary, LibSource};
 use middle::cstore::{LinkagePreference, NativeLibraryKind};
 use middle::dependency_format::Linkage;
 use CrateTranslation;
@@ -44,6 +44,7 @@
 use flate;
 use syntax::ast;
 use syntax::attr;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 // RLIB LLVM-BYTECODE OBJECT LAYOUT
@@ -93,8 +94,8 @@ pub fn find_crate_name(sess: Option<&Session>,
 
     if let Some(sess) = sess {
         if let Some(ref s) = sess.opts.crate_name {
-            if let Some((attr, ref name)) = attr_crate_name {
-                if *s != &name[..] {
+            if let Some((attr, name)) = attr_crate_name {
+                if name != &**s {
                     let msg = format!("--crate-name and #[crate_name] are \
                                        required to match, but `{}` != `{}`",
                                       s, name);
@@ -123,14 +124,13 @@ pub fn find_crate_name(sess: Option<&Session>,
     }
 
     "rust_out".to_string()
-
 }
 
 pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap,
                        name: &str)
                        -> LinkMeta {
     let r = LinkMeta {
-        crate_name: name.to_owned(),
+        crate_name: Symbol::intern(name),
         crate_hash: Svh::new(incremental_hashes_map[&DepNode::Krate].to_smaller_hash()),
     };
     info!("{:?}", r);
@@ -263,6 +263,9 @@ pub fn filename_for_input(sess: &Session,
         config::CrateTypeRlib => {
             outputs.out_directory.join(&format!("lib{}.rlib", libname))
         }
+        config::CrateTypeMetadata => {
+            outputs.out_directory.join(&format!("lib{}.rmeta", libname))
+        }
         config::CrateTypeCdylib |
         config::CrateTypeProcMacro |
         config::CrateTypeDylib => {
@@ -298,7 +301,7 @@ pub fn each_linked_rlib(sess: &Session,
                    .or_else(|| fmts.get(&config::CrateTypeCdylib))
                    .or_else(|| fmts.get(&config::CrateTypeProcMacro));
     let fmts = fmts.unwrap_or_else(|| {
-        bug!("could not find formats for rlibs")
+        bug!("could not find formats for rlibs");
     });
     for (cnum, path) in crates {
         match fmts[cnum.as_usize() - 1] {
@@ -307,8 +310,12 @@ pub fn each_linked_rlib(sess: &Session,
         }
         let name = sess.cstore.crate_name(cnum).clone();
         let path = match path {
-            Some(p) => p,
-            None => {
+            LibSource::Some(p) => p,
+            LibSource::MetadataOnly => {
+                sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file",
+                                    name));
+            }
+            LibSource::None => {
                 sess.fatal(&format!("could not find rlib for: `{}`", name));
             }
         };
@@ -352,6 +359,9 @@ fn link_binary_output(sess: &Session,
         config::CrateTypeStaticlib => {
             link_staticlib(sess, &objects, &out_filename, tmpdir.path());
         }
+        config::CrateTypeMetadata => {
+            emit_metadata(sess, trans, &out_filename);
+        }
         _ => {
             link_natively(sess, crate_type, &objects, &out_filename, trans,
                           outputs, tmpdir.path());
@@ -390,6 +400,13 @@ fn archive_config<'a>(sess: &'a Session,
     }
 }
 
+fn emit_metadata<'a>(sess: &'a Session, trans: &CrateTranslation, out_filename: &Path) {
+    let result = fs::File::create(out_filename).and_then(|mut f| f.write_all(&trans.metadata));
+    if let Err(e) = result {
+        sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
+    }
+}
+
 // Create an 'rlib'
 //
 // An rlib in its current incarnation is essentially a renamed .a file. The
@@ -403,6 +420,7 @@ fn link_rlib<'a>(sess: &'a Session,
                  tmpdir: &Path) -> ArchiveBuilder<'a> {
     info!("preparing rlib from {:?} to {:?}", objects, out_filename);
     let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None));
+
     for obj in objects {
         ab.add_file(obj);
     }
@@ -429,7 +447,7 @@ fn link_rlib<'a>(sess: &'a Session,
             NativeLibraryKind::NativeFramework |
             NativeLibraryKind::NativeUnknown => continue,
         }
-        ab.add_native_library(&lib.name);
+        ab.add_native_library(&lib.name.as_str());
     }
 
     // After adding all files to the archive, we need to update the
@@ -464,15 +482,7 @@ fn link_rlib<'a>(sess: &'a Session,
             // here so concurrent builds in the same directory don't try to use
             // the same filename for metadata (stomping over one another)
             let metadata = tmpdir.join(sess.cstore.metadata_filename());
-            match fs::File::create(&metadata).and_then(|mut f| {
-                f.write_all(&trans.metadata)
-            }) {
-                Ok(..) => {}
-                Err(e) => {
-                    sess.fatal(&format!("failed to write {}: {}",
-                                        metadata.display(), e));
-                }
-            }
+            emit_metadata(sess, trans, &metadata);
             ab.add_file(&metadata);
 
             // For LTO purposes, the bytecode of this library is also inserted
@@ -615,7 +625,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path,
         let skip_object_files = native_libs.iter().any(|lib| {
             lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
         });
-        ab.add_rlib(path, &name, sess.lto(), skip_object_files).unwrap();
+        ab.add_rlib(path, &name.as_str(), sess.lto(), skip_object_files).unwrap();
 
         all_native_libs.extend(sess.cstore.native_libraries(cnum));
     });
@@ -934,15 +944,15 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
         // don't otherwise explicitly reference them. This can occur for
         // libraries which are just providing bindings, libraries with generic
         // functions, etc.
-        cmd.link_whole_staticlib(&l.name, &search_path);
+        cmd.link_whole_staticlib(&l.name.as_str(), &search_path);
     }
 
     cmd.hint_dynamic();
 
     for lib in others {
         match lib.kind {
-            NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name),
-            NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name),
+            NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
+            NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
             NativeLibraryKind::NativeStatic => bug!(),
         }
     }
@@ -1185,8 +1195,8 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
                 continue
             }
             match lib.kind {
-                NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name),
-                NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name),
+                NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
+                NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
 
                 // ignore statically included native libraries here as we've
                 // already included them when we included the rust library
index 8758cdcf9d0ab63928ef1100381060561773bb1f..ccaa0d4e1b1b059de8214d48454ea049d7897eac 100644 (file)
 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,
@@ -35,7 +36,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
     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[..]));
 
index 0ad663f05b48b12c577810baff255a011bebeaf0..ff40cfda5ff7cb7a865622a3f8c6c69431e068c9 100644 (file)
 use rustc::util::common::record_time;
 
 use syntax::attr;
-use syntax::parse::token::{self, InternedString};
+use syntax::symbol::{Symbol, InternedString};
 
 fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 
@@ -275,7 +275,7 @@ fn root_mode(&self) -> &RootMode {
     }
 
     fn push(&mut self, text: &str) {
-        self.names.push(token::intern(text).as_str());
+        self.names.push(Symbol::intern(text).as_str());
     }
 }
 
@@ -288,7 +288,7 @@ pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a,
         krate: LOCAL_CRATE,
     };
     let hash = get_symbol_hash(scx, &empty_def_path, t, None);
-    let path = [token::intern_and_get_ident(prefix)];
+    let path = [Symbol::intern(prefix).as_str()];
     mangle(path.iter().cloned(), &hash)
 }
 
index 0c0b7fbf4afeab483d41a26f8697cfc352741945..d697a5bafb79ed5a6d9503fb88269c5fdb6fabab 100644 (file)
@@ -47,7 +47,7 @@
 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;
@@ -93,6 +93,7 @@
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::attr;
 use rustc::hir;
+use rustc::ty::layout::{self, Layout};
 use syntax::ast;
 
 thread_local! {
@@ -1128,11 +1129,11 @@ pub fn set_link_section(ccx: &CrateContext,
                         llval: ValueRef,
                         attrs: &[ast::Attribute]) {
     if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") {
-        if contains_null(&sect) {
+        if contains_null(&sect.as_str()) {
             ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", &sect));
         }
         unsafe {
-            let buf = CString::new(sect.as_bytes()).unwrap();
+            let buf = CString::new(sect.as_str().as_bytes()).unwrap();
             llvm::LLVMSetSection(llval, buf.as_ptr());
         }
     }
@@ -1260,7 +1261,8 @@ enum MetadataKind {
             config::CrateTypeStaticlib |
             config::CrateTypeCdylib => MetadataKind::None,
 
-            config::CrateTypeRlib => MetadataKind::Uncompressed,
+            config::CrateTypeRlib |
+            config::CrateTypeMetadata => MetadataKind::Uncompressed,
 
             config::CrateTypeDylib |
             config::CrateTypeProcMacro => MetadataKind::Compressed,
@@ -1600,7 +1602,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     assert_module_sources::assert_module_sources(tcx, &modules);
 
     // Skip crate items and just output metadata in -Z no-trans mode.
-    if tcx.sess.opts.debugging_opts.no_trans {
+    if tcx.sess.opts.debugging_opts.no_trans ||
+       tcx.sess.crate_types.borrow().iter().all(|ct| ct == &config::CrateTypeMetadata) {
         let linker_info = LinkerInfo::new(&shared_ccx, &[]);
         return CrateTranslation {
             modules: modules,
@@ -1739,6 +1742,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               .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);
@@ -1769,6 +1776,192 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+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,
index 3cbc378ab021619d9939395f53d928c719ae248a..f410627400c34ec4c2b1018d4188cdb3da48c941 100644 (file)
@@ -10,8 +10,8 @@
 
 #![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
@@ -39,7 +39,7 @@ fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
 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);
     }
 }
 
index b52231fa6b432f8aaca36d346d29368f2ea024c4..5377b49a2b441c8bf787e9627e686949cf9d9a21 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::*;
-use abi::FnType;
+use abi::{ArgAttribute, FnType};
 use type_::Type;
 use super::common::*;
 use super::machine::*;
@@ -45,7 +45,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
         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);
         }
index 33990148c8b7de13d4dbc1e4a39de610d9cd58f3..7f2fdbf000b651fd62acfab2cb256881e55375a5 100644 (file)
@@ -15,8 +15,8 @@
 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;
 
@@ -334,7 +334,7 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     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() {
@@ -384,7 +384,7 @@ fn x86_64_ty<F>(ccx: &CrateContext,
                 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
index 5902b0b1ce0755ec463354d90e634ef69fd4cc91..5c7b004375ed4b778aacf20c16d945633d061b8a 100644 (file)
@@ -663,7 +663,7 @@ fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 -> bool {
             (bare_fn_ty.abi == Abi::RustIntrinsic ||
              bare_fn_ty.abi == Abi::PlatformIntrinsic) &&
-            tcx.item_name(def_id).as_str() == "drop_in_place"
+            tcx.item_name(def_id) == "drop_in_place"
         }
     }
 }
index df70a6e81166b8113d9b4a0b15785c6a3b90a6d9..29925d964da253d4b7a26ae008b72575bbf920a1 100644 (file)
@@ -52,8 +52,7 @@
 use std::cell::{Cell, RefCell, Ref};
 
 use syntax::ast;
-use syntax::parse::token::InternedString;
-use syntax::parse::token;
+use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
 
 pub use context::{CrateContext, SharedCrateContext};
@@ -225,7 +224,7 @@ pub fn from_ty(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 VariantInfo {
                     discr: Disr(0),
                     fields: v.iter().enumerate().map(|(i, &t)| {
-                        Field(token::intern(&i.to_string()), t)
+                        Field(Symbol::intern(&i.to_string()), t)
                     }).collect()
                 }
             }
index 670a84565fafbc31f442a58a28ef17ef5b8c3bcb..4186721c122acdd839829c26b40c153f652e950b 100644 (file)
@@ -123,7 +123,7 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
                     // extern "C" fn() from being non-null, so we can't just declare a
                     // static and call it a day. Some linkages (like weak) will make it such
                     // that the static actually has a null value.
-                    let linkage = match base::llvm_linkage_by_name(&name) {
+                    let linkage = match base::llvm_linkage_by_name(&name.as_str()) {
                         Some(linkage) => linkage,
                         None => {
                             ccx.sess().span_fatal(span, "invalid linkage specified");
index 7657fc7d1c8b007cbdfdb14f130bfec6ca4f951a..771c5ef6d9d28c019b45bdecc93be31b3d8293ad 100644 (file)
@@ -42,7 +42,7 @@
 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 {
index 5b9ef78ddc22e86f0dd4abc5e112b74fa820415b..5d01ca892b316c4c9849cacafb0c79f84e0937f1 100644 (file)
 use std::fmt::Write;
 use std::path::Path;
 use std::ptr;
-use std::rc::Rc;
-use syntax::util::interner::Interner;
 use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::{Interner, InternedString};
 use syntax_pos::{self, Span};
 
 
@@ -117,9 +115,8 @@ fn register_unique_id_with_metadata(&mut self,
                                         unique_type_id: UniqueTypeId,
                                         metadata: DIType) {
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
-            let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
             bug!("Type metadata for unique id '{}' is already in the TypeMap!",
-                 &unique_type_id_str[..]);
+                 self.get_unique_type_id_as_string(unique_type_id));
         }
     }
 
@@ -133,7 +130,7 @@ fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DI
 
     // 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)
     }
@@ -182,7 +179,7 @@ fn get_unique_type_id_of_enum_variant<'a>(&mut self,
                                               -> UniqueTypeId {
         let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
         let enum_variant_type_id = format!("{}::{}",
-                                           &self.get_unique_type_id_as_string(enum_type_id),
+                                           self.get_unique_type_id_as_string(enum_type_id),
                                            variant_name);
         let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
         UniqueTypeId(interner_key)
@@ -623,14 +620,12 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
                 Some(metadata) => metadata,
                 None => {
-                    let unique_type_id_str =
-                        type_map.get_unique_type_id_as_string(unique_type_id);
                     span_bug!(usage_site_span,
                               "Expected type metadata for unique \
                                type id '{}' to already be in \
                                the debuginfo::TypeMap but it \
                                was not. (Ty = {})",
-                              &unique_type_id_str[..],
+                              type_map.get_unique_type_id_as_string(unique_type_id),
                               t);
                 }
             };
@@ -638,14 +633,12 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             match type_map.find_metadata_for_type(t) {
                 Some(metadata) => {
                     if metadata != metadata_for_uid {
-                        let unique_type_id_str =
-                            type_map.get_unique_type_id_as_string(unique_type_id);
                         span_bug!(usage_site_span,
                                   "Mismatch between Ty and \
                                    UniqueTypeId maps in \
                                    debuginfo::TypeMap. \
                                    UniqueTypeId={}, Ty={}",
-                                  &unique_type_id_str[..],
+                                  type_map.get_unique_type_id_as_string(unique_type_id),
                                   t);
                     }
                 }
@@ -809,7 +802,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
     };
 
     fn fallback_path(scc: &SharedCrateContext) -> CString {
-        CString::new(scc.link_meta().crate_name.clone()).unwrap()
+        CString::new(scc.link_meta().crate_name.to_string()).unwrap()
     }
 }
 
@@ -1526,13 +1519,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let enum_llvm_type = type_of::type_of(cx, enum_type);
     let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
 
-    let unique_type_id_str = debug_context(cx)
-                             .type_map
-                             .borrow()
-                             .get_unique_type_id_as_string(unique_type_id);
-
     let enum_name = CString::new(enum_name).unwrap();
-    let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
+    let unique_type_id_str = CString::new(
+        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
+    ).unwrap();
     let enum_metadata = unsafe {
         llvm::LLVMRustDIBuilderCreateUnionType(
         DIB(cx),
@@ -1566,7 +1556,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     fn get_enum_discriminant_name(cx: &CrateContext,
                                   def_id: DefId)
-                                  -> token::InternedString {
+                                  -> InternedString {
         cx.tcx().item_name(def_id).as_str()
     }
 }
@@ -1669,11 +1659,10 @@ fn create_struct_stub(cx: &CrateContext,
                    -> DICompositeType {
     let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
 
-    let unique_type_id_str = debug_context(cx).type_map
-                                              .borrow()
-                                              .get_unique_type_id_as_string(unique_type_id);
     let name = CString::new(struct_type_name).unwrap();
-    let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
+    let unique_type_id = CString::new(
+        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
+    ).unwrap();
     let metadata_stub = unsafe {
         // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
@@ -1707,11 +1696,10 @@ fn create_union_stub(cx: &CrateContext,
                    -> DICompositeType {
     let (union_size, union_align) = size_and_align_of(cx, union_llvm_type);
 
-    let unique_type_id_str = debug_context(cx).type_map
-                                              .borrow()
-                                              .get_unique_type_id_as_string(unique_type_id);
     let name = CString::new(union_type_name).unwrap();
-    let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
+    let unique_type_id = CString::new(
+        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes()
+    ).unwrap();
     let metadata_stub = unsafe {
         // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null
         // pointer will lead to hard to trace and debug LLVM assertions
index 5953ec4aaedfa3cb492de9d8a61f9fa4cf05beac..a0477c9fc1eee2ea93c9759edad86b4d0750e341 100644 (file)
@@ -35,7 +35,7 @@ fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut Stri
         }
 
         let name = match def_key.disambiguated_data.data {
-            DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate),
+            DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(),
             data => data.as_interned_str()
         };
 
@@ -64,7 +64,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
     });
 
     let namespace_name = match def_key.disambiguated_data.data {
-        DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate),
+        DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate).as_str(),
         data => data.as_interned_str()
     };
 
index 956402edc11665ca1eace8763dc26673e55f5f60..fce1ce561055507c42a5d15d04785122232c0090 100644 (file)
@@ -156,7 +156,7 @@ fn push_item_name(cx: &CrateContext,
                       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());
index b1b09d3ca20dee77f2a1454acc4cea0e258b8fc9..016a76a72531b4c783292281927e621e605029c4 100644 (file)
@@ -30,7 +30,7 @@
 use Disr;
 use rustc::hir;
 use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 
 use rustc::session::Session;
 use syntax_pos::{Span, DUMMY_SP};
@@ -107,7 +107,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     let sig = tcx.erase_late_bound_regions_and_normalize(&fty.sig);
     let arg_tys = sig.inputs;
     let ret_ty = sig.output;
-    let name = tcx.item_name(def_id).as_str();
+    let name = &*tcx.item_name(def_id).as_str();
 
     let span = match call_debug_location {
         DebugLoc::ScopeAt(_, span) => span,
@@ -123,15 +123,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         Call(bcx, llfn, &[], call_debug_location);
         Unreachable(bcx);
         return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to()));
-    } else if &name[..] == "unreachable" {
+    } else if name == "unreachable" {
         Unreachable(bcx);
         return Result::new(bcx, C_nil(ccx));
     }
 
     let llret_ty = type_of::type_of(ccx, ret_ty);
 
-    let simple = get_simple_intrinsic(ccx, &name);
-    let llval = match (simple, &name[..]) {
+    let simple = get_simple_intrinsic(ccx, name);
+    let llval = match (simple, name) {
         (Some(llfn), _) => {
             Call(bcx, llfn, &llargs, call_debug_location)
         }
@@ -208,7 +208,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
         (_, "type_name") => {
             let tp_ty = substs.type_at(0);
-            let ty_name = token::intern_and_get_ident(&tp_ty.to_string());
+            let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
             C_str_slice(ccx, ty_name)
         }
         (_, "type_id") => {
@@ -340,7 +340,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let sty = &arg_tys[0].sty;
             match int_type_width_signed(sty, ccx) {
                 Some((width, signed)) =>
-                    match &*name {
+                    match name {
                         "ctlz" => count_zeros_intrinsic(bcx, &format!("llvm.ctlz.i{}", width),
                                                         llargs[0], call_debug_location),
                         "cttz" => count_zeros_intrinsic(bcx, &format!("llvm.cttz.i{}", width),
@@ -394,7 +394,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let sty = &arg_tys[0].sty;
             match float_type_width(sty) {
                 Some(_width) =>
-                    match &*name {
+                    match name {
                         "fadd_fast" => FAddFast(bcx, llargs[0], llargs[1], call_debug_location),
                         "fsub_fast" => FSubFast(bcx, llargs[0], llargs[1], call_debug_location),
                         "fmul_fast" => FMulFast(bcx, llargs[0], llargs[1], call_debug_location),
index 611b93d2de118b80e0d312d149fd9318304cb5f1..d0cb302e1ab1fdb48bc649b77ecc436880289792 100644 (file)
@@ -23,6 +23,7 @@
       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)]
@@ -55,6 +56,9 @@
 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;
index b22bcf9825a2aa4239b23fbe49a9b11a4e0d9e40..29e6f6af416bcead29174057122ef460d6c69b38 100644 (file)
@@ -30,7 +30,7 @@
 use type_::Type;
 
 use rustc_data_structures::fx::FxHashMap;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 
 use super::{MirContext, LocalRef};
 use super::analyze::CleanupKind;
@@ -116,6 +116,9 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                 if let Some(cleanup_pad) = cleanup_pad {
                     bcx.cleanup_ret(cleanup_pad, None);
                 } else {
+                    let llpersonality = bcx.fcx().eh_personality();
+                    bcx.set_personality_fn(llpersonality);
+
                     let ps = self.get_personality_slot(&bcx);
                     let lp = bcx.load(ps);
                     bcx.with_block(|bcx| {
@@ -321,7 +324,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
 
                 // Get the location information.
                 let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
-                let filename = token::intern_and_get_ident(&loc.file.name);
+                let filename = Symbol::intern(&loc.file.name).as_str();
                 let filename = C_str_slice(bcx.ccx(), filename);
                 let line = C_u32(bcx.ccx(), loc.line as u32);
 
@@ -351,7 +354,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
                          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],
index 12b17c26cbc41dbec9d3eb7a4b27bb67531b9fc6..12cbfcef7d26b17cc50f2a699cfac7c55da2bc6a 100644 (file)
@@ -21,7 +21,7 @@
 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;
index 09a1cbd319ac454455f037f6d99c95ecac6b31ed..a36960993e47148a13d4d2aefabda75038cd61ae 100644 (file)
 use std::collections::hash_map::DefaultHasher;
 use symbol_map::SymbolMap;
 use syntax::ast::NodeId;
-use syntax::parse::token::{self, InternedString};
+use syntax::symbol::{Symbol, InternedString};
 use trans_item::TransItem;
 use util::nodemap::{FxHashMap, FxHashSet};
 
@@ -272,7 +272,7 @@ pub fn partition<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
     // If the partitioning should produce a fixed count of codegen units, merge
     // until that count is reached.
     if let PartitioningStrategy::FixedUnitCount(count) = strategy {
-        merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
+        merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name.as_str());
 
         debug_dump(scx, "POST MERGING:", initial_partitioning.codegen_units.iter());
     }
@@ -320,7 +320,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
 
             let codegen_unit_name = match characteristic_def_id {
                 Some(def_id) => compute_codegen_unit_name(tcx, def_id, is_volatile),
-                None => InternedString::new(FALLBACK_CODEGEN_UNIT),
+                None => Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str(),
             };
 
             let make_codegen_unit = || {
@@ -365,7 +365,7 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
     // always ensure we have at least one CGU; otherwise, if we have a
     // crate with just types (for example), we could wind up with no CGU
     if codegen_units.is_empty() {
-        let codegen_unit_name = InternedString::new(FALLBACK_CODEGEN_UNIT);
+        let codegen_unit_name = Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str();
         codegen_units.entry(codegen_unit_name.clone())
                      .or_insert_with(|| CodegenUnit::empty(codegen_unit_name.clone()));
     }
@@ -523,7 +523,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let mut mod_path = String::with_capacity(64);
 
     let def_path = tcx.def_path(def_id);
-    mod_path.push_str(&tcx.crate_name(def_path.krate));
+    mod_path.push_str(&tcx.crate_name(def_path.krate).as_str());
 
     for part in tcx.def_path(def_id)
                    .data
@@ -542,14 +542,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         mod_path.push_str(".volatile");
     }
 
-    return token::intern_and_get_ident(&mod_path[..]);
+    return Symbol::intern(&mod_path[..]).as_str();
 }
 
 fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
-    token::intern_and_get_ident(&format!("{}{}{}",
-        crate_name,
-        NUMBERED_CODEGEN_UNIT_MARKER,
-        index)[..])
+    Symbol::intern(&format!("{}{}{}", crate_name, NUMBERED_CODEGEN_UNIT_MARKER, index)).as_str()
 }
 
 fn debug_dump<'a, 'b, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
index 7fa59127704dc2c7e59504ff7eb6986f6605ef01..f2d1e375793b3bf08754e9ef77143764cfb1418e 100644 (file)
@@ -285,7 +285,7 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
 
         let attributes = tcx.get_attrs(def_id);
         if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
-            if let Some(linkage) = base::llvm_linkage_by_name(&name) {
+            if let Some(linkage) = base::llvm_linkage_by_name(&name.as_str()) {
                 Some(linkage)
             } else {
                 let span = tcx.map.span_if_local(def_id);
@@ -531,7 +531,7 @@ pub fn push_def_path(&self,
 
         // 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("::");
         }
 
index 9bde6b0c4d9953b85263998507ca9e3709217266..c5db8bc8cedc769d152913c6f8edc05d4348dbb5 100644 (file)
@@ -71,7 +71,7 @@
 use std::cell::RefCell;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::parse::token::{self, keywords};
+use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{Span, Pos};
 use errors::DiagnosticBuilder;
 
@@ -645,7 +645,7 @@ fn convert_parenthesized_parameters(&self,
         };
 
         let output_binding = ConvertedBinding {
-            item_name: token::intern(FN_OUTPUT_NAME),
+            item_name: Symbol::intern(FN_OUTPUT_NAME),
             ty: output,
             span: output_span
         };
@@ -1252,7 +1252,7 @@ fn one_bound_for_assoc_type(&self,
         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))
index 900c22a8176ed8ea33267771c0840387a86c1c32..e72dba858c562160dbc42da65d4a53cc8f60109e 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::hir;
 
 use syntax_pos::Span;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 
 #[derive(Copy, Clone, Debug)]
 enum AutoderefKind {
@@ -120,7 +120,7 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let normalized = traits::normalize_projection_type(&mut selcx,
                                                            ty::ProjectionTy {
                                                                trait_ref: trait_ref,
-                                                               item_name: token::intern("Target"),
+                                                               item_name: Symbol::intern("Target"),
                                                            },
                                                            cause,
                                                            0);
@@ -198,7 +198,7 @@ pub fn try_overloaded_deref(&self,
             (PreferMutLvalue, Some(trait_did)) => {
                 self.lookup_method_in_trait(span,
                                             base_expr,
-                                            token::intern("deref_mut"),
+                                            Symbol::intern("deref_mut"),
                                             trait_did,
                                             base_ty,
                                             None)
@@ -211,7 +211,7 @@ pub fn try_overloaded_deref(&self,
             (None, Some(trait_did)) => {
                 self.lookup_method_in_trait(span,
                                             base_expr,
-                                            token::intern("deref"),
+                                            Symbol::intern("deref"),
                                             trait_did,
                                             base_ty,
                                             None)
index 7606a5b7a4d46cc4fd0d0e6ea11056bafedc6341..3ffbbd1be80160acae8a304f4972be13661faba2 100644 (file)
@@ -16,8 +16,7 @@
 use hir::print;
 use rustc::{infer, traits};
 use rustc::ty::{self, LvaluePreference, Ty};
-use syntax::parse::token;
-use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use rustc::hir;
@@ -46,7 +45,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn check_call(&self,
                       call_expr: &'gcx hir::Expr,
                       callee_expr: &'gcx hir::Expr,
-                      arg_exprs: &'gcx [P<hir::Expr>],
+                      arg_exprs: &'gcx [hir::Expr],
                       expected: Expectation<'tcx>)
                       -> Ty<'tcx> {
         let original_callee_ty = self.check_expr(callee_expr);
@@ -160,9 +159,9 @@ fn try_overloaded_call_traits(&self,
                                   -> 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,
@@ -189,7 +188,7 @@ fn try_overloaded_call_traits(&self,
     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;
@@ -272,7 +271,7 @@ fn confirm_builtin_call(&self,
 
     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> {
@@ -299,7 +298,7 @@ fn confirm_deferred_closure_call(&self,
     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> {
index 4edf0011cb39044d8ed60620ab41a82967879095..5839c606566c31c73ea834d54d3615d7f840a755 100644 (file)
@@ -102,6 +102,7 @@ enum CastError {
     /// Cast of thin to fat raw ptr (eg. `*const () as *const [u8]`)
     SizedUnsizedCast,
     IllegalCast,
+    NeedDeref,
     NeedViaPtr,
     NeedViaThinPtr,
     NeedViaInt,
@@ -138,6 +139,25 @@ pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
 
     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,
@@ -390,8 +410,28 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (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),
index 77106b8b0c3a14dd26b4da1f19cd81b65597d63e..a07573a7b9eab08c9578f7bfa36d835b412dc060 100644 (file)
@@ -21,7 +21,7 @@
 
 use syntax::abi::Abi;
 use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use rustc::hir;
@@ -75,7 +75,7 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
-        let name = token::intern(&format!("P{}", n));
+        let name = Symbol::intern(&format!("P{}", n));
         ccx.tcx.mk_param(n, name)
     }
 
@@ -326,7 +326,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
 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)
     };
 
index 66a532fd76acff445794decf6c7f29441e58e102..bd34e993e1e86a984a65e413a19e57a2a8d6b6e6 100644 (file)
@@ -342,7 +342,7 @@ pub fn resolve_ufcs(&self,
         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);
             }
         }
index f08178e49fb2e835eb12768c32ec484ffa076e35..eeb7bb287002f7ffb32a93718ff8b2943a667a37 100644 (file)
 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};
 
@@ -407,6 +407,34 @@ fn always(self) -> bool {
     }
 }
 
+#[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>>>,
@@ -433,6 +461,8 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// Whether any child nodes have any type errors.
     has_errors: Cell<bool>,
 
+    enclosing_loops: RefCell<EnclosingLoops<'gcx, 'tcx>>,
+
     inh: &'a Inherited<'a, 'gcx, 'tcx>,
 }
 
@@ -931,7 +961,8 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     if let Some(ref attr) = item.attrs.iter().find(|a| {
         a.check_name("rustc_on_unimplemented")
     }) {
-        if let Some(ref istring) = attr.value_str() {
+        if let Some(istring) = attr.value_str() {
+            let istring = istring.as_str();
             let parser = Parser::new(&istring);
             let types = &generics.types;
             for token in parser {
@@ -942,7 +973,7 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         Position::ArgumentNamed(s) if s == "Self" => (),
                         // So is `{A}` if A is a type parameter
                         Position::ArgumentNamed(s) => match types.iter().find(|t| {
-                            t.name.as_str() == s
+                            t.name == s
                         }) {
                             Some(_) => (),
                             None => {
@@ -1502,6 +1533,10 @@ pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
                                                      ast::CRATE_NODE_ID)),
             diverges: Cell::new(Diverges::Maybe),
             has_errors: Cell::new(false),
+            enclosing_loops: RefCell::new(EnclosingLoops {
+                stack: Vec::new(),
+                by_id: NodeMap(),
+            }),
             inh: inh,
         }
     }
@@ -2369,7 +2404,7 @@ fn try_index_step(&self,
             (PreferMutLvalue, Some(trait_did)) => {
                 self.lookup_method_in_trait_adjusted(expr.span,
                                                      Some(&base_expr),
-                                                     token::intern("index_mut"),
+                                                     Symbol::intern("index_mut"),
                                                      trait_did,
                                                      autoderefs,
                                                      unsize,
@@ -2384,7 +2419,7 @@ fn try_index_step(&self,
             (None, Some(trait_did)) => {
                 self.lookup_method_in_trait_adjusted(expr.span,
                                                      Some(&base_expr),
-                                                     token::intern("index"),
+                                                     Symbol::intern("index"),
                                                      trait_did,
                                                      autoderefs,
                                                      unsize,
@@ -2408,7 +2443,7 @@ fn check_method_argument_types(&self,
                                    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> {
@@ -2447,7 +2482,7 @@ fn check_argument_types(&self,
                             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;
@@ -2821,7 +2856,7 @@ fn expected_types_for_fn_args(&self,
     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> {
@@ -3027,7 +3062,7 @@ fn check_field(&self,
     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
@@ -3126,7 +3161,7 @@ fn report_unknown_field(&self,
                 ty::TyAdt(adt, ..) if adt.is_enum() => {
                     struct_span_err!(self.tcx.sess, field.name.span, E0559,
                                     "{} `{}::{}` has no field named `{}`",
-                                    kind_name, actual, variant.name.as_str(), field.name.node)
+                                    kind_name, actual, variant.name, field.name.node)
                 }
                 _ => {
                     struct_span_err!(self.tcx.sess, field.name.span, E0560,
@@ -3146,7 +3181,7 @@ fn report_unknown_field(&self,
             match ty.sty {
                 ty::TyAdt(adt, ..) if adt.is_enum() => {
                     err.span_label(field.name.span, &format!("`{}::{}` does not have this field",
-                                                             ty, variant.name.as_str()));
+                                                             ty, variant.name));
                 }
                 _ => {
                     err.span_label(field.name.span, &format!("`{}` does not have this field", ty));
@@ -3583,7 +3618,74 @@ fn check_expr_kind(&self,
               }
               tcx.mk_nil()
           }
-          hir::ExprBreak(_) => { tcx.types.never }
+          hir::ExprBreak(ref label_opt, ref expr_opt) => {
+            let loop_id = if label_opt.is_some() {
+                let loop_def = tcx.expect_def(expr.id);
+                if let Def::Label(loop_id) = loop_def {
+                    Some(Some(loop_id))
+                } else if loop_def == Def::Err {
+                    // an error was already printed, so just ignore it
+                    None
+                } else {
+                    span_bug!(expr.span, "break label resolved to a non-label");
+                }
+            } else {
+                Some(None)
+            };
+            if let Some(loop_id) = loop_id {
+                let coerce_to = {
+                    let mut enclosing_loops = self.enclosing_loops.borrow_mut();
+                    enclosing_loops.find_loop(loop_id).map(|ctxt| ctxt.coerce_to)
+                };
+                if let Some(coerce_to) = coerce_to {
+                    let e_ty;
+                    let cause;
+                    if let Some(ref e) = *expr_opt {
+                        // Recurse without `enclosing_loops` borrowed.
+                        e_ty = self.check_expr_with_hint(e, coerce_to);
+                        cause = self.misc(e.span);
+                        // Notably, the recursive call may alter coerce_to - must not keep using it!
+                    } else {
+                        // `break` without argument acts like `break ()`.
+                        e_ty = tcx.mk_nil();
+                        cause = self.misc(expr.span);
+                    }
+                    let mut enclosing_loops = self.enclosing_loops.borrow_mut();
+                    let ctxt = enclosing_loops.find_loop(loop_id).unwrap();
+
+                    let result = if let Some(ref e) = *expr_opt {
+                        // Special-case the first element, as it has no "previous expressions".
+                        let result = if !ctxt.may_break {
+                            self.try_coerce(e, e_ty, ctxt.coerce_to)
+                        } else {
+                            self.try_find_coercion_lub(&cause, || ctxt.break_exprs.iter().cloned(),
+                                                       ctxt.unified, e, e_ty)
+                        };
+
+                        ctxt.break_exprs.push(e);
+                        result
+                    } else {
+                        self.eq_types(true, &cause, e_ty, ctxt.unified)
+                            .map(|InferOk { obligations, .. }| {
+                                // FIXME(#32730) propagate obligations
+                                assert!(obligations.is_empty());
+                                e_ty
+                            })
+                    };
+                    match result {
+                        Ok(ty) => ctxt.unified = ty,
+                        Err(err) => {
+                            self.report_mismatched_types(&cause, ctxt.unified, e_ty, err);
+                        }
+                    }
+
+                    ctxt.may_break = true;
+                }
+                // Otherwise, we failed to find the enclosing loop; this can only happen if the
+                // `break` was not inside a loop at all, which is caught by the loop-checking pass.
+            }
+            tcx.types.never
+          }
           hir::ExprAgain(_) => { tcx.types.never }
           hir::ExprRet(ref expr_opt) => {
             if let Some(ref e) = *expr_opt {
@@ -3634,12 +3736,22 @@ fn check_expr_kind(&self,
                                  expr.span, expected)
           }
           hir::ExprWhile(ref cond, ref body, _) => {
-            self.check_expr_has_type(&cond, tcx.types.bool);
-            let cond_diverging = self.diverges.get();
-            self.check_block_no_value(&body);
+            let unified = self.tcx.mk_nil();
+            let coerce_to = unified;
+            let ctxt = LoopCtxt {
+                unified: unified,
+                coerce_to: coerce_to,
+                break_exprs: vec![],
+                may_break: true,
+            };
+            self.with_loop_ctxt(expr.id, ctxt, || {
+                self.check_expr_has_type(&cond, tcx.types.bool);
+                let cond_diverging = self.diverges.get();
+                self.check_block_no_value(&body);
 
-            // We may never reach the body so it diverging means nothing.
-            self.diverges.set(cond_diverging);
+                // We may never reach the body so it diverging means nothing.
+                self.diverges.set(cond_diverging);
+            });
 
             if self.has_errors.get() {
                 tcx.types.err
@@ -3647,14 +3759,25 @@ fn check_expr_kind(&self,
                 tcx.mk_nil()
             }
           }
-          hir::ExprLoop(ref body, _) => {
-            self.check_block_no_value(&body);
-            if may_break(tcx, expr.id, &body) {
+          hir::ExprLoop(ref body, _, _) => {
+            let unified = self.next_ty_var();
+            let coerce_to = expected.only_has_type(self).unwrap_or(unified);
+            let ctxt = LoopCtxt {
+                unified: unified,
+                coerce_to: coerce_to,
+                break_exprs: vec![],
+                may_break: false,
+            };
+
+            let ctxt = self.with_loop_ctxt(expr.id, ctxt, || {
+                self.check_block_no_value(&body);
+            });
+            if ctxt.may_break {
                 // No way to know whether it's diverging because
                 // of a `break` or an outer `break` or `return.
                 self.diverges.set(Diverges::Maybe);
 
-                tcx.mk_nil()
+                ctxt.unified
             } else {
                 tcx.types.never
             }
@@ -3669,10 +3792,10 @@ fn check_expr_kind(&self,
             self.check_block_with_expected(&b, expected)
           }
           hir::ExprCall(ref callee, ref args) => {
-              self.check_call(expr, &callee, &args[..], expected)
+              self.check_call(expr, &callee, args, expected)
           }
           hir::ExprMethodCall(name, ref tps, ref args) => {
-              self.check_method_call(expr, name, &args[..], &tps[..], expected, lvalue_pref)
+              self.check_method_call(expr, name, args, &tps[..], expected, lvalue_pref)
           }
           hir::ExprCast(ref e, ref t) => {
             if let hir::TyArray(_, ref count_expr) = t.node {
@@ -3727,7 +3850,7 @@ fn check_expr_kind(&self,
                 let result = if i == 0 {
                     self.try_coerce(e, e_ty, coerce_to)
                 } else {
-                    let prev_elems = || args[..i].iter().map(|e| &**e);
+                    let prev_elems = || args[..i].iter().map(|e| &*e);
                     self.try_find_coercion_lub(&cause, prev_elems, unified, e, e_ty)
                 };
 
@@ -4436,19 +4559,20 @@ fn check_path_parameter_count(&self,
         let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
         if lifetimes.len() > lifetime_defs.len() {
             let span = lifetimes[lifetime_defs.len()].span;
-            span_err!(self.tcx.sess, span, E0088,
-                      "too many lifetime parameters provided: \
-                       expected {}, found {}",
-                      count(lifetime_defs.len()),
-                      count(lifetimes.len()));
-        } else if lifetimes.len() > 0 && lifetimes.len() < lifetime_defs.len() {
-            span_err!(self.tcx.sess, span, E0090,
-                      "too few lifetime parameters provided: \
-                       expected {}, found {}",
-                      count(lifetime_defs.len()),
-                      count(lifetimes.len()));
+            struct_span_err!(self.tcx.sess, span, E0088,
+                             "too many lifetime parameters provided: \
+                              expected {}, found {}",
+                              count(lifetime_defs.len()),
+                              count(lifetimes.len()))
+                .span_label(span, &format!("unexpected lifetime parameter{}",
+                                           match lifetimes.len() { 1 => "", _ => "s" }))
+                .emit();
         }
 
+        // The case where there is not enough lifetime parameters is not checked,
+        // because this is not possible - a function never takes lifetime parameters.
+        // See discussion for Pull Request 36208.
+
         // Check provided type parameters.
         let type_defs = segment.map_or(&[][..], |(_, generics)| {
             if generics.parent.is_none() {
@@ -4529,27 +4653,24 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
             self.tcx.types.err
         })
     }
-}
 
-// Returns true if b contains a break that can exit from b
-pub fn may_break(tcx: TyCtxt, id: ast::NodeId, b: &hir::Block) -> bool {
-    // First: is there an unlabeled break immediately
-    // inside the loop?
-    (loop_query(&b, |e| {
-        match *e {
-            hir::ExprBreak(None) => true,
-            _ => false
+    fn with_loop_ctxt<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>,
index 8b4975b7e3a2f723331219af60397986596beed3..adb8c6be42bc1ed6ed861e1e00b3c44938491f7b 100644 (file)
@@ -14,7 +14,7 @@
 use hir::def_id::DefId;
 use rustc::ty::{Ty, TypeFoldable, PreferMutLvalue};
 use syntax::ast;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use rustc::hir;
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@@ -182,7 +182,7 @@ fn check_overloaded_binop(&self,
         let rhs_ty_var = self.next_ty_var();
 
         let return_ty = match self.lookup_op_method(expr, lhs_ty, vec![rhs_ty_var],
-                                                    token::intern(name), trait_def_id,
+                                                    Symbol::intern(name), trait_def_id,
                                                     lhs_expr) {
             Ok(return_ty) => return_ty,
             Err(()) => {
@@ -248,9 +248,8 @@ pub fn check_user_unop(&self,
                            -> 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| {
index a280001d5e99d24f511781532dfb8948bf5293e4..c613b62bf2d82b4a3589f01d6f909986588d58b8 100644 (file)
@@ -613,11 +613,11 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
             hir::ExprCall(ref callee, ref args) => {
                 if has_method_map {
                     self.constrain_call(expr, Some(&callee),
-                                        args.iter().map(|e| &**e), false);
+                                        args.iter().map(|e| &*e), false);
                 } else {
                     self.constrain_callee(callee.id, expr, &callee);
                     self.constrain_call(expr, None,
-                                        args.iter().map(|e| &**e), false);
+                                        args.iter().map(|e| &*e), false);
                 }
 
                 intravisit::walk_expr(self, expr);
@@ -625,7 +625,7 @@ fn visit_expr(&mut self, expr: &hir::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);
             }
@@ -742,7 +742,7 @@ fn visit_expr(&mut self, expr: &hir::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);
index 535b6bcdcba177dff99ac1d7429bbbcc54cbfaf9..48d79a3ba4c87bb7b5fd932e0abbf7bb6f22d9ab 100644 (file)
@@ -79,7 +79,7 @@
 use std::cell::RefCell;
 
 use syntax::{abi, ast, attr};
-use syntax::parse::token::{self, keywords};
+use syntax::symbol::{Symbol, keywords};
 use syntax_pos::Span;
 
 use rustc::hir::{self, map as hir_map, print as pprust};
@@ -585,7 +585,7 @@ fn convert_closure<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| {
         fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef {
             index: (base_generics.count() as u32) + (i as u32),
-            name: token::intern("<upvar>"),
+            name: Symbol::intern("<upvar>"),
             def_id: def_id,
             default_def_id: base_def_id,
             default: None,
index 185f897c1baa1cfb82226cb4d59e3abe8204e382..c5562ae3b7febf5753f6a649a011ccc824847e1c 100644 (file)
@@ -18,7 +18,7 @@
 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() => {
@@ -66,39 +62,38 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
     })
 }
 
-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.
@@ -108,23 +103,24 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
         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),
@@ -134,9 +130,8 @@ fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     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.
@@ -144,27 +139,24 @@ pub fn load_attrs<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// 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);
@@ -176,45 +168,42 @@ pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tc
     }
 }
 
-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 {
@@ -222,44 +211,41 @@ fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             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
@@ -277,7 +263,7 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
     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.
@@ -303,22 +289,20 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
 
     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
@@ -377,7 +361,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
                         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),
@@ -424,7 +408,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
                     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),
@@ -440,15 +424,15 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
             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 {
@@ -471,26 +455,24 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
     });
 }
 
-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)
                 }
             }
@@ -498,9 +480,8 @@ fn fill_in<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-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);
@@ -508,16 +489,14 @@ fn build_const<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     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
     }
index a141d0e4788dd845509131780a6d83a9c268ff38..a19ec4e8b5edbf6bd57d71163b324764f2f7db5b 100644 (file)
@@ -14,7 +14,6 @@
 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::*;
@@ -24,9 +23,8 @@
 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;
@@ -44,6 +42,7 @@
 
 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> {
@@ -126,20 +125,17 @@ fn clean(&self, cx: &DocContext) -> Crate {
         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));
 
@@ -227,7 +223,7 @@ fn clean(&self, cx: &DocContext) -> Crate {
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct ExternalCrate {
     pub name: String,
-    pub attrs: Vec<Attribute>,
+    pub attrs: Attributes,
     pub primitives: Vec<PrimitiveType>,
 }
 
@@ -235,14 +231,12 @@ impl Clean<ExternalCrate> for CrateNum {
     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,
         }
@@ -258,7 +252,7 @@ pub struct Item {
     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,
@@ -270,7 +264,7 @@ impl Item {
     /// 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 {
@@ -450,7 +444,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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
@@ -459,86 +453,104 @@ fn clean(&self, cx: &DocContext) -> Item {
     }
 }
 
-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)
     }
 }
 
@@ -554,7 +566,7 @@ impl Clean<TyParam> for hir::TyParam {
     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),
         }
@@ -591,11 +603,9 @@ fn maybe_sized(cx: &DocContext) -> TyParamBound {
 
     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
@@ -616,9 +626,9 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
     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(),
@@ -641,7 +651,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
                 output: output
             }
         },
-        (..) => {
+        _ => {
             PathParameters::AngleBracketed {
                 lifetimes: lifetimes,
                 types: types.clean(cx),
@@ -666,10 +676,7 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
 
 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 =>
@@ -700,12 +707,8 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
 
 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);
@@ -772,18 +775,16 @@ pub fn statik() -> Lifetime {
 
 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())
     }
@@ -1048,7 +1049,7 @@ fn clean(&self, cx: &DocContext) -> Method {
             },
             output: self.decl.output.clean(cx),
             variadic: false,
-            attrs: Vec::new()
+            attrs: Attributes::default()
         };
         Method {
             generics: self.generics.clean(cx),
@@ -1076,7 +1077,7 @@ fn clean(&self, cx: &DocContext) -> TyMethod {
             },
             output: self.decl.output.clean(cx),
             variadic: false,
-            attrs: Vec::new()
+            attrs: Attributes::default()
         };
         TyMethod {
             unsafety: self.unsafety.clone(),
@@ -1105,7 +1106,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -1122,7 +1123,7 @@ pub struct FnDecl {
     pub inputs: Arguments,
     pub output: FunctionRetTy,
     pub variadic: bool,
-    pub attrs: Vec<Attribute>,
+    pub attrs: Attributes,
 }
 
 impl FnDecl {
@@ -1148,7 +1149,7 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
             },
             output: self.output.clean(cx),
             variadic: self.variadic,
-            attrs: Vec::new()
+            attrs: Attributes::default()
         }
     }
 }
@@ -1156,14 +1157,14 @@ fn clean(&self, cx: &DocContext) -> FnDecl {
 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| {
@@ -1247,7 +1248,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -1297,10 +1298,10 @@ fn clean(&self, cx: &DocContext) -> Item {
             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
         }
     }
@@ -1329,10 +1330,10 @@ fn clean(&self, cx: &DocContext) -> Item {
             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
         }
     }
@@ -1342,13 +1343,13 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
     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!()
                 };
@@ -1357,9 +1358,9 @@ fn clean(&self, cx: &DocContext) -> Item {
                 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 {
@@ -1405,8 +1406,8 @@ fn clean(&self, cx: &DocContext) -> Item {
                     // 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 {
@@ -1442,7 +1443,7 @@ fn clean(&self, cx: &DocContext) -> Item {
                 }
 
                 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
                 };
@@ -1457,7 +1458,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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,
         }
@@ -1616,11 +1617,11 @@ fn from_str(s: &str) -> Option<PrimitiveType> {
         }
     }
 
-    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;
                     }
                 }
@@ -1710,53 +1711,44 @@ fn clean(&self, cx: &DocContext) -> Type {
                              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));
@@ -1824,9 +1816,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             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)),
@@ -1846,7 +1836,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     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) => {
@@ -1857,7 +1847,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     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,
@@ -1884,7 +1874,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     });
                 }
 
-                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,
@@ -1902,9 +1892,9 @@ fn clean(&self, cx: &DocContext) -> Type {
             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())
@@ -1925,9 +1915,9 @@ fn clean(&self, cx: &DocContext) -> Item {
             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)),
         }
     }
@@ -1937,7 +1927,7 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
     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),
@@ -1988,7 +1978,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2008,7 +1998,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2055,7 +2045,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2082,7 +2072,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
             }),
@@ -2107,7 +2097,7 @@ fn clean(&self, cx: &DocContext) -> Item {
                         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),
@@ -2120,7 +2110,7 @@ fn clean(&self, cx: &DocContext) -> Item {
         };
         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,
@@ -2305,7 +2295,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2357,7 +2347,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2382,7 +2372,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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),
@@ -2443,24 +2433,22 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
 
         // 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),
@@ -2481,10 +2469,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
 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 {
@@ -2494,7 +2479,7 @@ fn build_deref_target_impls(cx: &DocContext,
         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() {
@@ -2525,7 +2510,7 @@ fn build_deref_target_impls(cx: &DocContext,
         };
         if let Some(did) = did {
             if !did.is_local() {
-                inline::build_impl(cx, tcx, did, ret);
+                inline::build_impl(cx, did, ret);
             }
         }
     }
@@ -2543,7 +2528,7 @@ fn clean(&self, cx: &DocContext) -> 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: Some(Public),
             stability: None,
             deprecation: None,
@@ -2577,7 +2562,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
         // #[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,
@@ -2627,7 +2612,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
             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,
@@ -2706,10 +2691,10 @@ fn clean(&self, cx: &DocContext) -> Item {
             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,
         }
     }
@@ -2776,22 +2761,7 @@ fn resolve_type(cx: &DocContext,
                 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 {
@@ -2816,8 +2786,6 @@ fn resolve_type(cx: &DocContext,
 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),
@@ -2827,7 +2795,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
         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
@@ -2837,7 +2805,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
     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
@@ -2851,9 +2819,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
 }
 
 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)]
@@ -2872,7 +2838,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             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,
index 19e084905aa92a03f0804fc93a6a7b0aac1238e3..7240f0aedbd2770fd38ab4da16a0fdff138faa41 100644 (file)
@@ -153,7 +153,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId,
     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() {
index a25cb0bacc5cf785610a2bc634d8535868b80882..7d7b7fead5854d9fbd9944dc32f7e904fb6e8d32 100644 (file)
@@ -7,7 +7,6 @@
 // <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.
@@ -77,24 +67,9 @@ pub struct DocContext<'a, 'tcx: 'a> {
     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
@@ -208,12 +183,9 @@ pub fn run_core(search_paths: SearchPaths,
         };
 
         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(),
@@ -221,11 +193,11 @@ pub fn run_core(search_paths: SearchPaths,
             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)
         };
 
index 44dadc4367b52cf411720b5bbd5514eb3445055d..757db81c4402196fc43e77a6547639117b591b0e 100644 (file)
@@ -53,7 +53,7 @@
 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;
@@ -62,7 +62,7 @@
 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;
@@ -453,30 +453,26 @@ pub fn run(mut krate: clean::Crate,
 
     // 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;
                 }
                 _ => {}
@@ -860,13 +856,16 @@ fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
 
     // 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> {
@@ -2437,7 +2436,6 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         write!(w, "}}")?;
     }
     write!(w, "</pre>")?;
-    render_stability_since_raw(w, it.stable_since(), None)?;
 
     document(w, cx, it)?;
     if !e.variants.is_empty() {
@@ -2512,49 +2510,47 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     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));
         }
     }
@@ -2811,7 +2807,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
         }
         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))?;
         }
     }
@@ -3053,7 +3049,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                                                      Some("macro"),
                                                      None,
                                                      None))?;
-    render_stability_since_raw(w, it.stable_since(), None)?;
     document(w, cx, it)
 }
 
index 3af7c20c1336e91f1941e0ceb50c449b246822ff..60ce7ea53953a5c5dbdef176dd55d0b4d3408785 100644 (file)
@@ -89,7 +89,7 @@ pub mod html {
 pub mod visit_lib;
 pub mod test;
 
-use clean::Attributes;
+use clean::AttributesExt;
 
 struct Output {
     krate: clean::Crate,
@@ -280,43 +280,45 @@ pub fn main_args(args: &[String]) -> isize {
                                                  !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))
     }
 }
 
@@ -342,7 +344,8 @@ fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
 /// 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");
@@ -355,6 +358,8 @@ fn rust_input(cratefile: &str, externs: Externs, matches: &getopts::Matches) ->
     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");
@@ -363,67 +368,68 @@ fn rust_input(cratefile: &str, externs: Externs, matches: &getopts::Matches) ->
     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()
 }
index c034ef9326846c349b7761606918c72bd1fad35d..3c63302127c5eef17b7df6e4818d3851d1f9db0d 100644 (file)
@@ -8,40 +8,33 @@
 // 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];
+        }
+    }
+}
index 927ccf917199978221c2488262aa97e838869e03..68c1231fc6f7c58e7266ee3e3c52708fa36e7b68 100644 (file)
@@ -11,7 +11,7 @@
 use rustc::util::nodemap::DefIdSet;
 use std::mem;
 
-use clean::{self, Attributes};
+use clean::{self, AttributesExt, NestedAttributesExt};
 use clean::Item;
 use plugins;
 use fold;
@@ -41,7 +41,7 @@ struct Stripper<'a> {
 
 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 {
index 20640f3f88518f98d2c8f7269a9377a9f698559e..4d94c30847852f42ce5393049f4b3ee22d6cecea 100644 (file)
 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;
index 12d33dcb207f7c78ab170e5cbb69439a8b27b098..9f29319430dd5f4688444904fa55295170f32ed8 100644 (file)
@@ -8,7 +8,6 @@
 // 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::*;
@@ -23,7 +22,8 @@
 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 {
@@ -87,48 +84,36 @@ pub fn run(input: &str,
         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());
 
@@ -472,56 +457,84 @@ pub fn register_header(&mut self, name: &str, level: u32) {
     }
 }
 
-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("&amp;") {
-                s = s.replace("&amp;", "&");
+    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("&gt;") {
-                s.replace("&gt;", ">")
-                 .replace("&lt;", "<")
-            } 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);
+        });
     }
 }
index 939fd6ccfc88e0e6f337d4fe04a4cc03d867f31e..8ed0567d820ac4af27ea5df04f26f3700374e3ee 100644 (file)
@@ -28,7 +28,7 @@
 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
@@ -65,18 +65,13 @@ pub fn new(cx: &'a core::DocContext<'a, 'tcx>) -> RustdocVisitor<'a, 'tcx> {
     }
 
     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) {
@@ -196,7 +191,7 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
         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;
@@ -279,10 +274,9 @@ fn maybe_inline_local(&mut self, id: ast::NodeId, renamed: Option<ast::Name>,
                   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 {
@@ -292,25 +286,22 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
             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) |
@@ -348,7 +339,7 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
                     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);
                             }
                         }
@@ -507,7 +498,7 @@ pub fn visit_item(&mut self, item: &hir::Item,
                 // 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,
index 6d2830c56192bb434b73485384b6a9681d8d7d8b..cee292f99153e4fc318463094d1633f8ac8e6074 100644 (file)
@@ -16,7 +16,7 @@
 
 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
 
@@ -49,10 +49,7 @@ pub fn visit_lib(&mut self, cnum: CrateNum) {
 
     // 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
index e29dbe35c5a59a242c592fd0dc0c3c3c5adb47ab..baa2b5d2846220c3ea41e1e3622f267cc43a3804 100644 (file)
@@ -546,17 +546,23 @@ pub fn current_exe() -> io::Result<PathBuf> {
     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 }
 
@@ -571,7 +577,7 @@ 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
 ///
@@ -583,6 +589,8 @@ pub struct ArgsOs { inner: sys::args::Args }
 ///     println!("{}", argument);
 /// }
 /// ```
+///
+/// [`args_os`]: ./fn.args_os.html
 #[stable(feature = "env", since = "1.0.0")]
 pub fn args() -> Args {
     Args { inner: args_os() }
index df5741d00a2c10b08dce46127377e6a8cebf2cf7..e91e808c5489a48a6a2d2cd03929e73384996a8d 100644 (file)
@@ -348,6 +348,41 @@ pub fn try_clone(&self) -> io::Result<File> {
             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 {
@@ -2469,6 +2504,24 @@ fn chmod_works() {
         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();
index 20dc5b3801ba410560d75100480ee17c6f1099d9..0328012ee57269a4411c6499da22de23907ff027 100644 (file)
@@ -31,7 +31,7 @@ pub enum SocketAddr {
     /// An IPv4 socket address which is a (ip, port) combination.
     #[stable(feature = "rust1", since = "1.0.0")]
     V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
-    /// An IPv6 socket address
+    /// An IPv6 socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
 }
@@ -48,6 +48,16 @@ pub struct SocketAddrV6 { inner: c::sockaddr_in6 }
 
 impl SocketAddr {
     /// Creates a new socket address from the (ip, port) pair.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
     #[stable(feature = "ip_addr", since = "1.7.0")]
     pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
         match ip {
@@ -57,6 +67,15 @@ pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
     }
 
     /// Returns the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+    /// ```
     #[stable(feature = "ip_addr", since = "1.7.0")]
     pub fn ip(&self) -> IpAddr {
         match *self {
@@ -66,6 +85,16 @@ pub fn ip(&self) -> IpAddr {
     }
 
     /// Change the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+    /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_ip(&mut self, new_ip: IpAddr) {
         // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
@@ -77,6 +106,15 @@ pub fn set_ip(&mut self, new_ip: IpAddr) {
     }
 
     /// Returns the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
         match *self {
@@ -86,6 +124,16 @@ pub fn port(&self) -> u16 {
     }
 
     /// Change the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// socket.set_port(1025);
+    /// assert_eq!(socket.port(), 1025);
+    /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
         match *self {
@@ -96,6 +144,20 @@ pub fn set_port(&mut self, new_port: u16) {
 
     /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
     /// false if it's a valid IPv6 address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(sockaddr_checker)]
+    ///
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// fn main() {
+    ///     let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    ///     assert_eq!(socket.is_ipv4(), true);
+    ///     assert_eq!(socket.is_ipv6(), false);
+    /// }
+    /// ```
     #[unstable(feature = "sockaddr_checker", issue = "36949")]
     pub fn is_ipv4(&self) -> bool {
         match *self {
@@ -106,6 +168,21 @@ pub fn is_ipv4(&self) -> bool {
 
     /// 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 {
@@ -117,6 +194,14 @@ pub fn is_ipv6(&self) -> bool {
 
 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 {
@@ -130,6 +215,15 @@ pub fn new(ip: Ipv4Addr, port: u16) -> 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 {
@@ -138,18 +232,47 @@ pub fn ip(&self) -> &Ipv4Addr {
     }
 
     /// 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);
index 9d21a76e81b9e41f4e39ebe1af7fba669e002aa2..c99fda9febc245e94d5042a3e015ef65a716aa53 100644 (file)
@@ -825,6 +825,21 @@ pub fn exit(code: i32) -> ! {
     ::sys::os::exit(code)
 }
 
+/// Terminates the process in an abnormal fashion.
+///
+/// The function will never return and will immediately terminate the current
+/// process in a platform specific "abnormal" manner.
+///
+/// Note that because this function never returns, and that it terminates the
+/// process, no destructors on the current stack or any other thread's stack
+/// will be run. If a clean shutdown is needed it is recommended to only call
+/// this function at a known point where there are no more destructors left
+/// to run.
+#[unstable(feature = "process_abort", issue = "37838")]
+pub fn abort() -> ! {
+    unsafe { ::sys::abort_internal() };
+}
+
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use io::prelude::*;
index 0b43fd2ac8c4df3a670c2899046ba9c0f1c301e2..9ee0458b5da365d1fae1c99bfa17fbdf0d20113f 100644 (file)
@@ -526,6 +526,11 @@ pub fn duplicate(&self) -> io::Result<File> {
     pub fn fd(&self) -> &FileDesc { &self.0 }
 
     pub fn into_fd(self) -> FileDesc { self.0 }
+
+    pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
+        cvt_r(|| unsafe { libc::fchmod(self.0.raw(), perm.mode) })?;
+        Ok(())
+    }
 }
 
 impl DirBuilder {
index ce563dc7b16d3e4fe31c3b6ab343bd82dfc0d484..1a563127f7f0668d69ba11485abdadfd5f49aa7d 100644 (file)
@@ -182,6 +182,7 @@ fn clone(&self) -> Self { *self }
 pub const ERROR_NO_MORE_FILES: DWORD = 18;
 pub const ERROR_HANDLE_EOF: DWORD = 38;
 pub const ERROR_FILE_EXISTS: DWORD = 80;
+pub const ERROR_INVALID_PARAMETER: DWORD = 87;
 pub const ERROR_BROKEN_PIPE: DWORD = 109;
 pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
 pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
@@ -388,6 +389,15 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
     MaximumFileInfoByHandlesClass
 }
 
+#[repr(C)]
+pub struct FILE_BASIC_INFO {
+    pub CreationTime: LARGE_INTEGER,
+    pub LastAccessTime: LARGE_INTEGER,
+    pub LastWriteTime: LARGE_INTEGER,
+    pub ChangeTime: LARGE_INTEGER,
+    pub FileAttributes: DWORD,
+}
+
 #[repr(C)]
 pub struct FILE_END_OF_FILE_INFO {
     pub EndOfFile: LARGE_INTEGER,
index 98fd15f863ba10ad0c18a1f404d00db98a6e88b7..7d7d78bbd87308315d75551a88c9ac5ef4558ac1 100644 (file)
@@ -417,6 +417,24 @@ fn readlink(&self) -> io::Result<PathBuf> {
             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 {
index ed7e88e72cd5609d69fa296ab0e811bd733db231..1eb1730547642f18eb3fc162d192f977089c84b0 100644 (file)
@@ -43,6 +43,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
         let reader;
         let mut name;
         let mut tries = 0;
+        let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
         loop {
             tries += 1;
             let key: u64 = rand::thread_rng().gen();
@@ -56,12 +57,12 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
 
             let handle = c::CreateNamedPipeW(wide_name.as_ptr(),
                                              c::PIPE_ACCESS_INBOUND |
-                                              c::FILE_FLAG_FIRST_PIPE_INSTANCE |
-                                              c::FILE_FLAG_OVERLAPPED,
+                                             c::FILE_FLAG_FIRST_PIPE_INSTANCE |
+                                             c::FILE_FLAG_OVERLAPPED,
                                              c::PIPE_TYPE_BYTE |
-                                              c::PIPE_READMODE_BYTE |
-                                              c::PIPE_WAIT |
-                                              c::PIPE_REJECT_REMOTE_CLIENTS,
+                                             c::PIPE_READMODE_BYTE |
+                                             c::PIPE_WAIT |
+                                             reject_remote_clients_flag,
                                              1,
                                              4096,
                                              4096,
@@ -76,11 +77,27 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
             //
             // Don't try again too much though as this could also perhaps be a
             // legit error.
+            // If ERROR_INVALID_PARAMETER is returned, this probably means we're
+            // running on pre-Vista version where PIPE_REJECT_REMOTE_CLIENTS is
+            // not supported, so we continue retrying without it. This implies
+            // reduced security on Windows versions older than Vista by allowing
+            // connections to this pipe from remote machines.
+            // Proper fix would increase the number of FFI imports and introduce
+            // significant amount of Windows XP specific code with no clean
+            // testing strategy
+            // for more info see https://github.com/rust-lang/rust/pull/37677
             if handle == c::INVALID_HANDLE_VALUE {
                 let err = io::Error::last_os_error();
-                if tries < 10 &&
-                   err.raw_os_error() == Some(c::ERROR_ACCESS_DENIED as i32) {
-                    continue
+                let raw_os_err = err.raw_os_error();
+                if tries < 10 {
+                    if raw_os_err == Some(c::ERROR_ACCESS_DENIED as i32) {
+                        continue
+                    } else if reject_remote_clients_flag != 0 &&
+                        raw_os_err == Some(c::ERROR_INVALID_PARAMETER as i32) {
+                        reject_remote_clients_flag = 0;
+                        tries -= 1;
+                        continue
+                    }
                 }
                 return Err(err)
             }
index f5cd089e923d7c7efe3dbbcdf7001d45656e5e06..2a911aceb9d94e01a8be3187953b019271d6103d 100644 (file)
 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 {
@@ -401,7 +373,7 @@ pub fn is_parameterized(&self) -> bool {
     }
     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);
             }
         }
@@ -479,7 +451,7 @@ pub struct WhereEqPredicate {
 
 /// The set of MetaItems that define the compilation environment of the crate,
 /// used to drive conditional compilation
-pub type CrateConfig = Vec<P<MetaItem>>;
+pub type CrateConfig = HashSet<(Name, Option<Symbol>)>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Crate {
@@ -498,7 +470,7 @@ 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
@@ -508,53 +480,30 @@ pub enum NestedMetaItemKind {
 /// 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 (`{ .. }`).
@@ -1050,8 +999,8 @@ pub enum ExprKind {
 
     /// 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
@@ -1149,7 +1098,7 @@ pub enum LitIntType {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum LitKind {
     /// A string literal (`"foo"`)
-    Str(InternedString, StrStyle),
+    Str(Symbol, StrStyle),
     /// A byte string (`b"foo"`)
     ByteStr(Rc<Vec<u8>>),
     /// A byte char (`b'f'`)
@@ -1159,9 +1108,9 @@ pub enum LitKind {
     /// An integer literal (`1`)
     Int(u64, LitIntType),
     /// A float literal (`1f64` or `1E10f64`)
-    Float(InternedString, FloatTy),
+    Float(Symbol, FloatTy),
     /// A float literal without a suffix (`1.0 or 1.0E10`)
-    FloatUnsuffixed(InternedString),
+    FloatUnsuffixed(Symbol),
     /// A boolean literal
     Bool(bool),
 }
@@ -1493,7 +1442,7 @@ pub enum AsmDialect {
 /// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsmOutput {
-    pub constraint: InternedString,
+    pub constraint: Symbol,
     pub expr: P<Expr>,
     pub is_rw: bool,
     pub is_indirect: bool,
@@ -1504,11 +1453,11 @@ pub struct InlineAsmOutput {
 /// E.g. `asm!("NOP");`
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsm {
-    pub asm: InternedString,
+    pub asm: Symbol,
     pub asm_str_style: StrStyle,
     pub outputs: Vec<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,
@@ -1755,8 +1704,6 @@ pub fn path(&self) -> &Path {
     }
 }
 
-/// 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
@@ -1770,13 +1717,15 @@ pub enum AttrStyle {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub struct AttrId(pub usize);
 
+/// Meta-data associated with an item
 /// Doc-comments are promoted to attributes that have is_sugared_doc = true
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct Attribute_ {
+pub struct Attribute {
     pub id: AttrId,
     pub style: AttrStyle,
-    pub value: P<MetaItem>,
+    pub value: MetaItem,
     pub is_sugared_doc: bool,
+    pub span: Span,
 }
 
 /// TraitRef's appear in impls.
index 2977e340a3c0c10b2e9f50320fc8a80f1ebe6692..45c120e0b95ca44daa6fc7445707efd986e822f6 100644 (file)
 pub use self::IntType::*;
 
 use ast;
-use ast::{AttrId, Attribute, Attribute_};
+use ast::{AttrId, Attribute, Name};
 use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
 use ast::{Lit, Expr, Item, Local, Stmt, StmtKind};
-use codemap::{respan, spanned, dummy_spanned};
+use codemap::{spanned, dummy_spanned, mk_sp};
 use syntax_pos::{Span, BytePos, DUMMY_SP};
 use errors::Handler;
 use feature_gate::{Features, GatedCfg};
 use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
-use parse::token::InternedString;
-use parse::{ParseSess, token};
+use parse::ParseSess;
 use ptr::P;
+use symbol::Symbol;
 use util::ThinVec;
 
 use std::cell::{RefCell, Cell};
@@ -37,8 +37,8 @@
 }
 
 enum AttrError {
-    MultipleItem(InternedString),
-    UnknownMetaItem(InternedString),
+    MultipleItem(Name),
+    UnknownMetaItem(Name),
     MissingSince,
     MissingFeature,
     MultipleStabilityLevels,
@@ -61,7 +61,7 @@ fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
 
 pub fn mark_used(attr: &Attribute) {
     debug!("Marking {:?} as used.", attr);
-    let AttrId(id) = attr.node.id;
+    let AttrId(id) = attr.id;
     USED_ATTRS.with(|slot| {
         let idx = (id / 64) as usize;
         let shift = id % 64;
@@ -73,7 +73,7 @@ pub fn mark_used(attr: &Attribute) {
 }
 
 pub fn is_used(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.node.id;
+    let AttrId(id) = attr.id;
     USED_ATTRS.with(|slot| {
         let idx = (id / 64) as usize;
         let shift = id % 64;
@@ -84,7 +84,7 @@ pub fn is_used(attr: &Attribute) -> bool {
 
 pub fn mark_known(attr: &Attribute) {
     debug!("Marking {:?} as known.", attr);
-    let AttrId(id) = attr.node.id;
+    let AttrId(id) = attr.id;
     KNOWN_ATTRS.with(|slot| {
         let idx = (id / 64) as usize;
         let shift = id % 64;
@@ -96,7 +96,7 @@ pub fn mark_known(attr: &Attribute) {
 }
 
 pub fn is_known(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.node.id;
+    let AttrId(id) = attr.id;
     KNOWN_ATTRS.with(|slot| {
         let idx = (id / 64) as usize;
         let shift = id % 64;
@@ -107,7 +107,7 @@ pub fn is_known(attr: &Attribute) -> bool {
 
 impl NestedMetaItem {
     /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem.
-    pub fn meta_item(&self) -> Option<&P<MetaItem>> {
+    pub fn meta_item(&self) -> Option<&MetaItem> {
         match self.node {
             NestedMetaItemKind::MetaItem(ref item) => Some(&item),
             _ => None
@@ -134,18 +134,18 @@ pub fn check_name(&self, name: &str) -> bool {
 
     /// 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 {
@@ -186,16 +186,16 @@ pub fn is_meta_item_list(&self) -> bool {
 
 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()
     }
 
@@ -218,17 +218,13 @@ pub fn is_value_str(&self) -> bool {
 }
 
 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,
@@ -240,14 +236,14 @@ pub fn value_str(&self) -> Option<InternedString> {
 
     pub fn meta_item_list(&self) -> Option<&[NestedMetaItem]> {
         match self.node {
-            MetaItemKind::List(_, ref l) => Some(&l[..]),
+            MetaItemKind::List(ref l) => Some(&l[..]),
             _ => None
         }
     }
 
     pub fn is_word(&self) -> bool {
         match self.node {
-            MetaItemKind::Word(_) => true,
+            MetaItemKind::Word => true,
             _ => false,
         }
     }
@@ -255,7 +251,7 @@ pub fn is_word(&self) -> bool {
     pub fn span(&self) -> Span { self.span }
 
     pub fn check_name(&self, name: &str) -> bool {
-        name == &self.name()[..]
+        self.name() == name
     }
 
     pub fn is_value_str(&self) -> bool {
@@ -270,7 +266,7 @@ pub fn is_meta_item_list(&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
@@ -279,16 +275,15 @@ pub fn meta(&self) -> &MetaItem {
     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)
@@ -298,41 +293,37 @@ pub fn with_desugared_doc<T, F>(&self, f: F) -> T where
 
 /* 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 }
 }
 
 
@@ -349,71 +340,63 @@ pub fn mk_attr_id() -> AttrId {
 }
 
 /// Returns an inner attribute with the given value.
-pub fn mk_attr_inner(id: AttrId, item: P<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 {
@@ -432,15 +415,13 @@ pub fn contains_name(attrs: &[Attribute], name: &str) -> bool {
     })
 }
 
-pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
-                                 -> Option<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))
@@ -449,12 +430,12 @@ pub fn last_meta_item_value_str_by_name(items: &[P<MetaItem>], name: &str)
 
 /* 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() {
@@ -488,13 +469,14 @@ pub enum InlineAttr {
 
 /// Determine what `#[inline]` attribute is present in `attrs`, if any.
 pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
-    attrs.iter().fold(InlineAttr::None, |ia,attr| {
-        match attr.node.value.node {
-            MetaItemKind::Word(ref n) if n == "inline" => {
+    attrs.iter().fold(InlineAttr::None, |ia, attr| {
+        match attr.value.node {
+            _ if attr.value.name != "inline" => ia,
+            MetaItemKind::Word => {
                 mark_used(attr);
                 InlineAttr::Hint
             }
-            MetaItemKind::List(ref n, ref items) if n == "inline" => {
+            MetaItemKind::List(ref items) => {
                 mark_used(attr);
                 if items.len() != 1 {
                     diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
@@ -527,7 +509,7 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool {
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
     match cfg.node {
-        ast::MetaItemKind::List(ref pred, ref mis) => {
+        ast::MetaItemKind::List(ref mis) => {
             for mi in mis.iter() {
                 if !mi.is_meta_item() {
                     handle_errors(&sess.span_diagnostic, mi.span, AttrError::UnsupportedLiteral);
@@ -537,7 +519,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
 
             // The unwraps below may look dangerous, but we've already asserted
             // that they won't fail with the loop above.
-            match &pred[..] {
+            match &*cfg.name.as_str() {
                 "any" => mis.iter().any(|mi| {
                     cfg_matches(mi.meta_item().unwrap(), sess, features)
                 }),
@@ -558,11 +540,11 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
                 }
             }
         },
-        ast::MetaItemKind::Word(_) | ast::MetaItemKind::NameValue(..) => {
+        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
             if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) {
                 gated_cfg.check_and_emit(sess, feats);
             }
-            contains(&sess.config, cfg)
+            sess.config.contains(&(cfg.name(), cfg.value_str()))
         }
     }
 }
@@ -571,7 +553,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
-    pub feature: InternedString,
+    pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
 }
 
@@ -579,20 +561,20 @@ pub struct Stability {
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
-    Unstable { reason: Option<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 {
@@ -611,7 +593,6 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
 
     'outer: for attr in attrs_iter {
         let tag = attr.name();
-        let tag = &*tag;
         if tag != "rustc_deprecated" && tag != "unstable" && tag != "stable" {
             continue // not a stability level
         }
@@ -619,7 +600,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         mark_used(attr);
 
         if let Some(metas) = attr.meta_item_list() {
-            let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
                     handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
@@ -633,7 +614,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 }
             };
 
-            match tag {
+            match &*tag.as_str() {
                 "rustc_deprecated" => {
                     if rustc_depr.is_some() {
                         span_err!(diagnostic, item_sp, E0540,
@@ -645,7 +626,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     let mut reason = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name() {
+                            match &*mi.name().as_str() {
                                 "since" => if !get(mi, &mut since) { continue 'outer },
                                 "reason" => if !get(mi, &mut reason) { continue 'outer },
                                 _ => {
@@ -688,7 +669,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     let mut issue = None;
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
-                            match &*mi.name() {
+                            match &*mi.name().as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "reason" => if !get(mi, &mut reason) { continue 'outer },
                                 "issue" => if !get(mi, &mut issue) { continue 'outer },
@@ -710,7 +691,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                 level: Unstable {
                                     reason: reason,
                                     issue: {
-                                        if let Ok(issue) = issue.parse() {
+                                        if let Ok(issue) = issue.as_str().parse() {
                                             issue
                                         } else {
                                             span_err!(diagnostic, attr.span(), E0545,
@@ -743,7 +724,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                     let mut since = None;
                     for meta in metas {
                         if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                            match &*mi.name() {
+                            match &*mi.name().as_str() {
                                 "feature" => if !get(mi, &mut feature) { continue 'outer },
                                 "since" => if !get(mi, &mut since) { continue 'outer },
                                 _ => {
@@ -821,7 +802,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
         }
 
         depr = if let Some(metas) = attr.meta_item_list() {
-            let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
                 if item.is_some() {
                     handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name()));
                     return false
@@ -839,7 +820,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler,
             let mut note = None;
             for meta in metas {
                 if let NestedMetaItemKind::MetaItem(ref mi) = meta.node {
-                    match &*mi.name() {
+                    match &*mi.name().as_str() {
                         "since" => if !get(mi, &mut since) { continue 'outer },
                         "note" => if !get(mi, &mut note) { continue 'outer },
                         _ => {
@@ -875,7 +856,7 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute],
     find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
 }
 
-pub fn require_unique_names(diagnostic: &Handler, metas: &[P<MetaItem>]) {
+pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) {
     let mut set = HashSet::new();
     for meta in metas {
         let name = meta.name();
@@ -896,8 +877,8 @@ pub fn require_unique_names(diagnostic: &Handler, metas: &[P<MetaItem>]) {
 /// 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() {
@@ -906,7 +887,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                 }
 
                 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),
index 49012ad036a9a9211a43d6ac0855beee96eae1e5..3cdfa718eabae2a7f85568b8c3dea57bc42cd494 100644 (file)
@@ -871,6 +871,7 @@ fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option<Span> {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use symbol::keywords;
     use std::rc::Rc;
 
     #[test]
@@ -1097,10 +1098,9 @@ fn t10() {
     #[test]
     fn t11() {
         // Test span_to_expanded_string works with expansion
-        use ast::Name;
         let cm = init_code_map();
         let root = Span { lo: BytePos(0), hi: BytePos(11), expn_id: NO_EXPANSION };
-        let format = ExpnFormat::MacroBang(Name(0u32));
+        let format = ExpnFormat::MacroBang(keywords::Invalid.name());
         let callee = NameAndSpan { format: format,
                                    allow_internal_unstable: false,
                                    span: None };
@@ -1197,11 +1197,9 @@ fn span_substr(&self,
     fn init_expansion_chain(cm: &CodeMap) -> Span {
         // Creates an expansion chain containing two recursive calls
         // root -> expA -> expA -> expB -> expB -> end
-        use ast::Name;
-
         let root = Span { lo: BytePos(0), hi: BytePos(11), expn_id: NO_EXPANSION };
 
-        let format_root = ExpnFormat::MacroBang(Name(0u32));
+        let format_root = ExpnFormat::MacroBang(keywords::Invalid.name());
         let callee_root = NameAndSpan { format: format_root,
                                         allow_internal_unstable: false,
                                         span: Some(root) };
@@ -1210,7 +1208,7 @@ fn init_expansion_chain(cm: &CodeMap) -> Span {
         let id_a1 = cm.record_expansion(info_a1);
         let span_a1 = Span { lo: BytePos(12), hi: BytePos(23), expn_id: id_a1 };
 
-        let format_a = ExpnFormat::MacroBang(Name(1u32));
+        let format_a = ExpnFormat::MacroBang(keywords::As.name());
         let callee_a = NameAndSpan { format: format_a,
                                       allow_internal_unstable: false,
                                       span: Some(span_a1) };
@@ -1223,7 +1221,7 @@ fn init_expansion_chain(cm: &CodeMap) -> Span {
         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 };
index 02429f02738fdcfe5c7bc77845d993443b3458e8..89eea3f6f8b288790ed0648bc293db97f15f9228 100644 (file)
@@ -12,7 +12,7 @@
 use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue};
 use {fold, attr};
 use ast;
-use codemap::{Spanned, respan};
+use codemap::Spanned;
 use parse::ParseSess;
 use ptr::P;
 
@@ -106,12 +106,13 @@ fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
         match (cfg.meta_item(), mi.meta_item()) {
             (Some(cfg), Some(mi)) =>
                 if cfg_matches(&cfg, self.sess, self.features) {
-                    self.process_cfg_attr(respan(mi.span, ast::Attribute_ {
+                    self.process_cfg_attr(ast::Attribute {
                         id: attr::mk_attr_id(),
-                        style: attr.node.style,
+                        style: attr.style,
                         value: mi.clone(),
                         is_sugared_doc: false,
-                    }))
+                        span: mi.span,
+                    })
                 } else {
                     None
                 },
@@ -131,8 +132,8 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
                 return false;
             }
 
-            let mis = match attr.node.value.node {
-                ast::MetaItemKind::List(_, ref mis) if is_cfg(&attr) => mis,
+            let mis = match attr.value.node {
+                ast::MetaItemKind::List(ref mis) if is_cfg(&attr) => mis,
                 _ => return true
             };
 
@@ -160,7 +161,7 @@ fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) {
                                           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();
index 81c8e0bdb8262c082835f9713470b87eebd880e4..fe5cb87ad59b5c89370490754c45576b6bcad900 100644 (file)
@@ -19,6 +19,7 @@
 use ext::build::AstBuilder;
 use parse::token;
 use ptr::P;
+use symbol::Symbol;
 use tokenstream::{TokenTree};
 use util::small_vector::SmallVector;
 
@@ -141,7 +142,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
             ));
         }
     });
-    let sym = Ident::with_empty_ctxt(token::gensym(&format!(
+    let sym = Ident::with_empty_ctxt(Symbol::gensym(&format!(
         "__register_diagnostic_{}", code
     )));
     MacEager::items(SmallVector::many(vec![
@@ -194,11 +195,11 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
     let (count, expr) =
         with_registered_diagnostics(|diagnostics| {
             let descriptions: Vec<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();
index 7014e576e2b8a36e2390e3da39262d03bf8c30a1..93ca1948ed84b878b2e2b57b627b133d5129abeb 100644 (file)
@@ -28,7 +28,7 @@ pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
                 EntryPointType::Start
             } else if attr::contains_name(&item.attrs, "main") {
                 EntryPointType::MainAttr
-            } else if item.ident.name.as_str() == "main" {
+            } else if item.ident.name == "main" {
                 if depth == 1 {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
index 7f66b060052ea06dd34bafbd4cc714bd1fd934ba..ddbca47429d1876298601836b0ed032e2d1ed1b7 100644 (file)
 use ext::expand::{self, Expansion};
 use ext::hygiene::Mark;
 use fold::{self, Folder};
-use parse::{self, parser};
+use parse::{self, parser, DirectoryOwnership};
 use parse::token;
-use parse::token::{InternedString, str_to_ident};
 use ptr::P;
+use symbol::Symbol;
 use util::small_vector::SmallVector;
 
 use std::path::PathBuf;
@@ -568,9 +568,7 @@ pub struct ExpansionData {
     pub depth: usize,
     pub backtrace: ExpnId,
     pub module: Rc<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;
@@ -601,7 +599,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
                 depth: 0,
                 backtrace: NO_EXPANSION,
                 module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
-                no_noninline_mod: false,
+                directory_ownership: DirectoryOwnership::Owned,
             },
         }
     }
@@ -643,7 +641,7 @@ pub fn expansion_cause(&self) -> Span {
         loop {
             if self.codemap().with_expn_info(expn_id, |info| {
                 info.map_or(None, |i| {
-                    if i.callee.name().as_str() == "include" {
+                    if i.callee.name() == "include" {
                         // Stop going up the backtrace once include! is encountered
                         return None;
                     }
@@ -735,7 +733,7 @@ pub fn set_trace_macros(&mut self, x: bool) {
         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();
@@ -746,7 +744,7 @@ pub fn std_path(&self, components: &[&str]) -> Vec<ast::Ident> {
         return v
     }
     pub fn name_of(&self, st: &str) -> ast::Name {
-        token::intern(st)
+        Symbol::intern(st)
     }
 }
 
@@ -754,7 +752,7 @@ pub fn name_of(&self, st: &str) -> ast::Name {
 /// 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();
@@ -765,7 +763,7 @@ pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &st
     let expr = cx.expander().fold_expr(expr);
     match expr.node {
         ast::ExprKind::Lit(ref l) => match l.node {
-            ast::LitKind::Str(ref s, style) => return Some(respan(expr.span, (s.clone(), style))),
+            ast::LitKind::Str(s, style) => return Some(respan(expr.span, (s, style))),
             _ => cx.span_err(l.span, err_msg)
         },
         _ => cx.span_err(expr.span, err_msg)
@@ -774,7 +772,7 @@ pub fn expr_to_spanned_string(cx: &mut ExtCtxt, expr: P<ast::Expr>, err_msg: &st
 }
 
 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)
 }
 
index c3e28cbb006a07795499c4af50cae727df286ed4..a208b934d79e1da09b7ca1b31ba069b7aca824dd 100644 (file)
@@ -14,8 +14,8 @@
 use syntax_pos::{Span, DUMMY_SP, Pos};
 use codemap::{dummy_spanned, respan, Spanned};
 use ext::base::ExtCtxt;
-use parse::token::{self, keywords, InternedString};
 use ptr::P;
+use symbol::{Symbol, keywords};
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
@@ -149,7 +149,7 @@ fn expr_struct_ident(&self, span: Span, id: ast::Ident,
     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>;
@@ -158,7 +158,7 @@ fn expr_struct_ident(&self, span: Span, id: ast::Ident,
 
     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>;
@@ -275,22 +275,22 @@ fn item_ty_poly(&self,
                     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>;
@@ -755,7 +755,7 @@ 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> {
         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))
     }
 
@@ -777,7 +777,7 @@ fn expr_none(&self, sp: Span) -> P<ast::Expr> {
 
 
     fn expr_break(&self, sp: Span) -> P<ast::Expr> {
-        self.expr(sp, ast::ExprKind::Break(None))
+        self.expr(sp, ast::ExprKind::Break(None, None))
     }
 
 
@@ -785,10 +785,9 @@ fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
         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);
@@ -801,9 +800,7 @@ fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr> {
     }
 
     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> {
@@ -1146,25 +1143,25 @@ fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> P<ast::Item> {
         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))
     }
 
index 8e0c3ce8448da46c983e8ddd186fe2e85c25907b..fd6cae1e1b6688bbfdea9b91da5935b06d5fad99 100644 (file)
 use feature_gate::{self, Features};
 use fold;
 use fold::*;
-use parse::{ParseSess, PResult, lexer};
+use parse::{ParseSess, DirectoryOwnership, PResult, lexer};
 use parse::parser::Parser;
-use parse::token::{self, intern, keywords};
+use parse::token;
 use print::pprust;
 use ptr::P;
 use std_inject;
+use symbol::keywords;
 use tokenstream::{TokenTree, TokenStream};
 use util::small_vector::SmallVector;
 use visit::Visitor;
@@ -190,7 +191,7 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
     pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
         self.cx.crate_root = std_inject::injected_crate_name(&krate);
         let mut module = ModuleData {
-            mod_path: vec![token::str_to_ident(&self.cx.ecfg.crate_name)],
+            mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
             directory: PathBuf::from(self.cx.codemap().span_to_filename(krate.span)),
         };
         module.directory.pop();
@@ -246,7 +247,7 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
                     self.cx.resolver.resolve_macro(scope, &mac.node.path, force)
                 }
                 InvocationKind::Attr { ref attr, .. } => {
-                    let ident = ast::Ident::with_empty_ctxt(intern(&*attr.name()));
+                    let ident = Ident::with_empty_ctxt(attr.name());
                     let path = ast::Path::from_ident(attr.span, ident);
                     self.cx.resolver.resolve_macro(scope, &path, force)
                 }
@@ -341,7 +342,7 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
         };
 
         attr::mark_used(&attr);
-        let name = intern(&attr.name());
+        let name = attr.name();
         self.cx.bt_push(ExpnInfo {
             call_site: attr.span,
             callee: NameAndSpan {
@@ -353,12 +354,12 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
 
         match *ext {
             MultiModifier(ref mac) => {
-                let item = mac.expand(self.cx, attr.span, &attr.node.value, item);
+                let item = mac.expand(self.cx, attr.span, &attr.value, item);
                 kind.expect_from_annotatables(item)
             }
             MultiDecorator(ref mac) => {
                 let mut items = Vec::new();
-                mac.expand(self.cx, attr.span, &attr.node.value, &item,
+                mac.expand(self.cx, attr.span, &attr.value, &item,
                            &mut |item| items.push(item));
                 items.push(item);
                 kind.expect_from_annotatables(items)
@@ -726,9 +727,10 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
     }
 
     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
     }
 
@@ -767,7 +769,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
                     return noop_fold_item(item, self);
                 }
 
-                let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod;
+                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
                 let mut module = (*self.cx.current_expansion.module).clone();
                 module.mod_path.push(item.ident);
 
@@ -778,23 +780,28 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
 
                 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.
index e323dd2f623276c16de3cfd6682194867f5c1ec1..4fe57a8345e94e707c71192c0f5f0f3bb8b06cbf 100644 (file)
@@ -13,8 +13,8 @@
 use ext::base::ExtCtxt;
 use ext::expand::{Expansion, ExpansionKind};
 use fold::*;
-use parse::token::{intern, keywords};
 use ptr::P;
+use symbol::{Symbol, keywords};
 use util::move_map::MoveMap;
 use util::small_vector::SmallVector;
 
@@ -227,7 +227,7 @@ pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion {
                     span: DUMMY_SP,
                     global: false,
                     segments: vec![ast::PathSegment {
-                        identifier: ast::Ident::with_empty_ctxt(intern("macro_rules")),
+                        identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")),
                         parameters: ast::PathParameters::none(),
                     }],
                 },
index dc3a01f41bc9db92392877a147d44d9ac48923f8..21ce89a6dd5be7d54ec78a3d4dde8a87082e2048 100644 (file)
@@ -66,6 +66,7 @@ pub mod prelude {
     pub use ast::Ident;
     pub use codemap::{DUMMY_SP, Span};
     pub use ext::base::{ExtCtxt, MacResult};
-    pub use parse::token::{self, Token, DelimToken, keywords, str_to_ident};
+    pub use parse::token::{self, Token, DelimToken};
+    pub use symbol::keywords;
     pub use tokenstream::{TokenTree, TokenStream};
 }
index 969cfa292ce8068315fea22fd6d587851647264f..aa777a19a9bcba047fe91ca30f841f19f38be83d 100644 (file)
@@ -33,6 +33,7 @@ pub mod rt {
     use parse::{self, token, classify};
     use ptr::P;
     use std::rc::Rc;
+    use symbol::Symbol;
 
     use tokenstream::{self, TokenTree};
 
@@ -211,7 +212,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<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)))]
@@ -223,13 +224,13 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
             let mut r = vec![];
             // FIXME: The spans could be better
             r.push(TokenTree::Token(self.span, token::Pound));
-            if self.node.style == ast::AttrStyle::Inner {
+            if self.style == ast::AttrStyle::Inner {
                 r.push(TokenTree::Token(self.span, token::Not));
             }
             r.push(TokenTree::Delimited(self.span, Rc::new(tokenstream::Delimited {
                 delim: token::Bracket,
                 open_span: self.span,
-                tts: self.node.value.to_tokens(cx),
+                tts: self.value.to_tokens(cx),
                 close_span: self.span,
             })));
             r
@@ -238,8 +239,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
 
     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)
         }
     }
@@ -405,7 +405,7 @@ pub fn parse_block_panic(parser: &mut Parser) -> P<Block> {
     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())
 }
 
@@ -527,17 +527,17 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt,
     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"),
@@ -546,7 +546,7 @@ fn mk_ident(cx: &ExtCtxt, sp: Span, ident: ast::Ident) -> P<ast::Expr> {
 
 // 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"),
index bda84cdaf39eb6d568e98ff900c1551b97ad964b..39b92c7d007dec77b151fd23129b3b9b0e02fbfb 100644 (file)
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
-use parse::token;
+use parse::{token, DirectoryOwnership};
 use parse;
 use print::pprust;
 use ptr::P;
+use symbol::Symbol;
 use tokenstream;
 use util::small_vector::SmallVector;
 
@@ -60,15 +61,13 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
 
     let topmost = cx.expansion_cause();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
-    let filename = token::intern_and_get_ident(&loc.file.name);
-    base::MacEager::expr(cx.expr_str(topmost, filename))
+    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name)))
 }
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                         -> Box<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])
@@ -77,9 +76,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
     let mod_path = &cx.current_expansion.module.mod_path;
     let string = mod_path.iter().map(|x| x.to_string()).collect::<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
@@ -93,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
     };
     // The file will be added to the code map by the parser
     let path = res_rel_file(cx, sp, Path::new(&file));
-    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, true, None, sp);
+    let directory_ownership = DirectoryOwnership::Owned;
+    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
 
     struct ExpandResult<'a> {
         p: parse::parser::Parser<'a>,
@@ -144,10 +142,9 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT
             // Add this input file to the code map to make it available as
             // dependency information
             let filename = format!("{}", file.display());
-            let interned = token::intern_and_get_ident(&src[..]);
             cx.codemap().new_filemap_and_lines(&filename, None, &src);
 
-            base::MacEager::expr(cx.expr_str(sp, interned))
+            base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&src)))
         }
         Err(_) => {
             cx.span_err(sp,
index 552d4de961740f4c59b749b30ba9fde36719d75e..4164b4a93ec91d4c91d65bcc65950730eff905e5 100644 (file)
 use ext::tt::macro_parser::{parse, parse_failure_msg};
 use parse::ParseSess;
 use parse::lexer::new_tt_reader;
-use parse::parser::{Parser, Restrictions};
-use parse::token::{self, gensym_ident, NtTT, Token};
+use parse::parser::Parser;
+use parse::token::{self, NtTT, Token};
 use parse::token::Token::*;
 use print;
+use symbol::Symbol;
 use tokenstream::{self, TokenTree};
 
 use std::collections::{HashMap};
@@ -116,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 let trncbr =
                     new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs);
                 let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr));
-                p.directory = cx.current_expansion.module.directory.clone();
-                p.restrictions = match cx.current_expansion.no_noninline_mod {
-                    true => Restrictions::NO_NONINLINE_MOD,
-                    false => Restrictions::empty(),
-                };
+                let module = &cx.current_expansion.module;
+                p.directory.path = module.directory.clone();
+                p.directory.ownership = cx.current_expansion.directory_ownership;
+                p.root_module_name =
+                    module.mod_path.last().map(|id| (*id.name.as_str()).to_owned());
+
                 p.check_unknown_macro_variable();
                 // Let the context choose how to interpret the result.
                 // Weird, but useful for X-macros.
@@ -187,16 +189,16 @@ fn expand(&self,
 
 /// Converts a `macro_rules!` invocation into a syntax extension.
 pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
-    let lhs_nm =  gensym_ident("lhs");
-    let rhs_nm =  gensym_ident("rhs");
+    let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs"));
+    let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs"));
 
     // The pattern that macro_rules matches.
     // The grammar for macro_rules! is:
     // $( $lhs:tt => $rhs:tt );+
     // ...quasiquoting this would be nice.
     // These spans won't matter, anyways
-    let match_lhs_tok = MatchNt(lhs_nm, token::str_to_ident("tt"));
-    let match_rhs_tok = MatchNt(rhs_nm, token::str_to_ident("tt"));
+    let match_lhs_tok = MatchNt(lhs_nm, ast::Ident::from_str("tt"));
+    let match_rhs_tok = MatchNt(rhs_nm, ast::Ident::from_str("tt"));
     let argument_gram = vec![
         TokenTree::Sequence(DUMMY_SP, Rc::new(tokenstream::SequenceRepetition {
             tts: vec![
@@ -790,8 +792,7 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
             "pat" => {
                 match *tok {
                     FatArrow | Comma | Eq | BinOp(token::Or) => Ok(true),
-                    Ident(i) if (i.name.as_str() == "if" ||
-                                 i.name.as_str() == "in") => Ok(true),
+                    Ident(i) if i.name == "if" || i.name == "in" => Ok(true),
                     _ => Ok(false)
                 }
             },
@@ -799,8 +800,8 @@ fn is_in_follow(tok: &Token, frag: &str) -> Result<bool, (String, &'static str)>
                 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)
                 }
             },
index ea66fdc31cf08e7ce59d07a288cb2fb0869799d9..aa6a29b78b075d2263a5eb2ed194161f371db08e 100644 (file)
@@ -33,7 +33,7 @@
 use errors::{DiagnosticBuilder, Handler};
 use visit::{self, FnKind, Visitor};
 use parse::ParseSess;
-use parse::token::InternedString;
+use symbol::Symbol;
 
 use std::ascii::AsciiExt;
 use std::env;
@@ -59,9 +59,9 @@ macro_rules! declare_features {
         /// A set of features to be used by later passes.
         pub struct Features {
             /// #![feature] attrs for stable language features, for error reporting
-            pub declared_stable_lang_features: Vec<(InternedString, Span)>,
+            pub declared_stable_lang_features: Vec<(Symbol, Span)>,
             /// #![feature] attrs for non-language (library) features
-            pub declared_lib_features: Vec<(InternedString, Span)>,
+            pub declared_lib_features: Vec<(Symbol, Span)>,
             $(pub $feature: bool),+
         }
 
@@ -284,9 +284,6 @@ pub fn new() -> Features {
     // instead of just the platforms on which it is the C ABI
     (active, abi_sysv64, "1.13.0", Some(36167)),
 
-    // Use the import semantics from RFC 1560.
-    (active, item_like_imports, "1.13.0", Some(35120)),
-
     // Macros 1.1
     (active, proc_macro, "1.13.0", Some(35900)),
 
@@ -316,6 +313,9 @@ pub fn new() -> Features {
     (active, link_cfg, "1.14.0", Some(37406)),
 
     (active, use_extern_macros, "1.15.0", Some(35896)),
+
+    // Allows `break {expr}` with a value inside `loop`s.
+    (active, loop_break_value, "1.14.0", Some(37339)),
 );
 
 declare_features! (
@@ -362,6 +362,7 @@ pub fn new() -> Features {
     (accepted, question_mark, "1.13.0", Some(31436)),
     // Allows `..` in tuple (struct) patterns
     (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
+    (accepted, item_like_imports, "1.14.0", Some(35120)),
 );
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -757,7 +758,7 @@ pub struct GatedCfg {
 
 impl GatedCfg {
     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
-        let name = cfg.name();
+        let name = &*cfg.name().as_str();
         GATED_CFGS.iter()
                   .position(|info| info.0 == name)
                   .map(|idx| {
@@ -804,7 +805,7 @@ macro_rules! gate_feature {
 impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = &*attr.name();
+        let name = &*attr.name().as_str();
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if n == name {
                 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
@@ -991,11 +992,11 @@ fn contains_novel_literal(item: &ast::MetaItem) -> bool {
     use ast::NestedMetaItemKind::*;
 
     match item.node {
-        Word(..) => false,
-        NameValue(_, ref lit) => !lit.node.is_str(),
-        List(_, ref list) => list.iter().any(|li| {
+        Word => false,
+        NameValue(ref lit) => !lit.node.is_str(),
+        List(ref list) => list.iter().any(|li| {
             match li.node {
-                MetaItem(ref mi) => contains_novel_literal(&**mi),
+                MetaItem(ref mi) => contains_novel_literal(&mi),
                 Literal(_) => true,
             }
         }),
@@ -1013,7 +1014,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
             self.context.check_attribute(attr, false);
         }
 
-        if contains_novel_literal(&*(attr.node.value)) {
+        if contains_novel_literal(&attr.value) {
             gate_feature_post!(&self, attr_literals, attr.span,
                                "non-string literals in attributes, or string \
                                literals in top-level positions, are experimental");
@@ -1121,9 +1122,8 @@ fn visit_item(&mut self, i: &ast::Item) {
     }
 
     fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
-        let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs,
-                                                                     "link_name") {
-            Some(val) => val.starts_with("llvm."),
+        let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
+            Some(val) => val.as_str().starts_with("llvm."),
             _ => false
         };
         if links_to_llvm {
@@ -1192,6 +1192,10 @@ fn visit_expr(&mut self, e: &ast::Expr) {
                     }
                 }
             }
+            ast::ExprKind::Break(_, Some(_)) => {
+                gate_feature_post!(&self, loop_break_value, e.span,
+                                   "`break` with a value is experimental");
+            }
             _ => {}
         }
         visit::walk_expr(self, e);
index 2e62f23578d815884167938f18949d42c69beb9a..6af8efb2a195c6c3408a568b2fa0b8a8f7c04568 100644 (file)
@@ -22,8 +22,9 @@
 use ast;
 use syntax_pos::Span;
 use codemap::{Spanned, respan};
-use parse::token::{self, keywords};
+use parse::token;
 use ptr::P;
+use symbol::keywords;
 use tokenstream::*;
 use util::small_vector::SmallVector;
 use util::move_map::MoveMap;
@@ -43,7 +44,7 @@ fn fold_crate(&mut self, c: Crate) -> Crate {
         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)
     }
 
@@ -51,7 +52,7 @@ fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
         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)
     }
 
@@ -293,8 +294,7 @@ fn new_span(&mut self, sp: Span) -> Span {
     }
 }
 
-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))
 }
 
@@ -486,16 +486,13 @@ pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
     })
 }
 
-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),
     })
 }
 
@@ -522,17 +519,18 @@ pub fn noop_fold_meta_list_item<T: Folder>(li: NestedMetaItem, fld: &mut T)
     }
 }
 
-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 {
@@ -1240,10 +1238,11 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                 });
                 ExprKind::Path(qself, folder.fold_path(path))
             }
-            ExprKind::Break(opt_ident) => ExprKind::Break(opt_ident.map(|label|
-                respan(folder.new_span(label.span),
-                       folder.fold_ident(label.node)))
-            ),
+            ExprKind::Break(opt_ident, opt_expr) => {
+                ExprKind::Break(opt_ident.map(|label| respan(folder.new_span(label.span),
+                                                             folder.fold_ident(label.node))),
+                                opt_expr.map(|e| folder.fold_expr(e)))
+            }
             ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label|
                 respan(folder.new_span(label.span),
                        folder.fold_ident(label.node)))
@@ -1334,9 +1333,8 @@ pub fn noop_fold_vis<T: Folder>(vis: Visibility, folder: &mut T) -> Visibility {
 #[cfg(test)]
 mod tests {
     use std::io;
-    use ast;
+    use ast::{self, Ident};
     use util::parser_testing::{string_to_crate, matches_codepattern};
-    use parse::token;
     use print::pprust;
     use fold;
     use super::*;
@@ -1352,7 +1350,7 @@ fn fake_print_crate(s: &mut pprust::State,
 
     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)
index 34280812421a131f74ca0db319e67365f452f38c..5a1b0d4005e17e12f14303a9dfe0e2b08dcc4dfb 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(associated_consts)]
 #![feature(const_fn)]
 #![feature(libc)]
+#![feature(optin_builtin_traits)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_escape)]
@@ -83,7 +84,6 @@ pub mod diagnostics {
 pub mod diagnostic_list;
 
 pub mod util {
-    pub mod interner;
     pub mod lev_distance;
     pub mod node_count;
     pub mod parser;
@@ -118,6 +118,7 @@ pub mod syntax {
 pub mod show_span;
 pub mod std_inject;
 pub mod str;
+pub mod symbol;
 pub mod test;
 pub mod tokenstream;
 pub mod visit;
index 983c882eafca31298542d0a2a53ee7d44eca1dd8..ded676da3c6761baa0adb4c3cc273836ca375b22 100644 (file)
 use attr;
 use ast;
 use syntax_pos::{mk_sp, Span};
-use codemap::{spanned, Spanned};
+use codemap::spanned;
 use parse::common::SeqSep;
 use parse::PResult;
 use parse::token;
 use parse::parser::{Parser, TokenType};
-use ptr::P;
 
 #[derive(PartialEq, Eq, Debug)]
 enum InnerAttributeParsePolicy<'a> {
@@ -49,13 +48,9 @@ pub fn parse_outer_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
                     just_parsed_doc_comment = false;
                 }
                 token::DocComment(s) => {
-                    let attr = ::attr::mk_sugared_doc_attr(
-                        attr::mk_attr_id(),
-                        self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)),
-                        self.span.lo,
-                        self.span.hi
-                    );
-                    if attr.node.style != ast::AttrStyle::Outer {
+                    let Span { lo, hi, .. } = self.span;
+                    let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, lo, hi);
+                    if attr.style != ast::AttrStyle::Outer {
                         let mut err = self.fatal("expected outer doc comment");
                         err.note("inner doc comments like this (starting with \
                                   `//!` or `/*!`) can only appear before items");
@@ -145,14 +140,12 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
             style = ast::AttrStyle::Inner;
         }
 
-        Ok(Spanned {
+        Ok(ast::Attribute {
+            id: attr::mk_attr_id(),
+            style: style,
+            value: value,
+            is_sugared_doc: false,
             span: span,
-            node: ast::Attribute_ {
-                id: attr::mk_attr_id(),
-                style: style,
-                value: value,
-                is_sugared_doc: false,
-            },
         })
     }
 
@@ -172,15 +165,14 @@ pub fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
                     }
 
                     let attr = self.parse_attribute(true)?;
-                    assert!(attr.node.style == ast::AttrStyle::Inner);
+                    assert!(attr.style == ast::AttrStyle::Inner);
                     attrs.push(attr);
                 }
                 token::DocComment(s) => {
                     // we need to get the position of this token before we bump.
                     let Span { lo, hi, .. } = self.span;
-                    let str = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s));
-                    let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
-                    if attr.node.style == ast::AttrStyle::Inner {
+                    let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, lo, hi);
+                    if attr.style == ast::AttrStyle::Inner {
                         attrs.push(attr);
                         self.bump();
                     } else {
@@ -213,7 +205,7 @@ fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
     ///
     /// 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()),
@@ -229,24 +221,15 @@ pub fn parse_meta_item(&mut self) -> PResult<'a, P<ast::MetaItem>> {
 
         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) ;
index cf48c445c80ebf24f2be8bb15467ecba278aab70..681dec0ab564d1c922cf60320583f43314e06331 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast;
+use ast::{self, Ident};
 use syntax_pos::{self, BytePos, CharPos, Pos, Span};
 use codemap::CodeMap;
 use errors::{FatalError, Handler, DiagnosticBuilder};
 use ext::tt::transcribe::tt_next_token;
-use parse::token::{self, keywords, str_to_ident};
+use parse::token;
 use str::char_at;
+use symbol::{Symbol, keywords};
 use rustc_unicode::property::Pattern_White_Space;
 
 use std::borrow::Cow;
@@ -350,13 +351,13 @@ pub fn with_str_from<T, F>(&self, start: BytePos, f: F) -> T
     /// single-byte delimiter).
     pub fn name_from(&self, start: BytePos) -> ast::Name {
         debug!("taking an ident from {:?} to {:?}", start, self.pos);
-        self.with_str_from(start, token::intern)
+        self.with_str_from(start, Symbol::intern)
     }
 
     /// As name_from, with an explicit endpoint.
     pub fn name_from_to(&self, start: BytePos, end: BytePos) -> ast::Name {
         debug!("taking an ident from {:?} to {:?}", start, end);
-        self.with_str_from_to(start, end, token::intern)
+        self.with_str_from_to(start, end, Symbol::intern)
     }
 
     /// Calls `f` with a string slice of the source text spanning from `start`
@@ -492,7 +493,7 @@ fn scan_optional_raw_name(&mut self) -> Option<ast::Name> {
             if string == "_" {
                 None
             } else {
-                Some(token::intern(string))
+                Some(Symbol::intern(string))
             }
         })
     }
@@ -540,7 +541,7 @@ fn scan_comment(&mut self) -> Option<TokenAndSpan> {
                         self.with_str_from(start_bpos, |string| {
                             // comments with only more "/"s are not doc comments
                             let tok = if is_doc_comment(string) {
-                                token::DocComment(token::intern(string))
+                                token::DocComment(Symbol::intern(string))
                             } else {
                                 token::Comment
                             };
@@ -669,7 +670,7 @@ fn scan_block_comment(&mut self) -> Option<TokenAndSpan> {
                 } else {
                     string.into()
                 };
-                token::DocComment(token::intern(&string[..]))
+                token::DocComment(Symbol::intern(&string[..]))
             } else {
                 token::Comment
             };
@@ -758,7 +759,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
             self.err_span_(start_bpos,
                            self.pos,
                            "no valid digits found for number");
-            return token::Integer(token::intern("0"));
+            return token::Integer(Symbol::intern("0"));
         }
 
         // might be a float, but don't be greedy if this is actually an
@@ -1097,7 +1098,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     token::Underscore
                 } else {
                     // FIXME: perform NFKC normalization here. (Issue #2253)
-                    token::Ident(str_to_ident(string))
+                    token::Ident(Ident::from_str(string))
                 }
             }));
         }
@@ -1277,13 +1278,13 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     // expansion purposes. See #12512 for the gory details of why
                     // this is necessary.
                     let ident = self.with_str_from(start, |lifetime_name| {
-                        str_to_ident(&format!("'{}", lifetime_name))
+                        Ident::from_str(&format!("'{}", lifetime_name))
                     });
 
                     // Conjure up a "keyword checking ident" to make sure that
                     // the lifetime name is not a keyword.
                     let keyword_checking_ident = self.with_str_from(start, |lifetime_name| {
-                        str_to_ident(lifetime_name)
+                        Ident::from_str(lifetime_name)
                     });
                     let keyword_checking_token = &token::Ident(keyword_checking_ident);
                     let last_bpos = self.pos;
@@ -1310,7 +1311,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 let id = if valid {
                     self.name_from(start)
                 } else {
-                    token::intern("0")
+                    Symbol::intern("0")
                 };
                 self.bump(); // advance ch past token
                 let suffix = self.scan_optional_raw_name();
@@ -1352,7 +1353,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 let id = if valid {
                     self.name_from(start_bpos + BytePos(1))
                 } else {
-                    token::intern("??")
+                    Symbol::intern("??")
                 };
                 self.bump();
                 let suffix = self.scan_optional_raw_name();
@@ -1424,7 +1425,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 let id = if valid {
                     self.name_from_to(content_start_bpos, content_end_bpos)
                 } else {
-                    token::intern("??")
+                    Symbol::intern("??")
                 };
                 let suffix = self.scan_optional_raw_name();
                 return Ok(token::Literal(token::StrRaw(id, hash_count), suffix));
@@ -1551,7 +1552,7 @@ fn scan_byte(&mut self) -> token::Lit {
         let id = if valid {
             self.name_from(start)
         } else {
-            token::intern("?")
+            Symbol::intern("?")
         };
         self.bump(); // advance ch past token
         return token::Byte(id);
@@ -1584,7 +1585,7 @@ fn scan_byte_string(&mut self) -> token::Lit {
         let id = if valid {
             self.name_from(start)
         } else {
-            token::intern("??")
+            Symbol::intern("??")
         };
         self.bump();
         return token::ByteStr(id);
@@ -1700,11 +1701,12 @@ fn ident_continue(c: Option<char>) -> bool {
 mod tests {
     use super::*;
 
+    use ast::Ident;
+    use symbol::Symbol;
     use syntax_pos::{BytePos, Span, NO_EXPANSION};
     use codemap::CodeMap;
     use errors;
     use parse::token;
-    use parse::token::str_to_ident;
     use std::io;
     use std::rc::Rc;
 
@@ -1732,7 +1734,7 @@ fn t1() {
                                       &sh,
                                       "/* my source file */ fn main() { println!(\"zebra\"); }\n"
                                           .to_string());
-        let id = str_to_ident("fn");
+        let id = Ident::from_str("fn");
         assert_eq!(string_reader.next_token().tok, token::Comment);
         assert_eq!(string_reader.next_token().tok, token::Whitespace);
         let tok1 = string_reader.next_token();
@@ -1751,7 +1753,7 @@ fn t1() {
         // read another token:
         let tok3 = string_reader.next_token();
         let tok4 = TokenAndSpan {
-            tok: token::Ident(str_to_ident("main")),
+            tok: token::Ident(Ident::from_str("main")),
             sp: Span {
                 lo: BytePos(24),
                 hi: BytePos(28),
@@ -1773,7 +1775,7 @@ fn check_tokenization(mut string_reader: StringReader, expected: Vec<token::Toke
 
     // make the identifier by looking up the string in the interner
     fn mk_ident(id: &str) -> token::Token {
-        token::Ident(str_to_ident(id))
+        token::Ident(Ident::from_str(id))
     }
 
     #[test]
@@ -1813,7 +1815,7 @@ fn character_a() {
         let cm = Rc::new(CodeMap::new());
         let sh = mk_sh(cm.clone());
         assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok,
-                   token::Literal(token::Char(token::intern("a")), None));
+                   token::Literal(token::Char(Symbol::intern("a")), None));
     }
 
     #[test]
@@ -1821,7 +1823,7 @@ fn character_space() {
         let cm = Rc::new(CodeMap::new());
         let sh = mk_sh(cm.clone());
         assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok,
-                   token::Literal(token::Char(token::intern(" ")), None));
+                   token::Literal(token::Char(Symbol::intern(" ")), None));
     }
 
     #[test]
@@ -1829,7 +1831,7 @@ fn character_escaped() {
         let cm = Rc::new(CodeMap::new());
         let sh = mk_sh(cm.clone());
         assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok,
-                   token::Literal(token::Char(token::intern("\\n")), None));
+                   token::Literal(token::Char(Symbol::intern("\\n")), None));
     }
 
     #[test]
@@ -1837,7 +1839,7 @@ fn lifetime_name() {
         let cm = Rc::new(CodeMap::new());
         let sh = mk_sh(cm.clone());
         assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok,
-                   token::Lifetime(token::str_to_ident("'abc")));
+                   token::Lifetime(Ident::from_str("'abc")));
     }
 
     #[test]
@@ -1847,7 +1849,7 @@ fn raw_string() {
         assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string())
                        .next_token()
                        .tok,
-                   token::Literal(token::StrRaw(token::intern("\"#a\\b\x00c\""), 3), None));
+                   token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None));
     }
 
     #[test]
@@ -1857,11 +1859,11 @@ fn literal_suffixes() {
         macro_rules! test {
             ($input: expr, $tok_type: ident, $tok_contents: expr) => {{
                 assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok,
-                           token::Literal(token::$tok_type(token::intern($tok_contents)),
-                                          Some(token::intern("suffix"))));
+                           token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
+                                          Some(Symbol::intern("suffix"))));
                 // with a whitespace separator:
                 assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok,
-                           token::Literal(token::$tok_type(token::intern($tok_contents)),
+                           token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
                                           None));
             }}
         }
@@ -1877,14 +1879,14 @@ macro_rules! test {
         test!("1.0e10", Float, "1.0e10");
 
         assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok,
-                   token::Literal(token::Integer(token::intern("2")),
-                                  Some(token::intern("us"))));
+                   token::Literal(token::Integer(Symbol::intern("2")),
+                                  Some(Symbol::intern("us"))));
         assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok,
-                   token::Literal(token::StrRaw(token::intern("raw"), 3),
-                                  Some(token::intern("suffix"))));
+                   token::Literal(token::StrRaw(Symbol::intern("raw"), 3),
+                                  Some(Symbol::intern("suffix"))));
         assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok,
-                   token::Literal(token::ByteStrRaw(token::intern("raw"), 3),
-                                  Some(token::intern("suffix"))));
+                   token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3),
+                                  Some(Symbol::intern("suffix"))));
     }
 
     #[test]
@@ -1904,7 +1906,7 @@ fn nested_block_comments() {
             _ => panic!("expected a comment!"),
         }
         assert_eq!(lexer.next_token().tok,
-                   token::Literal(token::Char(token::intern("a")), None));
+                   token::Literal(token::Char(Symbol::intern("a")), None));
     }
 
     #[test]
@@ -1917,6 +1919,6 @@ fn crlf_comments() {
         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")));
     }
 }
index 12408c7d3c95bdcb063132cb131a860607880c6b..bfaf00a3d3f0814ee319772f306d564a2fea5c73 100644 (file)
 use errors::{Handler, ColorConfig, DiagnosticBuilder};
 use feature_gate::UnstableFeatures;
 use parse::parser::Parser;
-use parse::token::InternedString;
 use ptr::P;
 use str::char_at;
+use symbol::Symbol;
 use tokenstream;
 
 use std::cell::RefCell;
+use std::collections::HashSet;
 use std::iter;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -64,7 +65,7 @@ pub fn with_span_handler(handler: Handler, code_map: Rc<CodeMap>) -> ParseSess {
         ParseSess {
             span_diagnostic: handler,
             unstable_features: UnstableFeatures::from_environment(),
-            config: Vec::new(),
+            config: HashSet::new(),
             included_mod_stack: RefCell::new(vec![]),
             code_map: code_map
         }
@@ -75,6 +76,19 @@ pub fn codemap(&self) -> &CodeMap {
     }
 }
 
+#[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
@@ -116,7 +130,7 @@ pub fn parse_item_from_source_str<'a>(name: String, source: String, sess: &'a Pa
 }
 
 pub fn parse_meta_from_source_str<'a>(name: String, source: String, sess: &'a ParseSess)
-                                      -> PResult<'a, P<ast::MetaItem>> {
+                                      -> PResult<'a, ast::MetaItem> {
     new_parser_from_source_str(sess, name, source).parse_meta_item()
 }
 
@@ -151,11 +165,11 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a>
 /// On an error, use the given span as the source of the problem.
 pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
                                     path: &Path,
-                                    owns_directory: bool,
+                                    directory_ownership: DirectoryOwnership,
                                     module_name: Option<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
 }
@@ -371,13 +385,18 @@ fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
         s[1..].chars().all(|c| '0' <= c && c <= '9')
 }
 
-fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>,
-                      sd: &Handler, sp: Span) -> ast::LitKind {
+fn filtered_float_lit(data: Symbol, suffix: Option<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..]))
@@ -391,16 +410,13 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>,
 
             ast::LitKind::FloatUnsuffixed(data)
         }
-        None => ast::LitKind::FloatUnsuffixed(data)
     }
 }
-pub fn float_lit(s: &str, suffix: Option<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`
@@ -495,11 +511,7 @@ fn eat<'a, I: Iterator<Item=(usize, u8)>>(it: &mut iter::Peekable<I>) {
     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>();
@@ -521,16 +533,15 @@ pub fn integer_lit(s: &str,
     }
 
     // 1f64 and 2f32 etc. are valid float literals.
-    if let Some(ref suf) = suffix {
-        if looks_like_width_suffix(&['f'], suf) {
+    if let Some(suf) = suffix {
+        if looks_like_width_suffix(&['f'], &suf.as_str()) {
             match base {
                 16 => sd.span_err(sp, "hexadecimal float literal is not supported"),
                 8 => sd.span_err(sp, "octal float literal is not supported"),
                 2 => sd.span_err(sp, "binary float literal is not supported"),
                 _ => ()
             }
-            let ident = token::intern_and_get_ident(&s);
-            return filtered_float_lit(ident, Some(&suf), sd, sp)
+            return filtered_float_lit(Symbol::intern(&s), Some(suf), sd, sp)
         }
     }
 
@@ -538,9 +549,9 @@ pub fn integer_lit(s: &str,
         s = &s[2..];
     }
 
-    if let Some(ref suf) = suffix {
-        if suf.is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")}
-        ty = match &**suf {
+    if let Some(suf) = suffix {
+        if suf.as_str().is_empty() { sd.span_bug(sp, "found empty literal suffix in Some")}
+        ty = match &*suf.as_str() {
             "isize" => ast::LitIntType::Signed(ast::IntTy::Is),
             "i8"  => ast::LitIntType::Signed(ast::IntTy::I8),
             "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
@@ -551,7 +562,7 @@ pub fn integer_lit(s: &str,
             "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
             "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
             "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
-            _ => {
+            suf => {
                 // i<digits> and u<digits> look like widths, so lets
                 // give an error message along those lines
                 if looks_like_width_suffix(&['i', 'u'], suf) {
@@ -599,12 +610,11 @@ mod tests {
     use std::rc::Rc;
     use syntax_pos::{self, Span, BytePos, Pos, NO_EXPANSION};
     use codemap::Spanned;
-    use ast::{self, PatKind};
+    use ast::{self, Ident, PatKind};
     use abi::Abi;
     use attr::first_attr_value_str_by_name;
     use parse;
     use parse::parser::Parser;
-    use parse::token::{str_to_ident};
     use print::pprust::item_to_string;
     use ptr::P;
     use tokenstream::{self, TokenTree};
@@ -626,7 +636,7 @@ fn sp(a: u32, b: u32) -> Span {
                         global: false,
                         segments: vec![
                             ast::PathSegment {
-                                identifier: str_to_ident("a"),
+                                identifier: Ident::from_str("a"),
                                 parameters: ast::PathParameters::none(),
                             }
                         ],
@@ -645,11 +655,11 @@ fn sp(a: u32, b: u32) -> Span {
                             global: true,
                             segments: vec![
                                 ast::PathSegment {
-                                    identifier: str_to_ident("a"),
+                                    identifier: Ident::from_str("a"),
                                     parameters: ast::PathParameters::none(),
                                 },
                                 ast::PathSegment {
-                                    identifier: str_to_ident("b"),
+                                    identifier: Ident::from_str("b"),
                                     parameters: ast::PathParameters::none(),
                                 }
                             ]
@@ -678,8 +688,8 @@ fn string_to_tts_macro () {
                 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 = &macro_delimed.tts[..];
                 match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
                     (
@@ -696,8 +706,7 @@ fn string_to_tts_macro () {
                                 Some(&TokenTree::Token(_, token::Dollar)),
                                 Some(&TokenTree::Token(_, token::Ident(ident))),
                             )
-                            if first_delimed.delim == token::Paren
-                            && ident.name.as_str() == "a" => {},
+                            if first_delimed.delim == token::Paren && ident.name == "a" => {},
                             _ => panic!("value 3: {:?}", **first_delimed),
                         }
                         let tts = &second_delimed.tts[..];
@@ -708,7 +717,7 @@ fn string_to_tts_macro () {
                                 Some(&TokenTree::Token(_, token::Ident(ident))),
                             )
                             if second_delimed.delim == token::Paren
-                            && ident.name.as_str() == "a" => {},
+                            && ident.name == "a" => {},
                             _ => panic!("value 4: {:?}", **second_delimed),
                         }
                     },
@@ -724,17 +733,17 @@ fn string_to_tts_1() {
         let tts = string_to_tts("fn a (b : i32) { b; }".to_string());
 
         let expected = vec![
-            TokenTree::Token(sp(0, 2), token::Ident(str_to_ident("fn"))),
-            TokenTree::Token(sp(3, 4), token::Ident(str_to_ident("a"))),
+            TokenTree::Token(sp(0, 2), token::Ident(Ident::from_str("fn"))),
+            TokenTree::Token(sp(3, 4), token::Ident(Ident::from_str("a"))),
             TokenTree::Delimited(
                 sp(5, 14),
                 Rc::new(tokenstream::Delimited {
                     delim: token::DelimToken::Paren,
                     open_span: sp(5, 6),
                     tts: vec![
-                        TokenTree::Token(sp(6, 7), token::Ident(str_to_ident("b"))),
+                        TokenTree::Token(sp(6, 7), token::Ident(Ident::from_str("b"))),
                         TokenTree::Token(sp(8, 9), token::Colon),
-                        TokenTree::Token(sp(10, 13), token::Ident(str_to_ident("i32"))),
+                        TokenTree::Token(sp(10, 13), token::Ident(Ident::from_str("i32"))),
                     ],
                     close_span: sp(13, 14),
                 })),
@@ -744,7 +753,7 @@ fn string_to_tts_1() {
                     delim: token::DelimToken::Brace,
                     open_span: sp(15, 16),
                     tts: vec![
-                        TokenTree::Token(sp(17, 18), token::Ident(str_to_ident("b"))),
+                        TokenTree::Token(sp(17, 18), token::Ident(Ident::from_str("b"))),
                         TokenTree::Token(sp(18, 19), token::Semi),
                     ],
                     close_span: sp(20, 21),
@@ -765,7 +774,7 @@ fn string_to_tts_1() {
                             global: false,
                             segments: vec![
                                 ast::PathSegment {
-                                    identifier: str_to_ident("d"),
+                                    identifier: Ident::from_str("d"),
                                     parameters: ast::PathParameters::none(),
                                 }
                             ],
@@ -788,7 +797,7 @@ fn string_to_tts_1() {
                                global:false,
                                segments: vec![
                                 ast::PathSegment {
-                                    identifier: str_to_ident("b"),
+                                    identifier: Ident::from_str("b"),
                                     parameters: ast::PathParameters::none(),
                                 }
                                ],
@@ -812,7 +821,7 @@ fn parser_done(p: Parser){
                 id: ast::DUMMY_NODE_ID,
                 node: PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable),
                                     Spanned{ span:sp(0, 1),
-                                             node: str_to_ident("b")
+                                             node: Ident::from_str("b")
                     },
                                     None),
                 span: sp(0,1)}));
@@ -824,7 +833,7 @@ fn parser_done(p: Parser){
         // this test depends on the intern order of "fn" and "i32"
         assert_eq!(string_to_item("fn a (b : i32) { b; }".to_string()),
                   Some(
-                      P(ast::Item{ident:str_to_ident("a"),
+                      P(ast::Item{ident:Ident::from_str("a"),
                             attrs:Vec::new(),
                             id: ast::DUMMY_NODE_ID,
                             node: ast::ItemKind::Fn(P(ast::FnDecl {
@@ -835,8 +844,7 @@ fn parser_done(p: Parser){
                                         global:false,
                                         segments: vec![
                                             ast::PathSegment {
-                                                identifier:
-                                                    str_to_ident("i32"),
+                                                identifier: Ident::from_str("i32"),
                                                 parameters: ast::PathParameters::none(),
                                             }
                                         ],
@@ -849,7 +857,7 @@ fn parser_done(p: Parser){
                                             ast::BindingMode::ByValue(ast::Mutability::Immutable),
                                                 Spanned{
                                                     span: sp(6,7),
-                                                    node: str_to_ident("b")},
+                                                    node: Ident::from_str("b")},
                                                 None
                                                     ),
                                             span: sp(6,7)
@@ -884,9 +892,7 @@ fn parser_done(p: Parser){
                                                         global:false,
                                                         segments: vec![
                                                             ast::PathSegment {
-                                                                identifier:
-                                                                str_to_ident(
-                                                                    "b"),
+                                                                identifier: Ident::from_str("b"),
                                                                 parameters:
                                                                 ast::PathParameters::none(),
                                                             }
@@ -998,12 +1004,12 @@ fn wb() -> c_int { O_WRONLY as c_int }
         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);
@@ -1011,7 +1017,7 @@ fn wb() -> c_int { O_WRONLY as c_int }
         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]
index 2e38ca82d5dbb6f0161d83b957cf982eb584f9f9..49226be4147d7c4b9b01a062f4b44c4997fcc45f 100644 (file)
@@ -38,7 +38,7 @@
 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;
@@ -67,7 +68,6 @@
     flags Restrictions: u8 {
         const RESTRICTION_STMT_EXPR         = 1 << 0,
         const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
-        const NO_NONINLINE_MOD  = 1 << 2,
     }
 }
 
@@ -199,12 +199,9 @@ pub struct Parser<'a> {
     /// extra detail when the same error is seen twice
     pub obsolete_set: HashSet<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.
@@ -244,8 +241,9 @@ pub struct ModulePath {
 }
 
 pub struct ModulePathSuccess {
-    pub path: ::std::path::PathBuf,
-    pub owns_directory: bool,
+    pub path: PathBuf,
+    pub directory_ownership: DirectoryOwnership,
+    warn: bool,
 }
 
 pub struct ModulePathError {
@@ -295,9 +293,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c
             quote_depth: 0,
             parsing_token_tree: false,
             obsolete_set: HashSet::new(),
-            directory: PathBuf::new(),
+            directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
             open_braces: Vec::new(),
-            owns_directory: true,
             root_module_name: None,
             expected_tokens: Vec::new(),
             tts: Vec::new(),
@@ -309,8 +306,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c
         parser.token = tok.tok;
         parser.span = tok.sp;
         if parser.span != syntax_pos::DUMMY_SP {
-            parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span));
-            parser.directory.pop();
+            parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
+            parser.directory.path.pop();
         }
         parser
     }
@@ -998,10 +995,6 @@ pub fn diagnostic(&self) -> &'a errors::Handler {
         &self.sess.span_diagnostic
     }
 
-    pub fn id_to_interned_str(&mut self, id: Ident) -> InternedString {
-        id.name.as_str()
-    }
-
     /// Is the current token one of the keywords that signals a bare function
     /// type?
     pub fn token_is_bare_fn_keyword(&mut self) -> bool {
@@ -1523,34 +1516,28 @@ pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
                     // float literals, so all the handling is done
                     // internally.
                     token::Integer(s) => {
-                        (false, parse::integer_lit(&s.as_str(),
-                                                   suf.as_ref().map(|s| s.as_str()),
-                                                   &self.sess.span_diagnostic,
-                                                   self.span))
+                        let diag = &self.sess.span_diagnostic;
+                        (false, parse::integer_lit(&s.as_str(), suf, diag, self.span))
                     }
                     token::Float(s) => {
-                        (false, parse::float_lit(&s.as_str(),
-                                                 suf.as_ref().map(|s| s.as_str()),
-                                                  &self.sess.span_diagnostic,
-                                                 self.span))
+                        let diag = &self.sess.span_diagnostic;
+                        (false, parse::float_lit(&s.as_str(), suf, diag, self.span))
                     }
 
                     token::Str_(s) => {
-                        (true,
-                         LitKind::Str(token::intern_and_get_ident(&parse::str_lit(&s.as_str())),
-                                      ast::StrStyle::Cooked))
+                        let s = Symbol::intern(&parse::str_lit(&s.as_str()));
+                        (true, LitKind::Str(s, ast::StrStyle::Cooked))
                     }
                     token::StrRaw(s, n) => {
-                        (true,
-                         LitKind::Str(
-                            token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())),
-                            ast::StrStyle::Raw(n)))
+                        let s = Symbol::intern(&parse::raw_str_lit(&s.as_str()));
+                        (true, LitKind::Str(s, ast::StrStyle::Raw(n)))
+                    }
+                    token::ByteStr(i) => {
+                        (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str())))
+                    }
+                    token::ByteStrRaw(i, _) => {
+                        (true, LitKind::ByteStr(Rc::new(i.to_string().into_bytes())))
                     }
-                    token::ByteStr(i) =>
-                        (true, LitKind::ByteStr(parse::byte_str_lit(&i.as_str()))),
-                    token::ByteStrRaw(i, _) =>
-                        (true,
-                         LitKind::ByteStr(Rc::new(i.to_string().into_bytes()))),
                 };
 
                 if suffix_illegal {
@@ -2269,15 +2256,25 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                         ex = ExprKind::Ret(None);
                     }
                 } else if self.eat_keyword(keywords::Break) {
-                    if self.token.is_lifetime() {
-                        ex = ExprKind::Break(Some(Spanned {
+                    let lt = if self.token.is_lifetime() {
+                        let spanned_lt = Spanned {
                             node: self.get_lifetime(),
                             span: self.span
-                        }));
+                        };
                         self.bump();
+                        Some(spanned_lt)
                     } else {
-                        ex = ExprKind::Break(None);
-                    }
+                        None
+                    };
+                    let e = if self.token.can_begin_expr()
+                               && !(self.token == token::OpenDelim(token::Brace)
+                                    && self.restrictions.contains(
+                                           Restrictions::RESTRICTION_NO_STRUCT_LITERAL)) {
+                        Some(self.parse_expr()?)
+                    } else {
+                        None
+                    };
+                    ex = ExprKind::Break(lt, e);
                     hi = self.prev_span.hi;
                 } else if self.token.is_keyword(keywords::Let) {
                     // Catch this syntax error here, instead of in `check_strict_keywords`, so
@@ -2544,7 +2541,7 @@ fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: BytePos) -> PResult<
                     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,
@@ -2627,7 +2624,7 @@ fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> {
                                       })));
                 } else if self.token.is_keyword(keywords::Crate) {
                     let ident = match self.token {
-                        token::Ident(id) => ast::Ident { name: token::intern("$crate"), ..id },
+                        token::Ident(id) => ast::Ident { name: Symbol::intern("$crate"), ..id },
                         _ => unreachable!(),
                     };
                     self.bump();
@@ -3751,9 +3748,7 @@ fn parse_name_and_ty(&mut self,
     /// Emit an expected item after attributes error.
     fn expected_item_err(&self, attrs: &[Attribute]) {
         let message = match attrs.last() {
-            Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => {
-                "expected item after doc comment"
-            }
+            Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment",
             _ => "expected item after attributes",
         };
 
@@ -3977,9 +3972,11 @@ fn parse_stmt_without_recovery(&mut self,
             }
         } else {
             // FIXME: Bad copy of attrs
-            let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
-            match self.with_res(restrictions,
-                                |this| this.parse_item_(attrs.clone(), false, true))? {
+            let old_directory_ownership =
+                mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
+            let item = self.parse_item_(attrs.clone(), false, true)?;
+            self.directory.ownership = old_directory_ownership;
+            match item {
                 Some(i) => Stmt {
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, i.span.hi),
@@ -4837,7 +4834,7 @@ fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) {
             Visibility::Inherited => (),
             _ => {
                 let is_macro_rules: bool = match self.token {
-                    token::Ident(sid) => sid.name == intern("macro_rules"),
+                    token::Ident(sid) => sid.name == Symbol::intern("macro_rules"),
                     _ => false,
                 };
                 if is_macro_rules {
@@ -5282,39 +5279,53 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
             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 .
@@ -5329,8 +5340,16 @@ pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -
         let secondary_exists = codemap.file_exists(&secondary_path);
 
         let result = match (default_exists, secondary_exists) {
-            (true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }),
-            (false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }),
+            (true, false) => Ok(ModulePathSuccess {
+                path: default_path,
+                directory_ownership: DirectoryOwnership::UnownedViaMod(false),
+                warn: false,
+            }),
+            (false, true) => Ok(ModulePathSuccess {
+                path: secondary_path,
+                directory_ownership: DirectoryOwnership::Owned,
+                warn: false,
+            }),
             (false, false) => Err(ModulePathError {
                 err_msg: format!("file not found for module `{}`", mod_name),
                 help_msg: format!("name the file either {} or {} inside the directory {:?}",
@@ -5358,13 +5377,20 @@ fn submod_path(&mut self,
                    id: ast::Ident,
                    outer_attrs: &[ast::Attribute],
                    id_sp: Span) -> PResult<'a, ModulePathSuccess> {
-        if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &self.directory) {
-            return Ok(ModulePathSuccess { path: p, owns_directory: true });
+        if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
+            return Ok(ModulePathSuccess {
+                directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
+                    Some("mod.rs") => DirectoryOwnership::Owned,
+                    _ => DirectoryOwnership::UnownedViaMod(true),
+                },
+                path: path,
+                warn: false,
+            });
         }
 
-        let paths = Parser::default_submod_path(id, &self.directory, self.sess.codemap());
+        let paths = Parser::default_submod_path(id, &self.directory.path, self.sess.codemap());
 
-        if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) {
+        if let DirectoryOwnership::UnownedViaBlock = self.directory.ownership {
             let msg =
                 "Cannot declare a non-inline module inside a block unless it has a path attribute";
             let mut err = self.diagnostic().struct_span_err(id_sp, msg);
@@ -5374,10 +5400,15 @@ fn submod_path(&mut self,
                 err.span_note(id_sp, &msg);
             }
             return Err(err);
-        } else if !self.owns_directory {
+        } else if let DirectoryOwnership::UnownedViaMod(warn) = self.directory.ownership {
+            if warn {
+                if let Ok(result) = paths.result {
+                    return Ok(ModulePathSuccess { warn: true, ..result });
+                }
+            }
             let mut err = self.diagnostic().struct_span_err(id_sp,
                 "cannot declare a new module at this location");
-            let this_module = match self.directory.file_name() {
+            let this_module = match self.directory.path.file_name() {
                 Some(file_name) => file_name.to_str().unwrap().to_owned(),
                 None => self.root_module_name.as_ref().unwrap().clone(),
             };
@@ -5390,8 +5421,10 @@ fn submod_path(&mut self,
                               &format!("... or maybe `use` the module `{}` instead \
                                         of possibly redeclaring it",
                                        paths.name));
-            }
-            return Err(err);
+                return Err(err);
+            } else {
+                return Err(err);
+            };
         }
 
         match paths.result {
@@ -5402,25 +5435,11 @@ fn submod_path(&mut self,
 
     /// 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: ");
@@ -5435,7 +5454,8 @@ fn eval_src_mod_from_path(&mut self,
         included_mod_stack.push(path.clone());
         drop(included_mod_stack);
 
-        let mut p0 = new_sub_parser_from_file(self.sess, &path, owns_directory, Some(name), id_sp);
+        let mut p0 =
+            new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
         let mod_inner_lo = p0.span.lo;
         let mod_attrs = p0.parse_inner_attributes()?;
         let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
@@ -6128,26 +6148,17 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
         })
     }
 
-    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;
index 0198ee073d23982c3534787ab2c950fa2a44076e..8ac39dd462e7cbf254667b21f5e12ae21329d352 100644 (file)
 
 use ast::{self};
 use ptr::P;
-use util::interner::Interner;
+use symbol::keywords;
 use tokenstream;
 
-use serialize::{Decodable, Decoder, Encodable, Encoder};
-use std::cell::RefCell;
 use std::fmt;
-use std::ops::Deref;
 use std::rc::Rc;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -301,7 +298,7 @@ pub enum Nonterminal {
     NtTy(P<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.
@@ -335,270 +332,3 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         }
     }
 }
-
-// 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))*/
-}
index 203c19285ac2c366e01f83b5d4eebc32cd35f772..c28b9d00501b70fd6a989f27af86ad170873d3df 100644 (file)
@@ -19,7 +19,7 @@
 use codemap::{self, CodeMap};
 use syntax_pos::{self, BytePos};
 use errors;
-use parse::token::{self, keywords, BinOpToken, Token, InternedString};
+use parse::token::{self, BinOpToken, Token};
 use parse::lexer::comments;
 use parse;
 use print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
@@ -27,6 +27,7 @@
 use print::pp::Breaks::{Consistent, Inconsistent};
 use ptr::P;
 use std_inject;
+use symbol::{Symbol, keywords};
 use tokenstream::{self, TokenTree};
 
 use std::ascii;
@@ -119,14 +120,13 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
         // of the feature gate, so we fake them up here.
 
         // #![feature(prelude_import)]
-        let prelude_import_meta = attr::mk_list_word_item(InternedString::new("prelude_import"));
-        let list = attr::mk_list_item(InternedString::new("feature"),
-                                      vec![prelude_import_meta]);
+        let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import"));
+        let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]);
         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list);
         try!(s.print_attribute(&fake_attr));
 
         // #![no_std]
-        let no_std_meta = attr::mk_word_item(InternedString::new("no_std"));
+        let no_std_meta = attr::mk_word_item(Symbol::intern("no_std"));
         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta);
         try!(s.print_attribute(&fake_attr));
     }
@@ -630,7 +630,7 @@ fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
             _ => ()
         }
         match lit.node {
-            ast::LitKind::Str(ref st, style) => self.print_string(&st, style),
+            ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
             ast::LitKind::Byte(byte) => {
                 let mut res = String::from("b'");
                 res.extend(ascii::escape_default(byte).map(|c| c as char));
@@ -664,7 +664,7 @@ fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
                          &f,
                          t.ty_to_string()))
             }
-            ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f[..]),
+            ast::LitKind::FloatUnsuffixed(ref f) => word(self.writer(), &f.as_str()),
             ast::LitKind::Bool(val) => {
                 if val { word(self.writer(), "true") } else { word(self.writer(), "false") }
             }
@@ -727,7 +727,7 @@ fn print_either_attributes(&mut self,
                               trailing_hardbreak: bool) -> io::Result<()> {
         let mut count = 0;
         for attr in attrs {
-            if attr.node.style == kind {
+            if attr.style == kind {
                 try!(self.print_attribute_inline(attr, is_inline));
                 if is_inline {
                     try!(self.nbsp());
@@ -751,11 +751,11 @@ fn print_attribute_inline(&mut self, attr: &ast::Attribute,
             try!(self.hardbreak_if_not_bol());
         }
         try!(self.maybe_print_comment(attr.span.lo));
-        if attr.node.is_sugared_doc {
-            try!(word(self.writer(), &attr.value_str().unwrap()));
+        if attr.is_sugared_doc {
+            try!(word(self.writer(), &attr.value_str().unwrap().as_str()));
             hardbreak(self.writer())
         } else {
-            match attr.node.style {
+            match attr.style {
                 ast::AttrStyle::Inner => try!(word(self.writer(), "#![")),
                 ast::AttrStyle::Outer => try!(word(self.writer(), "#[")),
             }
@@ -778,16 +778,16 @@ fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) -> io::Result<()>
     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
         try!(self.ibox(INDENT_UNIT));
         match item.node {
-            ast::MetaItemKind::Word(ref name) => {
-                try!(word(self.writer(), &name));
+            ast::MetaItemKind::Word => {
+                try!(word(self.writer(), &item.name.as_str()));
             }
-            ast::MetaItemKind::NameValue(ref name, ref value) => {
-                try!(self.word_space(&name[..]));
+            ast::MetaItemKind::NameValue(ref value) => {
+                try!(self.word_space(&item.name.as_str()));
                 try!(self.word_space("="));
                 try!(self.print_literal(value));
             }
-            ast::MetaItemKind::List(ref name, ref items) => {
-                try!(word(self.writer(), &name));
+            ast::MetaItemKind::List(ref items) => {
+                try!(word(self.writer(), &item.name.as_str()));
                 try!(self.popen());
                 try!(self.commasep(Consistent,
                               &items[..],
@@ -2191,13 +2191,17 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::Path(Some(ref qself), ref path) => {
                 try!(self.print_qpath(path, qself, true))
             }
-            ast::ExprKind::Break(opt_ident) => {
+            ast::ExprKind::Break(opt_ident, ref opt_expr) => {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
                 if let Some(ident) = opt_ident {
                     try!(self.print_ident(ident.node));
                     try!(space(&mut self.s));
                 }
+                if let Some(ref expr) = *opt_expr {
+                    try!(self.print_expr(expr));
+                    try!(space(&mut self.s));
+                }
             }
             ast::ExprKind::Continue(opt_ident) => {
                 try!(word(&mut self.s, "continue"));
@@ -2220,19 +2224,18 @@ fn print_expr_outer_attr_style(&mut self,
             ast::ExprKind::InlineAsm(ref a) => {
                 try!(word(&mut self.s, "asm!"));
                 try!(self.popen());
-                try!(self.print_string(&a.asm, a.asm_str_style));
+                try!(self.print_string(&a.asm.as_str(), a.asm_str_style));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.outputs,
-                                   |s, out| {
-                    let mut ch = out.constraint.chars();
+                try!(self.commasep(Inconsistent, &a.outputs, |s, out| {
+                    let constraint = out.constraint.as_str();
+                    let mut ch = constraint.chars();
                     match ch.next() {
                         Some('=') if out.is_rw => {
                             try!(s.print_string(&format!("+{}", ch.as_str()),
                                            ast::StrStyle::Cooked))
                         }
-                        _ => try!(s.print_string(&out.constraint,
-                                            ast::StrStyle::Cooked))
+                        _ => try!(s.print_string(&constraint, ast::StrStyle::Cooked))
                     }
                     try!(s.popen());
                     try!(s.print_expr(&out.expr));
@@ -2242,9 +2245,8 @@ fn print_expr_outer_attr_style(&mut self,
                 try!(space(&mut self.s));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.inputs,
-                                   |s, &(ref co, ref o)| {
-                    try!(s.print_string(&co, ast::StrStyle::Cooked));
+                try!(self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
+                    try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked));
                     try!(s.popen());
                     try!(s.print_expr(&o));
                     try!(s.pclose());
@@ -2255,7 +2257,7 @@ fn print_expr_outer_attr_style(&mut self,
 
                 try!(self.commasep(Inconsistent, &a.clobbers,
                                    |s, co| {
-                    try!(s.print_string(&co, ast::StrStyle::Cooked));
+                    try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked));
                     Ok(())
                 }));
 
@@ -3082,12 +3084,11 @@ mod tests {
 
     use ast;
     use codemap;
-    use parse::token;
     use syntax_pos;
 
     #[test]
     fn test_fun_to_string() {
-        let abba_ident = token::str_to_ident("abba");
+        let abba_ident = ast::Ident::from_str("abba");
 
         let decl = ast::FnDecl {
             inputs: Vec::new(),
@@ -3103,7 +3104,7 @@ fn test_fun_to_string() {
 
     #[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,
index 1b63a2b70763aff5da297077c8134a958490c0d9..6a291ad9c408a372ed1dbd9b7af1b8c59f9a0335 100644 (file)
 
 use ast;
 use attr;
+use symbol::{Symbol, keywords};
 use syntax_pos::{DUMMY_SP, Span};
 use codemap::{self, ExpnInfo, NameAndSpan, MacroAttribute};
-use parse::token::{intern, InternedString, keywords};
-use parse::{token, ParseSess};
+use parse::ParseSess;
 use ptr::P;
 
 /// Craft a span that will be ignored by the stability lint's
@@ -23,7 +23,7 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span {
     let info = ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            format: MacroAttribute(intern("std_inject")),
+            format: MacroAttribute(Symbol::intern("std_inject")),
             span: None,
             allow_internal_unstable: true,
         }
@@ -53,14 +53,14 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
         None => return krate,
     };
 
-    let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string()));
+    let crate_name = Symbol::intern(&alt_std_name.unwrap_or(name.to_string()));
 
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(),
-                                        attr::mk_word_item(InternedString::new("macro_use")))],
+                                        attr::mk_word_item(Symbol::intern("macro_use")))],
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::ExternCrate(Some(crate_name)),
-        ident: token::str_to_ident(name),
+        ident: ast::Ident::from_str(name),
         id: ast::DUMMY_NODE_ID,
         span: DUMMY_SP,
     }));
@@ -68,22 +68,21 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
     let span = ignored_span(sess, DUMMY_SP);
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![ast::Attribute {
-            node: ast::Attribute_ {
-                style: ast::AttrStyle::Outer,
-                value: P(ast::MetaItem {
-                    node: ast::MetaItemKind::Word(token::intern_and_get_ident("prelude_import")),
-                    span: span,
-                }),
-                id: attr::mk_attr_id(),
-                is_sugared_doc: false,
+            style: ast::AttrStyle::Outer,
+            value: ast::MetaItem {
+                name: Symbol::intern("prelude_import"),
+                node: ast::MetaItemKind::Word,
+                span: span,
             },
+            id: attr::mk_attr_id(),
+            is_sugared_doc: false,
             span: span,
         }],
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
             global: false,
             segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment {
-                identifier: token::str_to_ident(name),
+                identifier: ast::Ident::from_str(name),
                 parameters: ast::PathParameters::none(),
             }).collect(),
             span: span,
diff --git a/src/libsyntax/symbol.rs b/src/libsyntax/symbol.rs
new file mode 100644 (file)
index 0000000..fe9a176
--- /dev/null
@@ -0,0 +1,303 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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));
+    }
+}
index 59a7e75d12557039c10813c7dd1b88c67dfc76bb..4de3baf7d14fb27aaa240724903e35ecd2ab91a3 100644 (file)
 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
@@ -57,14 +57,14 @@ struct Test {
 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
@@ -91,10 +91,10 @@ pub fn modify_for_testing(sess: &ParseSess,
 
 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> {
@@ -191,8 +191,8 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
             EntryPointType::MainAttr |
             EntryPointType::Start =>
                 folded.map(|ast::Item {id, ident, attrs, node, vis, span}| {
-                    let allow_str = InternedString::new("allow");
-                    let dead_code_str = InternedString::new("dead_code");
+                    let allow_str = Symbol::intern("allow");
+                    let dead_code_str = Symbol::intern("dead_code");
                     let word_vec = vec![attr::mk_list_word_item(dead_code_str)];
                     let allow_dead_code_item = attr::mk_list_item(allow_str, word_vec);
                     let allow_dead_code = attr::mk_attr_outer(attr::mk_attr_id(),
@@ -222,15 +222,18 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
     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,
@@ -247,7 +250,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec<ast::Ident
         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 {
@@ -264,7 +267,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, parent: ast::NodeId, tests: Vec<ast::Ident
 
 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
@@ -286,7 +289,7 @@ fn generate_test_harness(sess: &ParseSess,
     cx.ext_cx.bt_push(ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            format: MacroAttribute(intern("test")),
+            format: MacroAttribute(Symbol::intern("test")),
             span: None,
             allow_internal_unstable: false,
         }
@@ -306,7 +309,7 @@ fn ignored_span(cx: &TestCtxt, sp: Span) -> Span {
     let info = ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            format: MacroAttribute(intern("test")),
+            format: MacroAttribute(Symbol::intern("test")),
             span: None,
             allow_internal_unstable: true,
         }
@@ -456,7 +459,7 @@ fn main() {
 */
 
 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,
@@ -487,16 +490,17 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
     let ecx = &cx.ext_cx;
 
     // test::test_main_static
-    let test_main_path = ecx.path(sp, vec![token::str_to_ident("test"),
-                                           token::str_to_ident("test_main_static")]);
+    let test_main_path =
+        ecx.path(sp, vec![Ident::from_str("test"), Ident::from_str("test_main_static")]);
+
     // test::test_main_static(...)
     let test_main_path_expr = ecx.expr_path(test_main_path);
-    let tests_ident_expr = ecx.expr_ident(sp, token::str_to_ident("TESTS"));
+    let tests_ident_expr = ecx.expr_ident(sp, Ident::from_str("TESTS"));
     let call_test_main = ecx.expr_call(sp, test_main_path_expr,
                                        vec![tests_ident_expr]);
     let call_test_main = ecx.stmt_expr(call_test_main);
     // #![main]
-    let main_meta = ecx.meta_word(sp, token::intern_and_get_ident("main"));
+    let main_meta = ecx.meta_word(sp, Symbol::intern("main"));
     let main_attr = ecx.attribute(sp, main_meta);
     // pub fn main() { ... }
     let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![]));
@@ -506,7 +510,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
                            dummy_spanned(ast::Constness::NotConst),
                            ::abi::Abi::Rust, ast::Generics::default(), main_body);
     let main = P(ast::Item {
-        ident: token::str_to_ident("main"),
+        ident: Ident::from_str("main"),
         attrs: vec![main_attr],
         id: ast::DUMMY_NODE_ID,
         node: main,
@@ -533,7 +537,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
         items: vec![import, mainfn, tests],
     };
     let item_ = ast::ItemKind::Mod(testmod);
-    let mod_ident = token::gensym_ident("__test");
+    let mod_ident = Ident::with_empty_ctxt(Symbol::gensym("__test"));
 
     let mut expander = cx.ext_cx.monotonic_expander();
     let item = expander.fold_item(P(ast::Item {
@@ -544,13 +548,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<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,
@@ -571,7 +575,7 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
     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,
@@ -582,7 +586,7 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
     }
 }
 
-fn path_name_i(idents: &[ast::Ident]) -> String {
+fn path_name_i(idents: &[Ident]) -> String {
     // FIXME: Bad copies (#2543 -- same for everything else that says "bad")
     idents.iter().map(|i| i.to_string()).collect::<Vec<String>>().join("::")
 }
@@ -614,7 +618,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
 
 fn is_test_crate(krate: &ast::Crate) -> bool {
     match attr::find_crate_name(&krate.attrs) {
-        Some(ref s) if "test" == &s[..] => true,
+        Some(s) if "test" == &*s.as_str() => true,
         _ => false
     }
 }
@@ -660,7 +664,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
 
     // path to the #[test] function: "foo::bar::baz"
     let path_string = path_name_i(&path[..]);
-    let name_expr = ecx.expr_str(span, token::intern_and_get_ident(&path_string[..]));
+    let name_expr = ecx.expr_str(span, Symbol::intern(&path_string));
 
     // self::test::StaticTestName($name_expr)
     let name_expr = ecx.expr_call(span,
@@ -673,10 +677,10 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     };
     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])
                 }
index 9ef6c07e489dce7de227d349cbeef5b313358422..0d5dcaf339feb086f6dddabb627cf161cce958cb 100644 (file)
@@ -34,6 +34,7 @@
 use parse;
 use parse::token::{self, Token, Lit, Nonterminal};
 use print::pprust;
+use symbol::Symbol;
 
 use std::fmt;
 use std::iter::*;
@@ -173,10 +174,10 @@ pub fn get_tt(&self, index: usize) -> TokenTree {
                 TokenTree::Delimited(sp, Rc::new(Delimited {
                     delim: token::Bracket,
                     open_span: sp,
-                    tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"))),
+                    tts: vec![TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"))),
                               TokenTree::Token(sp, token::Eq),
                               TokenTree::Token(sp, token::Literal(
-                                  token::StrRaw(token::intern(&stripped), num_of_hashes), None))],
+                                  token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None))],
                     close_span: sp,
                 }))
             }
@@ -295,7 +296,7 @@ pub fn maybe_lit(&self) -> Option<token::Lit> {
     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,
@@ -303,7 +304,7 @@ pub fn maybe_str(&self) -> Option<ast::Lit> {
                 })
             }
             TokenTree::Token(sp, Token::Literal(Lit::StrRaw(s, n), _)) => {
-                let l = LitKind::Str(token::intern_and_get_ident(&parse::raw_str_lit(&s.as_str())),
+                let l = LitKind::Str(Symbol::intern(&parse::raw_str_lit(&s.as_str())),
                                      ast::StrStyle::Raw(n));
                 Some(Spanned {
                     node: l,
@@ -871,8 +872,9 @@ fn index(&self, index: usize) -> &TokenTree {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use syntax::ast::Ident;
     use syntax_pos::{Span, BytePos, NO_EXPANSION, DUMMY_SP};
-    use parse::token::{self, str_to_ident, Token};
+    use parse::token::{self, Token};
     use util::parser_testing::string_to_tts;
     use std::rc::Rc;
 
@@ -967,15 +969,17 @@ fn test_slice_1() {
         let test_res = TokenStream::from_tts(string_to_tts("foo::bar::baz".to_string()))
             .slice(2..3);
         let test_eqs = TokenStream::from_tts(vec![TokenTree::Token(sp(5,8),
-                                                    token::Ident(str_to_ident("bar")))]);
+                                                    token::Ident(Ident::from_str("bar")))]);
         assert_eq!(test_res, test_eqs)
     }
 
     #[test]
     fn test_is_empty() {
         let test0 = TokenStream::from_tts(Vec::new());
-        let test1 = TokenStream::from_tts(vec![TokenTree::Token(sp(0, 1),
-                                                                Token::Ident(str_to_ident("a")))]);
+        let test1 = TokenStream::from_tts(
+            vec![TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a")))]
+        );
+
         let test2 = TokenStream::from_tts(string_to_tts("foo(bar::baz)".to_string()));
 
         assert_eq!(test0.is_empty(), true);
@@ -1035,20 +1039,20 @@ fn test_maybe_delimited() {
         assert_eq!(test0, None);
 
         let test1_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
-                                                        token::Ident(str_to_ident("bar"))),
+                                                        token::Ident(Ident::from_str("bar"))),
                                        TokenTree::Token(sp(4, 6), token::ModSep),
                                        TokenTree::Token(sp(6, 9),
-                                                        token::Ident(str_to_ident("baz")))]);
+                                                        token::Ident(Ident::from_str("baz")))]);
         assert_eq!(test1, Some(test1_expected));
 
         let test2_expected = TokenStream::from_tts(vec![TokenTree::Token(sp(1, 4),
-                                                        token::Ident(str_to_ident("foo"))),
+                                                        token::Ident(Ident::from_str("foo"))),
                                        TokenTree::Token(sp(4, 5), token::Comma),
                                        TokenTree::Token(sp(5, 8),
-                                                        token::Ident(str_to_ident("bar"))),
+                                                        token::Ident(Ident::from_str("bar"))),
                                        TokenTree::Token(sp(8, 9), token::Comma),
                                        TokenTree::Token(sp(9, 12),
-                                                        token::Ident(str_to_ident("baz")))]);
+                                                        token::Ident(Ident::from_str("baz")))]);
         assert_eq!(test2, Some(test2_expected));
 
         assert_eq!(test3, None);
@@ -1069,7 +1073,7 @@ fn test_maybe_ident() {
 
         assert_eq!(test0, None);
         assert_eq!(test1, None);
-        assert_eq!(test2, Some(str_to_ident("foo")));
+        assert_eq!(test2, Some(Ident::from_str("foo")));
         assert_eq!(test3, None);
         assert_eq!(test4, None);
     }
@@ -1079,9 +1083,9 @@ fn test_as_delimited_stream() {
         let test0 = as_paren_delimited_stream(string_to_tts("foo,bar,".to_string()));
         let test1 = as_paren_delimited_stream(string_to_tts("baz(foo,bar)".to_string()));
 
-        let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("foo"))),
+        let test0_tts = vec![TokenTree::Token(sp(0, 3), token::Ident(Ident::from_str("foo"))),
                              TokenTree::Token(sp(3, 4), token::Comma),
-                             TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("bar"))),
+                             TokenTree::Token(sp(4, 7), token::Ident(Ident::from_str("bar"))),
                              TokenTree::Token(sp(7, 8), token::Comma)];
         let test0_stream = TokenStream::from_tts(vec![TokenTree::Delimited(sp(0, 8),
                                                                Rc::new(Delimited {
@@ -1094,11 +1098,11 @@ fn test_as_delimited_stream() {
         assert_eq!(test0, test0_stream);
 
 
-        let test1_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(str_to_ident("foo"))),
+        let test1_tts = vec![TokenTree::Token(sp(4, 7), token::Ident(Ident::from_str("foo"))),
                              TokenTree::Token(sp(7, 8), token::Comma),
-                             TokenTree::Token(sp(8, 11), token::Ident(str_to_ident("bar")))];
+                             TokenTree::Token(sp(8, 11), token::Ident(Ident::from_str("bar")))];
 
-        let test1_parse = vec![TokenTree::Token(sp(0, 3), token::Ident(str_to_ident("baz"))),
+        let test1_parse = vec![TokenTree::Token(sp(0, 3), token::Ident(Ident::from_str("baz"))),
                                TokenTree::Delimited(sp(3, 12),
                                                     Rc::new(Delimited {
                                                         delim: token::DelimToken::Paren,
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
deleted file mode 100644 (file)
index f56c6ce..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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");
-    }
-}
index e0796c34e57efde74e2e0e046780785547279196..a6fff2d707469ffd2d4d1607dfb658b62b4a1139 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::Name;
 use std::cmp;
-use parse::token::InternedString;
+use symbol::Symbol;
 
 /// To find the Levenshtein distance between two strings
 pub fn lev_distance(a: &str, b: &str) -> usize {
@@ -48,14 +47,14 @@ pub fn lev_distance(a: &str, b: &str) -> usize {
 /// to one-third of the given word
 pub fn find_best_match_for_name<'a, T>(iter_names: T,
                                        lookup: &str,
-                                       dist: Option<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,
         }
     })
index df4eb1c9ed7d8053ac5382f817c502e42d4d608c..ce24fe1eb61e241d6eee5830c982e01b49c20638 100644 (file)
@@ -7,7 +7,8 @@
 // <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.
index 76d3f2a063c1884bd0d49b980ecbafe47c2a4e28..e703dc6b4191c50f933fa82e98777eb9cbf189fe 100644 (file)
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast;
+use ast::{self, Ident};
 use parse::{ParseSess,PResult,filemap_to_tts};
 use parse::{lexer, new_parser_from_source_str};
 use parse::parser::Parser;
-use parse::token;
 use ptr::P;
 use tokenstream;
 use std::iter::Peekable;
@@ -78,9 +77,9 @@ pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
     })
 }
 
-/// 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
index 7c1ff617ab64d00b46d07021b15c5f83ab79abb7..da36225fb329cdd17d51846e2b953a07abb82f6a 100644 (file)
@@ -746,7 +746,11 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) {
             }
             visitor.visit_path(path, expression.id)
         }
-        ExprKind::Break(ref opt_sp_ident) | ExprKind::Continue(ref opt_sp_ident) => {
+        ExprKind::Break(ref opt_sp_ident, ref opt_expr) => {
+            walk_opt_sp_ident(visitor, opt_sp_ident);
+            walk_list!(visitor, visit_expr, opt_expr);
+        }
+        ExprKind::Continue(ref opt_sp_ident) => {
             walk_opt_sp_ident(visitor, opt_sp_ident);
         }
         ExprKind::Ret(ref optional_expression) => {
index e4d0cb74046037a9407e421640445adaaacb8d16..a5e083f926a07ad97184355a2604f2c73ee4726a 100644 (file)
@@ -17,9 +17,9 @@
 use syntax::ext::base;
 use syntax::ext::base::*;
 use syntax::feature_gate;
-use syntax::parse::token::intern;
 use syntax::parse::{self, token};
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax::ast::AsmDialect;
 use syntax_pos::Span;
 use syntax::tokenstream;
@@ -73,7 +73,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
         })
         .unwrap_or(tts.len());
     let mut p = cx.new_parser_from_tts(&tts[first_colon..]);
-    let mut asm = token::InternedString::new("");
+    let mut asm = Symbol::intern("");
     let mut asm_str_style = None;
     let mut outputs = Vec::new();
     let mut inputs = Vec::new();
@@ -135,11 +135,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
                     // It's the opposite of '=&' which means that the memory
                     // cannot be shared with any other operand (usually when
                     // a register is clobbered early.)
-                    let mut ch = constraint.chars();
+                    let constraint_str = constraint.as_str();
+                    let mut ch = constraint_str.chars();
                     let output = match ch.next() {
                         Some('=') => None,
                         Some('+') => {
-                            Some(token::intern_and_get_ident(&format!("={}", ch.as_str())))
+                            Some(Symbol::intern(&format!("={}", ch.as_str())))
                         }
                         _ => {
                             cx.span_err(span, "output operand constraint lacks '=' or '+'");
@@ -148,9 +149,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
                     };
 
                     let is_rw = output.is_some();
-                    let is_indirect = constraint.contains("*");
+                    let is_indirect = constraint_str.contains("*");
                     outputs.push(ast::InlineAsmOutput {
-                        constraint: output.unwrap_or(constraint.clone()),
+                        constraint: output.unwrap_or(constraint),
                         expr: out,
                         is_rw: is_rw,
                         is_indirect: is_indirect,
@@ -166,9 +167,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
 
                     let (constraint, _str_style) = panictry!(p.parse_str());
 
-                    if constraint.starts_with("=") {
+                    if constraint.as_str().starts_with("=") {
                         cx.span_err(p.prev_span, "input operand constraint contains '='");
-                    } else if constraint.starts_with("+") {
+                    } else if constraint.as_str().starts_with("+") {
                         cx.span_err(p.prev_span, "input operand constraint contains '+'");
                     }
 
@@ -190,7 +191,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
 
                     if OPTIONS.iter().any(|&opt| s == opt) {
                         cx.span_warn(p.prev_span, "expected a clobber, found an option");
-                    } else if s.starts_with("{") || s.ends_with("}") {
+                    } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") {
                         cx.span_err(p.prev_span, "clobber should not be surrounded by braces");
                     }
 
@@ -242,7 +243,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
     let expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
         call_site: sp,
         callee: codemap::NameAndSpan {
-            format: codemap::MacroBang(intern("asm")),
+            format: codemap::MacroBang(Symbol::intern("asm")),
             span: None,
             allow_internal_unstable: false,
         },
@@ -251,7 +252,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt,
     MacEager::expr(P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprKind::InlineAsm(P(ast::InlineAsm {
-            asm: token::intern_and_get_ident(&asm),
+            asm: asm,
             asm_str_style: asm_str_style.unwrap(),
             outputs: outputs,
             inputs: inputs,
index 02b44f2d012ea101f224d69969ba2a401a45e1b7..bfe18dc4060c929820c2a6c363bf213c84193846 100644 (file)
@@ -11,7 +11,7 @@
 use syntax::ast;
 use syntax::ext::base;
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax_pos;
 use syntax::tokenstream;
 
@@ -33,7 +33,7 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                     ast::LitKind::Str(ref s, _) |
                     ast::LitKind::Float(ref s, _) |
                     ast::LitKind::FloatUnsuffixed(ref s) => {
-                        accumulator.push_str(&s);
+                        accumulator.push_str(&s.as_str());
                     }
                     ast::LitKind::Char(c) => {
                         accumulator.push(c);
@@ -57,5 +57,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
             }
         }
     }
-    base::MacEager::expr(cx.expr_str(sp, token::intern_and_get_ident(&accumulator[..])))
+    base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
 }
index e56c6e2229a75630657eedd7bcc164635b033541..b26e33eb384dc0017fc942a16ec9e62e0bf9e6c7 100644 (file)
@@ -13,7 +13,6 @@
 use syntax::ext::base;
 use syntax::feature_gate;
 use syntax::parse::token;
-use syntax::parse::token::str_to_ident;
 use syntax::ptr::P;
 use syntax_pos::Span;
 use syntax::tokenstream::TokenTree;
@@ -51,7 +50,7 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
             }
         }
     }
-    let res = str_to_ident(&res_str);
+    let res = ast::Ident::from_str(&res_str);
 
     struct Result {
         ident: ast::Ident,
index d7bc2a6faeeb993f29f60007b80e88e07815bdb4..d14b59d6c70e2f20bdaa0dde1ab1706501c10e22 100644 (file)
@@ -15,8 +15,8 @@
 use syntax::attr;
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::{keywords, InternedString};
 use syntax::ptr::P;
+use syntax::symbol::{Symbol, keywords};
 use syntax_pos::Span;
 
 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
@@ -74,7 +74,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
         _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"),
     }
 
-    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
index fa0fb2492c551c439287a6be89795bbe1cbc758d..6ab5987a159cad3983df2818414950279f52523f 100644 (file)
@@ -14,8 +14,8 @@
 use syntax::ast::{self, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_eq(cx: &mut ExtCtxt,
@@ -23,9 +23,9 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                           mitem: &MetaItem,
                           item: &Annotatable,
                           push: &mut FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, InternedString::new("inline"));
-    let hidden = cx.meta_list_item_word(span, InternedString::new("hidden"));
-    let doc = cx.meta_list(span, InternedString::new("doc"), vec![hidden]);
+    let inline = cx.meta_word(span, Symbol::intern("inline"));
+    let hidden = cx.meta_list_item_word(span, Symbol::intern("hidden"));
+    let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]);
     let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)];
     let trait_def = TraitDef {
         span: span,
index 6b2e36e63b65708d5152098d517405b075de9cea..9fc3d997585d711abfbc3fb2403a554c0bfc1deb 100644 (file)
@@ -14,8 +14,8 @@
 use syntax::ast::{self, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_ord(cx: &mut ExtCtxt,
@@ -23,7 +23,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                            mitem: &MetaItem,
                            item: &Annotatable,
                            push: &mut FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
index c46d4b34173f65fb48acefd057fc044264985ba5..f2a050ce971edc76d414d9998ccfaa70d0a414f7 100644 (file)
@@ -14,8 +14,8 @@
 use syntax::ast::{BinOpKind, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
@@ -64,7 +64,7 @@ fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
 
     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,
index 597ff306b3dd8edf4c7cb08d145cdd0a25f73be2..ce4d549d696f4d344fb3f2e938f9e370db456fb8 100644 (file)
@@ -16,8 +16,8 @@
 use syntax::ast::{self, BinOpKind, Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
@@ -27,7 +27,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
                                    push: &mut FnMut(Annotatable)) {
     macro_rules! md {
         ($name:expr, $op:expr, $equal:expr) => { {
-            let inline = cx.meta_word(span, InternedString::new("inline"));
+            let inline = cx.meta_word(span, Symbol::intern("inline"));
             let attrs = vec![cx.attribute(span, inline)];
             MethodDef {
                 name: $name,
@@ -51,7 +51,7 @@ macro_rules! md {
                                     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 {
index e101757ad23220dfabebc1a5a1ba707b245ca084..1076a6a6d63a5bef4e90c8816dc9304af46c4b8d 100644 (file)
 use syntax::codemap::Span;
 use syntax::ext::base::*;
 use syntax::fold::Folder;
-use syntax::parse::token::InternedString;
 use syntax::visit::Visitor;
 
-struct MarkAttrs<'a>(&'a [InternedString]);
+struct MarkAttrs<'a>(&'a [ast::Name]);
 
 impl<'a> Visitor for MarkAttrs<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
@@ -33,13 +32,11 @@ 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 }
     }
 }
index f367fed9cc2ceb52b788b75b5d40e6d960b86b5a..a767716466cb15d13e1902ecccf1fa4a97a73064 100644 (file)
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast;
+use syntax::ast::{self, Ident};
 use syntax::ast::{Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
 use syntax::ptr::P;
 use syntax_pos::{DUMMY_SP, Span};
 
@@ -69,9 +68,8 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
 
     // 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();
@@ -83,7 +81,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
             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 {
@@ -93,7 +91,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
 
                     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
@@ -103,12 +101,12 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
             } 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
@@ -116,7 +114,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
                     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));
                 }
@@ -126,7 +124,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
         _ => 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);
index dc1f7b4e6201e7132f989a8929b0337d7a6652cc..e2634c60dcaad0cd8f16ab3e824c8a54e8b7ccbb 100644 (file)
@@ -18,9 +18,8 @@
 use syntax::ast::{Expr, MetaItem, Mutability};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
-use syntax::parse::token;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
@@ -131,7 +130,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_struct"),
-                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, nfields),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
@@ -143,7 +142,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
             let rvariant_arg = cx.ident_of("read_enum_variant_arg");
 
             for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
-                variants.push(cx.expr_str(v_span, ident.name.as_str()));
+                variants.push(cx.expr_str(v_span, ident.name));
 
                 let path = cx.path(trait_span, vec![substr.type_ident, ident]);
                 let decoded = decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| {
@@ -175,7 +174,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_enum"),
-                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.lambda1(trait_span, result, blkarg)])
         }
         _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
@@ -191,7 +190,7 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
                            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) => {
@@ -202,10 +201,7 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
                 let fields = fields.iter()
                     .enumerate()
                     .map(|(i, &span)| {
-                        getarg(cx,
-                               span,
-                               token::intern_and_get_ident(&format!("_field{}", i)),
-                               i)
+                        getarg(cx, span, Symbol::intern(&format!("_field{}", i)), i)
                     })
                     .collect();
 
@@ -217,7 +213,7 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
             let fields = fields.iter()
                 .enumerate()
                 .map(|(i, &(ident, span))| {
-                    let arg = getarg(cx, span, ident.name.as_str(), i);
+                    let arg = getarg(cx, span, ident.name, i);
                     cx.field_imm(span, ident, arg)
                 })
                 .collect();
index b15fd2b49a65547c241ed463f0c5a55767754f71..69391f48c2288dd512119c79d23412b5423b53ba 100644 (file)
@@ -14,8 +14,8 @@
 use syntax::ast::{Expr, MetaItem};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::InternedString;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_default(cx: &mut ExtCtxt,
@@ -23,7 +23,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
                                mitem: &MetaItem,
                                item: &Annotatable,
                                push: &mut FnMut(Annotatable)) {
-    let inline = cx.meta_word(span, InternedString::new("inline"));
+    let inline = cx.meta_word(span, Symbol::intern("inline"));
     let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
index ebbddc6e48084464208cd33b9dacce183863b98b..092738ab8a03d372333f6272ae608e775cc9d617 100644 (file)
@@ -95,8 +95,8 @@
 use syntax::ast::{Expr, ExprKind, MetaItem, Mutability};
 use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
@@ -192,8 +192,8 @@ fn encodable_substructure(cx: &mut ExtCtxt,
             let mut stmts = Vec::new();
             for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
                 let name = match name {
-                    Some(id) => id.name.as_str(),
-                    None => token::intern_and_get_ident(&format!("_field{}", i)),
+                    Some(id) => id.name,
+                    None => Symbol::intern(&format!("_field{}", i)),
                 };
                 let self_ref = cx.expr_addr_of(span, self_.clone());
                 let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
@@ -226,7 +226,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
             cx.expr_method_call(trait_span,
                                 encoder,
                                 cx.ident_of("emit_struct"),
-                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                vec![cx.expr_str(trait_span, substr.type_ident.name),
                                      cx.expr_usize(trait_span, fields.len()),
                                      blk])
         }
@@ -265,7 +265,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
             }
 
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
-            let name = cx.expr_str(trait_span, variant.node.name.name.as_str());
+            let name = cx.expr_str(trait_span, variant.node.name.name);
             let call = cx.expr_method_call(trait_span,
                                            blkencoder,
                                            cx.ident_of("emit_enum_variant"),
@@ -277,8 +277,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
             let ret = cx.expr_method_call(trait_span,
                                           encoder,
                                           cx.ident_of("emit_enum"),
-                                          vec![cx.expr_str(trait_span,
-                                                           substr.type_ident.name.as_str()),
+                                          vec![cx.expr_str(trait_span ,substr.type_ident.name),
                                                blk]);
             cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
         }
index e6b63be3efc0d963f063d7b665c56966f38bf8b3..63cd7678321ef832686b8f68fe827d064e8839dd 100644 (file)
 use syntax::ext::build::AstBuilder;
 use syntax::codemap::{self, dummy_spanned, respan};
 use syntax::util::move_map::MoveMap;
-use syntax::parse::token::{InternedString, keywords};
 use syntax::ptr::P;
+use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{DUMMY_SP, Span};
 use errors::Handler;
 
@@ -442,7 +442,7 @@ pub fn expand_ext(&self,
                 attrs.extend(item.attrs
                     .iter()
                     .filter(|a| {
-                        match &a.name()[..] {
+                        match &*a.name().as_str() {
                             "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
                             _ => false,
                         }
@@ -639,15 +639,15 @@ fn create_derived_impl(&self,
 
         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());
 
index b1d473820f774b1914c37cac18277a1843d28dee..535d7de19e341aa5432f89d3a57512cd21f19f08 100644 (file)
@@ -16,8 +16,8 @@
 use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate::{self, emit_feature_err};
-use syntax::parse::token::{intern, intern_and_get_ident};
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 macro_rules! pathvec {
@@ -80,7 +80,7 @@ fn allow_unstable(cx: &mut ExtCtxt, span: Span, attr_name: &str) -> Span {
         expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
             call_site: span,
             callee: codemap::NameAndSpan {
-                format: codemap::MacroAttribute(intern(attr_name)),
+                format: codemap::MacroAttribute(Symbol::intern(attr_name)),
                 span: Some(span),
                 allow_internal_unstable: true,
             },
@@ -105,9 +105,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         }
     };
 
+    let derive = Symbol::intern("derive");
     let mut derive_attrs = Vec::new();
     item = item.map_attrs(|attrs| {
-        let partition = attrs.into_iter().partition(|attr| &attr.name() == "derive");
+        let partition = attrs.into_iter().partition(|attr| attr.name() == derive);
         derive_attrs = partition.0;
         partition.1
     });
@@ -115,7 +116,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
     // Expand `#[derive]`s after other attribute macro invocations.
     if cx.resolver.find_attr_invoc(&mut item.attrs.clone()).is_some() {
         return vec![Annotatable::Item(item.map_attrs(|mut attrs| {
-            attrs.push(cx.attribute(span, P(mitem.clone())));
+            attrs.push(cx.attribute(span, mitem.clone()));
             attrs.extend(derive_attrs);
             attrs
         }))];
@@ -135,7 +136,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
 
     let mut traits = get_traits(mitem, cx);
     for derive_attr in derive_attrs {
-        traits.extend(get_traits(&derive_attr.node.value, cx));
+        traits.extend(get_traits(&derive_attr.value, cx));
     }
 
     // First, weed out malformed #[derive]
@@ -158,9 +159,8 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         let tword = titem.word().unwrap();
         let tname = tword.name();
 
-        if is_builtin_trait(&tname) || {
-            let derive_mode =
-                ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(intern(&tname)));
+        if is_builtin_trait(tname) || {
+            let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname));
             cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| {
                 if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false }
             }).unwrap_or(false)
@@ -176,7 +176,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
                                            feature_gate::EXPLAIN_CUSTOM_DERIVE);
         } else {
             cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE);
-            let name = intern_and_get_ident(&format!("derive_{}", tname));
+            let name = Symbol::intern(&format!("derive_{}", tname));
             let mitem = cx.meta_word(titem.span, name);
             new_attributes.push(cx.attribute(mitem.span, mitem));
         }
@@ -186,9 +186,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         item = item.map(|mut i| {
             i.attrs.extend(new_attributes);
             if traits.len() > 0 {
-                let list = cx.meta_list(mitem.span,
-                                        intern_and_get_ident("derive"),
-                                        traits);
+                let list = cx.meta_list(mitem.span, derive, traits);
                 i.attrs.push(cx.attribute(mitem.span, list));
             }
             i
@@ -217,7 +215,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
     let macros_11_derive = traits.iter()
                                  .cloned()
                                  .enumerate()
-                                 .filter(|&(_, ref name)| !is_builtin_trait(&name.name().unwrap()))
+                                 .filter(|&(_, ref name)| !is_builtin_trait(name.name().unwrap()))
                                  .next();
     if let Some((i, titem)) = macros_11_derive {
         if !cx.ecfg.features.unwrap().proc_macro {
@@ -226,24 +224,20 @@ pub fn expand_derive(cx: &mut ExtCtxt,
             emit_feature_err(cx.parse_sess, "proc_macro", titem.span, issue, msg);
         }
 
-        let tname = ast::Ident::with_empty_ctxt(intern(&titem.name().unwrap()));
+        let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap());
         let path = ast::Path::from_ident(titem.span, tname);
         let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap();
 
         traits.remove(i);
         if traits.len() > 0 {
             item = item.map(|mut i| {
-                let list = cx.meta_list(mitem.span,
-                                        intern_and_get_ident("derive"),
-                                        traits);
+                let list = cx.meta_list(mitem.span, derive, traits);
                 i.attrs.push(cx.attribute(mitem.span, list));
                 i
             });
         }
         let titem = cx.meta_list_item_word(titem.span, titem.name().unwrap());
-        let mitem = cx.meta_list(titem.span,
-                                 intern_and_get_ident("derive"),
-                                 vec![titem]);
+        let mitem = cx.meta_list(titem.span, derive, vec![titem]);
         let item = Annotatable::Item(item);
         if let SyntaxExtension::CustomDerive(ref ext) = *ext {
             return ext.expand(cx, mitem.span, &mitem, item);
@@ -257,9 +251,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
 
     // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
     // `#[structural_match]` attribute.
-    if traits.iter().filter_map(|t| t.name()).any(|t| t == "PartialEq") &&
-       traits.iter().filter_map(|t| t.name()).any(|t| t == "Eq") {
-        let structural_match = intern_and_get_ident("structural_match");
+    let (partial_eq, eq) = (Symbol::intern("PartialEq"), Symbol::intern("Eq"));
+    if traits.iter().any(|t| t.name() == Some(partial_eq)) &&
+       traits.iter().any(|t| t.name() == Some(eq)) {
+        let structural_match = Symbol::intern("structural_match");
         let span = allow_unstable(cx, span, "derive(PartialEq, Eq)");
         let meta = cx.meta_word(span, structural_match);
         item = item.map(|mut i| {
@@ -272,9 +267,10 @@ pub fn expand_derive(cx: &mut ExtCtxt,
     // the same as the copy implementation.
     //
     // Add a marker attribute here picked up during #[derive(Clone)]
-    if traits.iter().filter_map(|t| t.name()).any(|t| t == "Clone") &&
-       traits.iter().filter_map(|t| t.name()).any(|t| t == "Copy") {
-        let marker = intern_and_get_ident("rustc_copy_clone_marker");
+    let (copy, clone) = (Symbol::intern("Copy"), Symbol::intern("Clone"));
+    if traits.iter().any(|t| t.name() == Some(clone)) &&
+       traits.iter().any(|t| t.name() == Some(copy)) {
+        let marker = Symbol::intern("rustc_copy_clone_marker");
         let span = allow_unstable(cx, span, "derive(Copy, Clone)");
         let meta = cx.meta_word(span, marker);
         item = item.map(|mut i| {
@@ -286,14 +282,14 @@ pub fn expand_derive(cx: &mut ExtCtxt,
     let mut items = Vec::new();
     for titem in traits.iter() {
         let tname = titem.word().unwrap().name();
-        let name = intern_and_get_ident(&format!("derive({})", tname));
+        let name = Symbol::intern(&format!("derive({})", tname));
         let mitem = cx.meta_word(titem.span, name);
 
         let span = Span {
             expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
                 call_site: titem.span,
                 callee: codemap::NameAndSpan {
-                    format: codemap::MacroAttribute(intern(&format!("derive({})", tname))),
+                    format: codemap::MacroAttribute(Symbol::intern(&format!("derive({})", tname))),
                     span: Some(titem.span),
                     allow_internal_unstable: true,
                 },
@@ -302,7 +298,7 @@ pub fn expand_derive(cx: &mut ExtCtxt,
         };
 
         let my_item = Annotatable::Item(item);
-        expand_builtin(&tname, cx, span, &mitem, &my_item, &mut |a| {
+        expand_builtin(&tname.as_str(), cx, span, &mitem, &my_item, &mut |a| {
             items.push(a);
         });
         item = my_item.expect_item();
@@ -314,8 +310,8 @@ pub fn expand_derive(cx: &mut ExtCtxt,
 
 macro_rules! derive_traits {
     ($( $name:expr => $func:path, )+) => {
-        pub fn is_builtin_trait(name: &str) -> bool {
-            match name {
+        pub fn is_builtin_trait(name: ast::Name) -> bool {
+            match &*name.as_str() {
                 $( $name )|+ => true,
                 _ => false,
             }
@@ -412,7 +408,7 @@ fn call_intrinsic(cx: &ExtCtxt,
     span.expn_id = cx.codemap().record_expansion(codemap::ExpnInfo {
         call_site: span,
         callee: codemap::NameAndSpan {
-            format: codemap::MacroAttribute(intern("derive")),
+            format: codemap::MacroAttribute(Symbol::intern("derive")),
             span: Some(span),
             allow_internal_unstable: true,
         },
index 5c081b98962e310345110f2b5efe7561a97d2c70..ecf0a8f377ea3dc3c81f220cc3688020525778bf 100644 (file)
@@ -17,7 +17,7 @@
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use syntax::tokenstream;
 
@@ -32,7 +32,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
         Some(v) => v,
     };
 
-    let e = match env::var(&var[..]) {
+    let e = match env::var(&*var.as_str()) {
         Err(..) => {
             cx.expr_path(cx.path_all(sp,
                                      true,
@@ -49,7 +49,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt,
         Ok(s) => {
             cx.expr_call_global(sp,
                                 cx.std_path(&["option", "Option", "Some"]),
-                                vec![cx.expr_str(sp, token::intern_and_get_ident(&s[..]))])
+                                vec![cx.expr_str(sp, Symbol::intern(&s))])
         }
     };
     MacEager::expr(e)
@@ -73,7 +73,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
         Some((v, _style)) => v,
     };
     let msg = match exprs.next() {
-        None => token::intern_and_get_ident(&format!("environment variable `{}` not defined", var)),
+        None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
         Some(second) => {
             match expr_to_string(cx, second, "expected string literal") {
                 None => return DummyResult::expr(sp),
@@ -87,12 +87,12 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt,
         return DummyResult::expr(sp);
     }
 
-    let e = match env::var(&var[..]) {
+    let e = match env::var(&*var.as_str()) {
         Err(_) => {
-            cx.span_err(sp, &msg);
+            cx.span_err(sp, &msg.as_str());
             cx.expr_usize(sp, 0)
         }
-        Ok(s) => cx.expr_str(sp, token::intern_and_get_ident(&s)),
+        Ok(s) => cx.expr_str(sp, Symbol::intern(&s)),
     };
     MacEager::expr(e)
 }
index 6eba8baf5b82496b002284fff2d59ef14f46bc2f..d2afa08cadaf4efb40b16f32b46996a9078dc06a 100644 (file)
@@ -17,8 +17,9 @@
 use syntax::ext::base::*;
 use syntax::ext::base;
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::{self, keywords};
+use syntax::parse::token;
 use syntax::ptr::P;
+use syntax::symbol::{Symbol, keywords};
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::tokenstream;
 
@@ -369,7 +370,7 @@ fn trans_count(&self, c: parse::Count) -> P<ast::Expr> {
     /// 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)
     }
@@ -727,7 +728,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         fmtsp: fmt.span,
     };
 
-    let mut parser = parse::Parser::new(&fmt.node.0);
+    let fmt_str = &*fmt.node.0.as_str();
+    let mut parser = parse::Parser::new(fmt_str);
     let mut pieces = vec![];
 
     loop {
@@ -808,7 +810,6 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
         // Decide if we want to look for foreign formatting directives.
         if args_used < args_unused {
             use super::format_foreign as foreign;
-            let fmt_str = &fmt.node.0[..];
 
             // The set of foreign substitutions we've explained.  This prevents spamming the user
             // with `%d should be written as {}` over and over again.
index 1ebac19b4f029ddab1bddc2199fb90e67371f263..e83fd55cd714bfe5032e593fd66e880d2d4b9040 100644 (file)
@@ -53,7 +53,7 @@
 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>,
@@ -62,11 +62,11 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
         resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };
 
-    register(intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
+    register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
 
     macro_rules! register {
         ($( $name:ident: $f:expr, )*) => { $(
-            register(intern(stringify!($name)),
+            register(Symbol::intern(stringify!($name)),
                      NormalTT(Box::new($f as MacroExpanderFn), None, false));
         )* }
     }
@@ -112,9 +112,10 @@ macro_rules! register {
     }
 
     // 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);
index d6d31200a994fcbc29d99422c4c21c56e48085f0..bbdbda701ae8eba464d48f88f7a9f6b9e33e8d16 100644 (file)
 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> {
@@ -38,12 +38,14 @@ 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 {
@@ -55,6 +57,7 @@ pub fn modify(sess: &ParseSess,
         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);
 
@@ -137,6 +140,12 @@ fn visit_item(&mut self, item: &ast::Item) {
                                              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 \
@@ -174,7 +183,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             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");
         }
@@ -262,29 +271,29 @@ fn mk_registrar(cx: &mut ExtCtxt,
     let eid = cx.codemap().record_expansion(ExpnInfo {
         call_site: DUMMY_SP,
         callee: NameAndSpan {
-            format: MacroAttribute(token::intern("proc_macro")),
+            format: MacroAttribute(Symbol::intern("proc_macro")),
             span: None,
             allow_internal_unstable: true,
         }
     });
     let span = Span { expn_id: eid, ..DUMMY_SP };
 
-    let proc_macro = token::str_to_ident("proc_macro");
+    let proc_macro = Ident::from_str("proc_macro");
     let krate = cx.item(span,
                         proc_macro,
                         Vec::new(),
                         ast::ItemKind::ExternCrate(None));
 
-    let __internal = token::str_to_ident("__internal");
-    let registry = token::str_to_ident("Registry");
-    let registrar = token::str_to_ident("registrar");
-    let register_custom_derive = token::str_to_ident("register_custom_derive");
+    let __internal = Ident::from_str("__internal");
+    let registry = Ident::from_str("Registry");
+    let registrar = Ident::from_str("registrar");
+    let register_custom_derive = Ident::from_str("register_custom_derive");
     let stmts = custom_derives.iter().map(|cd| {
         let path = cx.path_global(cd.span, vec![cd.function_name]);
-        let trait_name = cx.expr_str(cd.span, cd.trait_name.clone());
+        let trait_name = cx.expr_str(cd.span, cd.trait_name);
         let attrs = cx.expr_vec_slice(
             span,
-            cd.attrs.iter().map(|s| cx.expr_str(cd.span, s.clone())).collect::<Vec<_>>()
+            cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::<Vec<_>>()
         );
         (path, trait_name, attrs)
     }).map(|(path, trait_name, attrs)| {
@@ -307,15 +316,14 @@ fn mk_registrar(cx: &mut ExtCtxt,
                           cx.ty(span, ast::TyKind::Tup(Vec::new())),
                           cx.block(span, stmts));
 
-    let derive_registrar = token::intern_and_get_ident("rustc_derive_registrar");
-    let derive_registrar = cx.meta_word(span, derive_registrar);
+    let derive_registrar = cx.meta_word(span, Symbol::intern("rustc_derive_registrar"));
     let derive_registrar = cx.attribute(span, derive_registrar);
     let func = func.map(|mut i| {
         i.attrs.push(derive_registrar);
         i.vis = ast::Visibility::Public;
         i
     });
-    let ident = ast::Ident::with_empty_ctxt(token::gensym("registrar"));
+    let ident = ast::Ident::with_empty_ctxt(Symbol::gensym("registrar"));
     let module = cx.item_mod(span, span, ident, Vec::new(), vec![krate, func]).map(|mut i| {
         i.vis = ast::Visibility::Public;
         i
index 9578af68100782d0611ba79239c4643908b7eda0..48be8e0c53c2ed2c41363da6e7c843efb8053135 100644 (file)
@@ -11,7 +11,7 @@
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::base;
 use syntax::feature_gate;
-use syntax::parse::token::keywords;
+use syntax::symbol::keywords;
 use syntax_pos::Span;
 use syntax::tokenstream::TokenTree;
 
index a5ba1d219c369facd880704562ecc5b971294fb2..70f7ee3004dd437a74832efc6e9b72c7abdf245c 100644 (file)
@@ -22,6 +22,9 @@
 #include "llvm/Target/TargetSubtargetInfo.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 
+#if LLVM_VERSION_GE(4, 0)
+#include "llvm/Transforms/IPO/AlwaysInliner.h"
+#endif
 
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
@@ -539,7 +542,11 @@ LLVMRustPrintPasses() {
 
 extern "C" void
 LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) {
+#if LLVM_VERSION_GE(4, 0)
+    unwrap(PMB)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
+#else
     unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes);
+#endif
 }
 
 extern "C" void
index 369388caa0496046bafe5b8e5d05c051578fd431..b035e134e37d52abedff817571f0f6e362991de8 100644 (file)
@@ -109,37 +109,82 @@ extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
   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));
 }
 
@@ -153,16 +198,6 @@ extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
   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,
@@ -175,31 +210,16 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
 
 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
@@ -1293,3 +1313,7 @@ extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
 extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
     LLVMSetLinkage(V, from_rust(RustLinkage));
 }
+
+extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
+    return wrap(&unwrap(V)->getContext());
+}
index ffe94d1e22f20b117bd607cb3ab129f10ef75100..346153d578c4a8afab4c24c50aed475f2fce557f 100644 (file)
@@ -72,6 +72,28 @@ enum class LLVMRustResult {
     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;
index 8ea131da338cb1bd61f60fac56e32fe166a8beb6..8647797270f9a841f5092b974faf0ec745509cbb 100644 (file)
@@ -36,7 +36,7 @@ fn get_lints(&self) -> LintArray {
 
 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'");
         }
     }
index 409f9dbf03c54f160c7e5157befb172451d9995c..dc88bfc40595f4401da5db5c86f16c2eede12ccd 100644 (file)
@@ -19,8 +19,9 @@
 
 use syntax::ast::{self, Item, MetaItem, ItemKind};
 use syntax::ext::base::*;
-use syntax::parse::{self, token};
+use syntax::parse;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax::tokenstream::TokenTree;
 use syntax_pos::Span;
 use rustc_plugin::Registry;
@@ -34,11 +35,11 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_macro("make_a_1", expand_make_a_1);
     reg.register_macro("identity", expand_identity);
     reg.register_syntax_extension(
-        token::intern("into_multi_foo"),
+        Symbol::intern("into_multi_foo"),
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         MultiModifier(Box::new(expand_into_foo_multi)));
     reg.register_syntax_extension(
-        token::intern("duplicate"),
+        Symbol::intern("duplicate"),
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         MultiDecorator(Box::new(expand_duplicate)));
 }
@@ -102,9 +103,9 @@ fn expand_duplicate(cx: &mut ExtCtxt,
                     push: &mut FnMut(Annotatable))
 {
     let copy_name = match mi.node {
-        ast::MetaItemKind::List(_, ref xs) => {
+        ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                token::str_to_ident(&word.name())
+                ast::Ident::with_empty_ctxt(word.name())
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/error-on-test.rs b/src/test/compile-fail-fulldeps/proc-macro/error-on-test.rs
new file mode 100644 (file)
index 0000000..1fd48f0
--- /dev/null
@@ -0,0 +1,22 @@
+// 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()
+}
index 4a7033d44b87858e65e5479c8bb9a4b52825536a..8acab3369e48fb3ef3ba71b3c45160eaf2750970 100644 (file)
@@ -16,8 +16,8 @@
 extern crate syntax_pos;
 
 use syntax::ast;
-use syntax::parse;
 use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax_pos::DUMMY_SP;
 
 fn main() {
@@ -30,7 +30,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            format: syntax::codemap::MacroBang(parse::token::intern("")),
+            format: syntax::codemap::MacroBang(Symbol::intern("")),
             allow_internal_unstable: false,
             span: None,
         }
index 0b235aa240c3cbd0f178188a9f4cf6043d3507ba..9ec09603224107bf298f2e2e282c852cfff6f5d7 100644 (file)
@@ -9,7 +9,12 @@
 // except according to those terms.
 
 fn f() {}
+fn g<'a>() {}
 
 fn main() {
     f::<'static>(); //~ ERROR E0088
+    //~^ unexpected lifetime parameter
+
+    g::<'static, 'static>(); //~ ERROR E0088
+    //~^ unexpected lifetime parameters
 }
diff --git a/src/test/compile-fail/auxiliary/issue_12612_1.rs b/src/test/compile-fail/auxiliary/issue_12612_1.rs
deleted file mode 100644 (file)
index a0234c1..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
-}
diff --git a/src/test/compile-fail/auxiliary/namespace-mix-new.rs b/src/test/compile-fail/auxiliary/namespace-mix-new.rs
deleted file mode 100644 (file)
index d42c0ee..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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;
-}
diff --git a/src/test/compile-fail/auxiliary/namespace-mix-old.rs b/src/test/compile-fail/auxiliary/namespace-mix-old.rs
deleted file mode 100644 (file)
index 29b139d..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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;
-}
diff --git a/src/test/compile-fail/auxiliary/namespace-mix.rs b/src/test/compile-fail/auxiliary/namespace-mix.rs
new file mode 100644 (file)
index 0000000..d82e9bb
--- /dev/null
@@ -0,0 +1,76 @@
+// 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;
+}
diff --git a/src/test/compile-fail/auxiliary/rmeta_meta.rs b/src/test/compile-fail/auxiliary/rmeta_meta.rs
new file mode 100644 (file)
index 0000000..7bd1a96
--- /dev/null
@@ -0,0 +1,17 @@
+// 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,
+}
diff --git a/src/test/compile-fail/auxiliary/rmeta_rlib.rs b/src/test/compile-fail/auxiliary/rmeta_rlib.rs
new file mode 100644 (file)
index 0000000..6096c4d
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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,
+}
index 1dbad9e30e3addd8c4f7293a9d585437db6efe94..b98f464c902278443f7ecec8231ea4efc6c6508b 100644 (file)
@@ -115,4 +115,9 @@ fn main()
     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`?
 }
diff --git a/src/test/compile-fail/directory_ownership/backcompat-warnings.rs b/src/test/compile-fail/directory_ownership/backcompat-warnings.rs
new file mode 100644 (file)
index 0000000..75e3426
--- /dev/null
@@ -0,0 +1,21 @@
+// 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() {}
diff --git a/src/test/compile-fail/directory_ownership/macro-expanded-mod.rs b/src/test/compile-fail/directory_ownership/macro-expanded-mod.rs
new file mode 100644 (file)
index 0000000..8e631a6
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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
+}
diff --git a/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/bar.rs b/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/bar.rs
new file mode 100644 (file)
index 0000000..3ec3436
--- /dev/null
@@ -0,0 +1,11 @@
+// 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
diff --git a/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/mod.rs b/src/test/compile-fail/directory_ownership/macro_expanded_mod_helper/foo/mod.rs
new file mode 100644 (file)
index 0000000..25fcf11
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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);
diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning.rs
new file mode 100644 (file)
index 0000000..adbcedd
--- /dev/null
@@ -0,0 +1,15 @@
+// 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() {}
diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux1.rs
new file mode 100644 (file)
index 0000000..4ac94a9
--- /dev/null
@@ -0,0 +1,16 @@
+// 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!();
diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux2.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux2.rs
new file mode 100644 (file)
index 0000000..41401d6
--- /dev/null
@@ -0,0 +1,11 @@
+// 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
diff --git a/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs b/src/test/compile-fail/directory_ownership/mod_file_not_owning_aux3.rs
new file mode 100644 (file)
index 0000000..3a164fd
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
diff --git a/src/test/compile-fail/directory_ownership/non-inline-mod-restriction.rs b/src/test/compile-fail/directory_ownership/non-inline-mod-restriction.rs
new file mode 100644 (file)
index 0000000..c4ede12
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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
+}
diff --git a/src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs b/src/test/compile-fail/directory_ownership/unowned_mod_with_path.rs
new file mode 100644 (file)
index 0000000..854f790
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
diff --git a/src/test/compile-fail/feature-gate-loop-break-value.rs b/src/test/compile-fail/feature-gate-loop-break-value.rs
new file mode 100644 (file)
index 0000000..1632c40
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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
+    }
+}
index 077ae19b4cbd6b71058cf3bb398be19e2b2dabb0..8f1b8ec91db38aafa4b79e74ebe7cbb89a71387e 100644 (file)
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(rustc_attrs)]
+
 mod foo {
     pub use bar::*;
-    pub use main as f; //~ ERROR has already been imported
+    pub use main as f;
 }
 
 mod bar {
@@ -18,9 +20,10 @@ mod bar {
 }
 
 pub use foo::*;
-pub use baz::*; //~ ERROR has already been imported
+pub use baz::*;
 mod baz {
     pub use super::*;
 }
 
-pub fn main() {}
+#[rustc_error]
+pub fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/import-shadow-1.rs b/src/test/compile-fail/import-shadow-1.rs
deleted file mode 100644 (file)
index 503fa4e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-2.rs b/src/test/compile-fail/import-shadow-2.rs
deleted file mode 100644 (file)
index 0c107cf..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-3.rs b/src/test/compile-fail/import-shadow-3.rs
deleted file mode 100644 (file)
index bf90973..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-4.rs b/src/test/compile-fail/import-shadow-4.rs
deleted file mode 100644 (file)
index f21fdaa..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-5.rs b/src/test/compile-fail/import-shadow-5.rs
deleted file mode 100644 (file)
index dc300bc..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/import-shadow-6.rs
deleted file mode 100644 (file)
index fa3b75c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/import-shadow-7.rs b/src/test/compile-fail/import-shadow-7.rs
deleted file mode 100644 (file)
index 34aba15..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
index 1ca1c060410adb1b44fecc132103d2fc78680000..81a5334ed7ab7675867ad8c184784b12d72095c6 100644 (file)
@@ -20,6 +20,6 @@ mod zed {
 }
 
 fn main() {
-    zed::foo(); //~ ERROR unresolved name
+    zed::foo(); //~ ERROR `foo` is private
     bar();
 }
index faf85a523e8fb01fdf33c6b00e45b3ff20fd1037..8dd69d8c24c855afc267e983199f09e1ed103675 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(item_like_imports)]
-
 mod a {
     pub fn foo() {}
 }
index fc46b23351adf071f8e5893c71285ad495340452..65e6e8d01b05f119c6bd6de43eb287c5ed4df57c 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(item_like_imports)]
-
 mod a {
     fn foo() {}
     mod foo {}
index 4ec9987df4208fb673b7b4a5c9f32cbf42b56960..05ecc781af30d53b22689e613d3ab4ca74eb8351 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(pub_restricted, item_like_imports)]
+#![feature(pub_restricted)]
 #![deny(unused)]
 
 mod foo {
diff --git a/src/test/compile-fail/issue-12612.rs b/src/test/compile-fail/issue-12612.rs
deleted file mode 100644 (file)
index c6f76ca..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
index af75783a710b53c2fc3d7f598e52b94462a599a3..2c54ed3e857e93130c5456b62fd54417b7214945 100644 (file)
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(rustc_attrs)]
+
 pub use bar::*;
 mod bar {
     pub use super::*;
 }
 
-pub use baz::*; //~ ERROR already been imported
+pub use baz::*;
 mod baz {
     pub use main as f;
 }
 
-pub fn main() {}
+#[rustc_error]
+pub fn main() {} //~ ERROR compilation successful
index d610e8b483798af81cf2c1df4a57f5054a925b72..41383e93603d36cd3b12921a95c3f774b9535900 100644 (file)
@@ -11,8 +11,7 @@
 use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
               //~^ no `Foo` in `bar`
 mod bar {
-    use Foo; //~ ERROR unresolved import `Foo` [E0432]
-             //~^ no `Foo` in the root
+    use Foo;
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/loop-break-value.rs b/src/test/compile-fail/loop-break-value.rs
new file mode 100644 (file)
index 0000000..d4f2959
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+    };
+}
diff --git a/src/test/compile-fail/macro-expanded-mod.rs b/src/test/compile-fail/macro-expanded-mod.rs
deleted file mode 100644 (file)
index 8e631a6..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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
-}
diff --git a/src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs b/src/test/compile-fail/macro_expanded_mod_helper/foo/bar.rs
deleted file mode 100644 (file)
index 3ec3436..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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
diff --git a/src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs b/src/test/compile-fail/macro_expanded_mod_helper/foo/mod.rs
deleted file mode 100644 (file)
index 25fcf11..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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);
diff --git a/src/test/compile-fail/mod_file_not_owning.rs b/src/test/compile-fail/mod_file_not_owning.rs
deleted file mode 100644 (file)
index 7dcff6e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/mod_file_not_owning_aux1.rs b/src/test/compile-fail/mod_file_not_owning_aux1.rs
deleted file mode 100644 (file)
index 2d522be..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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;
diff --git a/src/test/compile-fail/mod_file_not_owning_aux2.rs b/src/test/compile-fail/mod_file_not_owning_aux2.rs
deleted file mode 100644 (file)
index 41401d6..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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
diff --git a/src/test/compile-fail/namespace-mix-new.rs b/src/test/compile-fail/namespace-mix-new.rs
deleted file mode 100644 (file)
index 59592e3..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/namespace-mix-old.rs b/src/test/compile-fail/namespace-mix-old.rs
deleted file mode 100644 (file)
index 8cd8205..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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() {}
diff --git a/src/test/compile-fail/namespace-mix.rs b/src/test/compile-fail/namespace-mix.rs
new file mode 100644 (file)
index 0000000..cb7894b
--- /dev/null
@@ -0,0 +1,165 @@
+// 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() {}
diff --git a/src/test/compile-fail/non-inline-mod-restriction.rs b/src/test/compile-fail/non-inline-mod-restriction.rs
deleted file mode 100644 (file)
index c4ede12..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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
-}
index 376e95312b8fbf6b1cc7df7034e1bf42cbae3edc..113dd2879406892e60fa0938d6e433b76393b258 100644 (file)
@@ -31,8 +31,7 @@ fn test1() {
 
 fn test2() {
     use bar::glob::foo;
-    //~^ ERROR unresolved import `bar::glob::foo` [E0432]
-    //~| no `foo` in `bar::glob`
+    //~^ ERROR `foo` is private
 }
 
 #[start] fn main(_: isize, _: *const *const u8) -> isize { 3 }
diff --git a/src/test/compile-fail/rmeta-lib-pass.rs b/src/test/compile-fail/rmeta-lib-pass.rs
new file mode 100644 (file)
index 0000000..f2ac37a
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 };
+}
diff --git a/src/test/compile-fail/rmeta-pass.rs b/src/test/compile-fail/rmeta-pass.rs
new file mode 100644 (file)
index 0000000..2c0b6f7
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 };
+}
diff --git a/src/test/compile-fail/rmeta.rs b/src/test/compile-fail/rmeta.rs
new file mode 100644 (file)
index 0000000..e81e054
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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`
+}
diff --git a/src/test/compile-fail/rmeta_lib.rs b/src/test/compile-fail/rmeta_lib.rs
new file mode 100644 (file)
index 0000000..3b7d1f3
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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 };
+}
diff --git a/src/test/compile-fail/rmeta_meta_main.rs b/src/test/compile-fail/rmeta_meta_main.rs
new file mode 100644 (file)
index 0000000..1c922c2
--- /dev/null
@@ -0,0 +1,24 @@
+// 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`
+}
index 1bf7f3933849de76ba2307357ba574ebc776b90c..e7e57a73de02f7176fa6d6a8a70b77114489a29d 100644 (file)
@@ -16,11 +16,11 @@ pub fn f() {}
 }
 
 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() {}
index 3d8e2daaa15b15616cb3d3e08bb7c460e0bce728..44e9260770e03ccfe83441c2b83b1dc32566310b 100644 (file)
@@ -31,11 +31,11 @@ enum E {
 const XUnit: u8 = 0;
 
 extern crate variant_namespacing;
-pub use variant_namespacing::XE::*;
+pub use variant_namespacing::XE::{XStruct, XTuple, XUnit};
 //~^ ERROR `XStruct` has already been defined
 //~| ERROR `XTuple` has already been defined
 //~| ERROR `XUnit` has already been defined
-pub use E::*;
+pub use E::{Struct, Tuple, Unit};
 //~^ ERROR `Struct` has already been defined
 //~| ERROR `Tuple` has already been defined
 //~| ERROR `Unit` has already been defined
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
new file mode 100644 (file)
index 0000000..261eb38
--- /dev/null
@@ -0,0 +1,164 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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() {
+}
diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
new file mode 100644 (file)
index 0000000..665eafb
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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() {
+}
diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
new file mode 100644 (file)
index 0000000..54e06e1
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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() {
+}
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
new file mode 100644 (file)
index 0000000..7a8502f
--- /dev/null
@@ -0,0 +1,306 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+    }
+}
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
new file mode 100644 (file)
index 0000000..eaa5f68
--- /dev/null
@@ -0,0 +1,231 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+    }
+}
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
new file mode 100644 (file)
index 0000000..c4366ea
--- /dev/null
@@ -0,0 +1,254 @@
+// 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)
+    }
+}
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
new file mode 100644 (file)
index 0000000..405645b
--- /dev/null
@@ -0,0 +1,256 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+    }
+}
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
new file mode 100644 (file)
index 0000000..f16611e
--- /dev/null
@@ -0,0 +1,256 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+    }
+}
index 7def91da5eca4da1926f08578a3397398adff655..092adbf29e340cd52394c00e169fdb4dd746544f 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z parse-only
 
-// error-pattern:expected `]`
+// error-pattern:expected one of `=` or `]`
 
 // asterisk is bogus
 #[attr*]
index 4de817dbd9ca7823ba14719bf2d25bb4af2c6a49..94770aa875b4258b04cc336e54fdcf11ad688d8e 100644 (file)
@@ -12,6 +12,7 @@
 
 // ignore-test: this is an auxiliary file for circular-modules-main.rs
 
+#[path = "circular_modules_main.rs"]
 mod circular_modules_main;
 
 pub fn say_hello() {
index d2a16ac750704de8f3bf49cea7cc6aed7e6db5fb..d692bb519c149ec33c24269302f268505e24f507 100644 (file)
@@ -19,8 +19,8 @@
 
 use syntax::ast;
 use syntax::codemap;
-use syntax::parse;
 use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax_pos::DUMMY_SP;
 
 fn main() {
@@ -33,7 +33,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            format: syntax::codemap::MacroBang(parse::token::intern("")),
+            format: syntax::codemap::MacroBang(Symbol::intern("")),
             allow_internal_unstable: false,
             span: None,
         }
index ed127b017b6a92cdfe800aadd8a5e2e416942a28..0336fe277c51f8eb6f064d6e248d1f0d00e26653 100644 (file)
@@ -25,6 +25,7 @@
 use rustc_metadata::cstore::CStore;
 use rustc_errors::registry::Registry;
 
+use std::collections::HashSet;
 use std::path::PathBuf;
 use std::rc::Rc;
 
@@ -65,7 +66,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     let (sess, cstore) = basic_sess(sysroot);
-    let cfg = build_configuration(&sess, vec![]);
+    let cfg = build_configuration(&sess, HashSet::new());
     let control = CompileController::basic();
     let input = Input::Str { name: anon_src(), input: code };
     compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
diff --git a/src/test/run-make/issue-37893/Makefile b/src/test/run-make/issue-37893/Makefile
new file mode 100644 (file)
index 0000000..27b69ba
--- /dev/null
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) a.rs && $(RUSTC) b.rs && $(RUSTC) c.rs
diff --git a/src/test/run-make/issue-37893/a.rs b/src/test/run-make/issue-37893/a.rs
new file mode 100644 (file)
index 0000000..3dff453
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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"]
diff --git a/src/test/run-make/issue-37893/b.rs b/src/test/run-make/issue-37893/b.rs
new file mode 100644 (file)
index 0000000..82f48f6
--- /dev/null
@@ -0,0 +1,12 @@
+// 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;
diff --git a/src/test/run-make/issue-37893/c.rs b/src/test/run-make/issue-37893/c.rs
new file mode 100644 (file)
index 0000000..eee55cc
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
diff --git a/src/test/run-make/save-analysis-fail/Makefile b/src/test/run-make/save-analysis-fail/Makefile
new file mode 100644 (file)
index 0000000..f29f907
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+all: code
+krate2: krate2.rs
+       $(RUSTC) $<
+code: foo.rs krate2
+       $(RUSTC) foo.rs -Zsave-analysis || exit 0
diff --git a/src/test/run-make/save-analysis-fail/SameDir.rs b/src/test/run-make/save-analysis-fail/SameDir.rs
new file mode 100644 (file)
index 0000000..fe70ac1
--- /dev/null
@@ -0,0 +1,15 @@
+// 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
+}
diff --git a/src/test/run-make/save-analysis-fail/SameDir3.rs b/src/test/run-make/save-analysis-fail/SameDir3.rs
new file mode 100644 (file)
index 0000000..315f900
--- /dev/null
@@ -0,0 +1,13 @@
+// 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);
+}
diff --git a/src/test/run-make/save-analysis-fail/SubDir/mod.rs b/src/test/run-make/save-analysis-fail/SubDir/mod.rs
new file mode 100644 (file)
index 0000000..fe84db0
--- /dev/null
@@ -0,0 +1,37 @@
+// 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
+}
diff --git a/src/test/run-make/save-analysis-fail/foo.rs b/src/test/run-make/save-analysis-fail/foo.rs
new file mode 100644 (file)
index 0000000..e331f65
--- /dev/null
@@ -0,0 +1,450 @@
+// 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);
+}
diff --git a/src/test/run-make/save-analysis-fail/krate2.rs b/src/test/run-make/save-analysis-fail/krate2.rs
new file mode 100644 (file)
index 0000000..2c6f517
--- /dev/null
@@ -0,0 +1,18 @@
+// 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");
+}
index 48919fe876a221cad38d87ba119f86eae212d934..664bb9da89a5765fa19fb4dd4a94f3f5930dcd06 100644 (file)
 
 use proc_macro_tokens::build::ident_eq;
 
+use syntax::ast::Ident;
 use syntax::ext::base::{ExtCtxt, MacResult};
 use syntax::ext::proc_macro_shim::build_block_emitter;
 use syntax::tokenstream::{TokenTree, TokenStream};
-use syntax::parse::token::str_to_ident;
 use syntax::codemap::Span;
 
 use rustc_plugin::Registry;
@@ -57,7 +57,7 @@ fn cond_rec(input: TokenStream) -> TokenStream {
   let test: TokenStream = clause.slice(0..1);
   let rhs: TokenStream = clause.slice_from(1..);
 
-  if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+  if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() {
     qquote!({unquote(rhs)})
   } else {
     qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
index 0ea4cec75cdda5ae6b726e59c7f4142664089921..31a5f5968bab6addf652bb73bf1a9fb834826497 100644 (file)
@@ -26,7 +26,7 @@
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::ext::proc_macro_shim::build_block_emitter;
 use syntax::ext::base::{ExtCtxt, MacResult};
-use syntax::parse::token::{self, Token, DelimToken, keywords, str_to_ident};
+use syntax::parse::token::{self, Token, DelimToken};
 use syntax::tokenstream::{TokenTree, TokenStream};
 
 #[plugin_registrar]
@@ -58,7 +58,7 @@ fn cond_rec(input: TokenStream) -> TokenStream {
   let test: TokenStream = clause.slice(0..1);
   let rhs: TokenStream = clause.slice_from(1..);
 
-  if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+  if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() {
     qquote!({unquote(rhs)})
   } else {
     qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
index 169c96b438529166ebbdee1f3eef6d9e0dc800a9..6a2d159a4bdd96e774025f72df238e7ddac836ae 100644 (file)
@@ -52,7 +52,7 @@ fn cond_rec(input: TokenStream) -> TokenStream {
   let test: TokenStream = clause.slice(0..1);
   let rhs: TokenStream = clause.slice_from(1..);
 
-  if ident_eq(&test[0], str_to_ident("else")) || rest.is_empty() {
+  if ident_eq(&test[0], Ident::from_str("else")) || rest.is_empty() {
     qquote!({unquote(rhs)})
   } else {
     qquote!({if unquote(test) { unquote(rhs) } else { cond!(unquote(rest)) } })
index e750d1fb1e3e6364dba8cf64655988c0a5a4bec5..63dbd4d5bed047a7ffe0039210a0e49c5ffe2f1d 100644 (file)
@@ -10,7 +10,7 @@
 
 // force-host
 
-#![feature(plugin_registrar, rustc_private, item_like_imports)]
+#![feature(plugin_registrar, rustc_private)]
 
 extern crate syntax;
 extern crate syntax_ext;
 use syntax::codemap::Span;
 use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token::{intern, InternedString};
+use syntax::symbol::Symbol;
 use syntax::ptr::P;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_syntax_extension(intern("derive_CustomPartialEq"),
+    reg.register_syntax_extension(Symbol::intern("derive_CustomPartialEq"),
                                   MultiDecorator(Box::new(expand_deriving_partial_eq)));
 }
 
@@ -52,7 +52,7 @@ fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
                 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",
index 6b688b006bd4a675c8478cb5c64b3bcc0be103f2..07f7d6bad7bf2b40967b8830f4bdc380dafcd0cc 100644 (file)
@@ -23,7 +23,7 @@
 use syntax::ast;
 use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax_ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
 use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
 use syntax_pos::Span;
@@ -32,7 +32,7 @@
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_syntax_extension(
-        token::intern("derive_TotalSum"),
+        Symbol::intern("derive_TotalSum"),
         MultiDecorator(box expand));
 }
 
@@ -66,7 +66,7 @@ fn expand(cx: &mut ExtCtxt,
                             |cx, span, subexpr, field, _| {
                                 cx.expr_binary(span, ast::BinOpKind::Add, subexpr,
                                     cx.expr_method_call(span, field,
-                                        token::str_to_ident("total_sum"), vec![]))
+                                        ast::Ident::from_str("total_sum"), vec![]))
                             },
                             zero,
                             box |cx, span, _, _| { cx.span_bug(span, "wtf??"); },
index 6b58fee157584c5255bdeb452671d2a9a7046b23..50b16a0e26fb49b79a951e0b8d019a73e5012aa9 100644 (file)
@@ -23,7 +23,7 @@
 use syntax::ast;
 use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
 use syntax::ext::build::AstBuilder;
-use syntax::parse::token;
+use syntax::symbol::Symbol;
 use syntax::ptr::P;
 use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure};
 use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching};
@@ -34,7 +34,7 @@
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_syntax_extension(
-        token::intern("derive_TotalSum"),
+        Symbol::intern("derive_TotalSum"),
         MultiDecorator(box expand));
 }
 
index 8ea131da338cb1bd61f60fac56e32fe166a8beb6..8647797270f9a841f5092b974faf0ec745509cbb 100644 (file)
@@ -36,7 +36,7 @@ fn get_lints(&self) -> LintArray {
 
 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'");
         }
     }
index 7257444ee8703631675b40983b4c914483c23b67..29cc6b7db94741c4b44b1f0b5e66a65cea1a5b0a 100644 (file)
@@ -23,6 +23,7 @@
 use syntax::ext::quote::rt::ToTokens;
 use syntax::parse::{self, token};
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax::tokenstream::TokenTree;
 use syntax_pos::Span;
 use rustc_plugin::Registry;
@@ -36,15 +37,15 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_macro("make_a_1", expand_make_a_1);
     reg.register_macro("identity", expand_identity);
     reg.register_syntax_extension(
-        token::intern("into_multi_foo"),
+        Symbol::intern("into_multi_foo"),
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         MultiModifier(Box::new(expand_into_foo_multi)));
     reg.register_syntax_extension(
-        token::intern("duplicate"),
+        Symbol::intern("duplicate"),
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         MultiDecorator(Box::new(expand_duplicate)));
     reg.register_syntax_extension(
-        token::intern("caller"),
+        Symbol::intern("caller"),
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         MultiDecorator(Box::new(expand_caller)));
 }
@@ -108,9 +109,9 @@ fn expand_duplicate(cx: &mut ExtCtxt,
                     it: &Annotatable,
                     push: &mut FnMut(Annotatable)) {
     let copy_name = match mi.node {
-        ast::MetaItemKind::List(_, ref xs) => {
+        ast::MetaItemKind::List(ref xs) => {
             if let Some(word) = xs[0].word() {
-                token::str_to_ident(&word.name())
+                ast::Ident::with_empty_ctxt(word.name())
             } else {
                 cx.span_err(mi.span, "Expected word");
                 return;
@@ -179,7 +180,7 @@ fn expand_caller(cx: &mut ExtCtxt,
         }
 
         let fn_name = match list[0].name() {
-            Some(name) => token::str_to_ident(&name),
+            Some(name) => ast::Ident::with_empty_ctxt(name),
             None => cx.span_fatal(list[0].span(), "First parameter must be an ident.")
         };
 
index f21c914a76c9c7406bee608dda9d53a7f7a1b5ef..ba2af77cdb297f75c2cbc2e6e66c6ee08c4031d3 100644 (file)
@@ -22,9 +22,9 @@
 use syntax::ast;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager, NormalTT};
-use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::ptr::P;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use syntax::tokenstream;
 use rustc_plugin::Registry;
@@ -40,15 +40,14 @@ fn expand<'cx>(&self,
                    _: &[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));
 }
index 9fce19f46f65c7a4bdfafa445ca69a40289f6ca3..f97fb04aadf6ab2149c47be89aaaa677d9e54f0a 100644 (file)
 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)));
 }
 
index 6ac0d5ad1a3bc89e9f145548c16511f60afbebbb..2b3857048f36732acc33f5c524aa8cd6f7fa978c 100644 (file)
@@ -18,8 +18,8 @@
 extern crate rustc;
 extern crate rustc_plugin;
 
-use syntax::parse::token::{str_to_ident, NtExpr, NtPat};
-use syntax::ast::{Pat};
+use syntax::parse::token::{NtExpr, NtPat};
+use syntax::ast::{Ident, Pat};
 use syntax::tokenstream::{TokenTree};
 use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
 use syntax::ext::build::AstBuilder;
@@ -44,12 +44,12 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree])
         }
     };
 
-    let matched_nt = match *map[&str_to_ident("matched")] {
+    let matched_nt = match *map[&Ident::from_str("matched")] {
         MatchedNonterminal(ref nt) => nt.clone(),
         _ => unreachable!(),
     };
 
-    let mac_expr = match (&*matched_nt, &*map[&str_to_ident("pat")]) {
+    let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) {
         (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => {
             let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt| {
                 match **pat_nt {
index 914da3f746773fe69d731c8ee2e24de1c426f960..948b20c14771fa48aaf5c60d9e09366daaf75263 100644 (file)
@@ -18,9 +18,6 @@
 use proc_macro_tokens::prelude::*;
 
 extern crate syntax;
-use syntax::ast::Ident;
-use syntax::codemap::DUMMY_SP;
-use syntax::parse::token::{self, Token, keywords, str_to_ident};
 
 fn main() {
     let lex_true = lex("true");
diff --git a/src/test/run-pass-fulldeps/myriad-closures.rs b/src/test/run-pass-fulldeps/myriad-closures.rs
new file mode 100644 (file)
index 0000000..a946ec6
--- /dev/null
@@ -0,0 +1,48 @@
+// 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);
+}
index 7c0c24163fe617a7486fe21cee25ff1206d171b0..b4ed57192ccf69647015b18639b858c7d7d574df 100644 (file)
@@ -16,7 +16,7 @@
 extern crate syntax_pos;
 
 use syntax::print::pprust::*;
-use syntax::parse::token::intern;
+use syntax::symbol::Symbol;
 use syntax_pos::DUMMY_SP;
 
 fn main() {
@@ -29,7 +29,7 @@ fn main() {
     cx.bt_push(syntax::codemap::ExpnInfo {
         call_site: DUMMY_SP,
         callee: syntax::codemap::NameAndSpan {
-            format: syntax::codemap::MacroBang(intern("")),
+            format: syntax::codemap::MacroBang(Symbol::intern("")),
             allow_internal_unstable: false,
             span: None,
         }
@@ -97,7 +97,7 @@ macro_rules! check {
     // quote_meta_item!
 
     let meta = quote_meta_item!(cx, cfg(foo = "bar"));
-    check!(meta_item_to_string, meta, *quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#);
+    check!(meta_item_to_string, meta, quote_meta_item!(cx, $meta); r#"cfg(foo = "bar")"#);
 
     let attr = quote_attr!(cx, #![$meta]);
     check!(attribute_to_string, attr; r#"#![cfg(foo = "bar")]"#);
diff --git a/src/test/run-pass/auxiliary/rmeta_rlib.rs b/src/test/run-pass/auxiliary/rmeta_rlib.rs
new file mode 100644 (file)
index 0000000..28c1131
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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,
+}
diff --git a/src/test/run-pass/auxiliary/rmeta_rmeta.rs b/src/test/run-pass/auxiliary/rmeta_rmeta.rs
new file mode 100644 (file)
index 0000000..394845b
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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,
+}
index 195b99c9788e893ccdf0ca67649df55ce3c6650b..f845a2ee571622b699ce35054b0480f63d14177d 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(item_like_imports)]
 #![allow(unused)]
 
 // Like other items, private imports can be imported and used non-lexically in paths.
diff --git a/src/test/run-pass/issue-23699.rs b/src/test/run-pass/issue-23699.rs
new file mode 100644 (file)
index 0000000..1909be4
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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);
+}
+
diff --git a/src/test/run-pass/loop-break-value.rs b/src/test/run-pass/loop-break-value.rs
new file mode 100644 (file)
index 0000000..6a5e051
--- /dev/null
@@ -0,0 +1,133 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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);
+}
diff --git a/src/test/run-pass/myriad-closures.rs b/src/test/run-pass/myriad-closures.rs
deleted file mode 100644 (file)
index d2c9a5d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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);
-}
diff --git a/src/test/run-pass/rmeta.rs b/src/test/run-pass/rmeta.rs
new file mode 100644 (file)
index 0000000..11684d8
--- /dev/null
@@ -0,0 +1,22 @@
+// 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 };
+}
diff --git a/src/test/ui/print_type_sizes/anonymous.rs b/src/test/ui/print_type_sizes/anonymous.rs
new file mode 100644 (file)
index 0000000..dc93bdd
--- /dev/null
@@ -0,0 +1,27 @@
+// 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 { } }
+}
diff --git a/src/test/ui/print_type_sizes/generics.rs b/src/test/ui/print_type_sizes/generics.rs
new file mode 100644 (file)
index 0000000..93bcd1c
--- /dev/null
@@ -0,0 +1,73 @@
+// 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());
+}
diff --git a/src/test/ui/print_type_sizes/generics.stdout b/src/test/ui/print_type_sizes/generics.stdout
new file mode 100644 (file)
index 0000000..0f02f39
--- /dev/null
@@ -0,0 +1,14 @@
+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
diff --git a/src/test/ui/print_type_sizes/multiple_types.rs b/src/test/ui/print_type_sizes/multiple_types.rs
new file mode 100644 (file)
index 0000000..2b50107
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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;
+}
diff --git a/src/test/ui/print_type_sizes/multiple_types.stdout b/src/test/ui/print_type_sizes/multiple_types.stdout
new file mode 100644 (file)
index 0000000..eed9af2
--- /dev/null
@@ -0,0 +1,10 @@
+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
diff --git a/src/test/ui/print_type_sizes/no_duplicates.rs b/src/test/ui/print_type_sizes/no_duplicates.rs
new file mode 100644 (file)
index 0000000..6008a34
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <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]);
+}
diff --git a/src/test/ui/print_type_sizes/no_duplicates.stdout b/src/test/ui/print_type_sizes/no_duplicates.stdout
new file mode 100644 (file)
index 0000000..50180f3
--- /dev/null
@@ -0,0 +1,2 @@
+print-type-size type: `SevenBytes`: 7 bytes, alignment: 1 bytes
+print-type-size     field `.0`: 7 bytes
diff --git a/src/test/ui/print_type_sizes/nullable.rs b/src/test/ui/print_type_sizes/nullable.rs
new file mode 100644 (file)
index 0000000..f7fdcac
--- /dev/null
@@ -0,0 +1,69 @@
+// 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();
+}
diff --git a/src/test/ui/print_type_sizes/nullable.stdout b/src/test/ui/print_type_sizes/nullable.stdout
new file mode 100644 (file)
index 0000000..dd999c4
--- /dev/null
@@ -0,0 +1,27 @@
+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
diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs
new file mode 100644 (file)
index 0000000..cd7ef86
--- /dev/null
@@ -0,0 +1,49 @@
+// 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();
+}
diff --git a/src/test/ui/print_type_sizes/packed.stdout b/src/test/ui/print_type_sizes/packed.stdout
new file mode 100644 (file)
index 0000000..1278a7d
--- /dev/null
@@ -0,0 +1,17 @@
+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
diff --git a/src/test/ui/print_type_sizes/padding.rs b/src/test/ui/print_type_sizes/padding.rs
new file mode 100644 (file)
index 0000000..af34a90
--- /dev/null
@@ -0,0 +1,39 @@
+// 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() { }
diff --git a/src/test/ui/print_type_sizes/padding.stdout b/src/test/ui/print_type_sizes/padding.stdout
new file mode 100644 (file)
index 0000000..bb95f79
--- /dev/null
@@ -0,0 +1,21 @@
+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
diff --git a/src/test/ui/print_type_sizes/variants.rs b/src/test/ui/print_type_sizes/variants.rs
new file mode 100644 (file)
index 0000000..875edb4
--- /dev/null
@@ -0,0 +1,31 @@
+// 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;
+}
diff --git a/src/test/ui/print_type_sizes/variants.stdout b/src/test/ui/print_type_sizes/variants.stdout
new file mode 100644 (file)
index 0000000..eed9af2
--- /dev/null
@@ -0,0 +1,10 @@
+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