]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #35558 - lukehinds:master, r=nikomatsakis
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Sun, 14 Aug 2016 17:29:49 +0000 (20:29 +0300)
committerGitHub <noreply@github.com>
Sun, 14 Aug 2016 17:29:49 +0000 (20:29 +0300)
Update error message for E0253 #35512

Fixes #35512. Part of #35233.

345 files changed:
.gitignore
man/rustc.1
mk/rustllvm.mk
src/bootstrap/compile.rs
src/bootstrap/lib.rs
src/doc/book/crates-and-modules.md
src/doc/book/patterns.md
src/doc/reference.md
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/vec.rs
src/libcore/cell.rs
src/libcore/macros.rs
src/libcore/result.rs
src/librustc/dep_graph/README.md
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/dep_tracking_map.rs
src/librustc/dep_graph/visit.rs
src/librustc/diagnostics.rs
src/librustc/hir/fold.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/infer/freshen.rs
src/librustc/infer/mod.rs
src/librustc/lint/builtin.rs
src/librustc/middle/cstore.rs
src/librustc/middle/effect.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/mir/mir_map.rs
src/librustc/mir/repr.rs
src/librustc/mir/tcx.rs
src/librustc/mir/transform.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/contents.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/item_path.rs
src/librustc/ty/ivar.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_back/target/mod.rs
src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
src/librustc_borrowck/borrowck/mir/gather_moves.rs
src/librustc_borrowck/borrowck/mir/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/graph/mod.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_errors/snippet.rs
src/librustc_incremental/assert_dep_graph.rs
src/librustc_incremental/calculate_svh.rs [deleted file]
src/librustc_incremental/calculate_svh/mod.rs [new file with mode: 0644]
src/librustc_incremental/calculate_svh/svh_visitor.rs [new file with mode: 0644]
src/librustc_incremental/persist/data.rs
src/librustc_incremental/persist/directory.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/hash.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/mod.rs
src/librustc_incremental/persist/preds.rs [new file with mode: 0644]
src/librustc_incremental/persist/save.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_llvm/build.rs
src/librustc_llvm/ffi.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/def_key.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tyencode.rs
src/librustc_mir/graphviz.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/mir_map.rs
src/librustc_mir/pretty.rs
src/librustc_mir/transform/deaggregator.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/consts.rs
src/librustc_passes/rvalues.rs
src/librustc_privacy/diagnostics.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_trans/_match.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/back/write.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/type_names.rs
src/librustc_trans/glue.rs
src/librustc_trans/meth.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/mir/statement.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/format.rs
src/librustdoc/test.rs
src/libstd/collections/hash/map.rs
src/libstd/env.rs
src/libstd/ffi/c_str.rs
src/libstd/lib.rs
src/libstd/panic.rs
src/libstd/panicking.rs
src/libstd/rt.rs
src/libstd/sys/unix/ext/net.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/tokenstream.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/llvm
src/rustllvm/PassWrapper.cpp
src/rustllvm/llvm-auto-clean-trigger
src/test/codegen-units/partitioning/vtable-through-const.rs [new file with mode: 0644]
src/test/compile-fail/E0007.rs
src/test/compile-fail/E0008.rs
src/test/compile-fail/E0017.rs
src/test/compile-fail/E0023.rs
src/test/compile-fail/E0026.rs
src/test/compile-fail/E0038.rs
src/test/compile-fail/E0045.rs
src/test/compile-fail/E0071.rs
src/test/compile-fail/E0072.rs
src/test/compile-fail/E0081.rs
src/test/compile-fail/E0087.rs
src/test/compile-fail/E0091.rs
src/test/compile-fail/E0092.rs
src/test/compile-fail/E0128.rs
src/test/compile-fail/E0130.rs
src/test/compile-fail/E0133.rs
src/test/compile-fail/E0162.rs
src/test/compile-fail/E0191.rs
src/test/compile-fail/E0205.rs
src/test/compile-fail/E0214.rs
src/test/compile-fail/E0248.rs
src/test/compile-fail/E0263.rs
src/test/compile-fail/E0365.rs [new file with mode: 0644]
src/test/compile-fail/E0370.rs [new file with mode: 0644]
src/test/compile-fail/E0374.rs [new file with mode: 0644]
src/test/compile-fail/E0375.rs [new file with mode: 0644]
src/test/compile-fail/E0376.rs [new file with mode: 0644]
src/test/compile-fail/E0388.rs [new file with mode: 0644]
src/test/compile-fail/E0389.rs [new file with mode: 0644]
src/test/compile-fail/E0390.rs [new file with mode: 0644]
src/test/compile-fail/E0392.rs [new file with mode: 0644]
src/test/compile-fail/E0393.rs [new file with mode: 0644]
src/test/compile-fail/asm-out-assign-imm.rs
src/test/compile-fail/assign-imm-local-twice.rs
src/test/compile-fail/associated-const-impl-wrong-type.rs
src/test/compile-fail/associated-type-projection-from-multiple-supertraits.rs
src/test/compile-fail/auxiliary/empty-struct.rs
src/test/compile-fail/derived-errors/issue-31997-1.rs
src/test/compile-fail/empty-struct-braces-pat-2.rs
src/test/compile-fail/empty-struct-braces-pat-3.rs
src/test/compile-fail/empty-struct-tuple-pat.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-unit-pat-1.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-unit-pat-2.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-unit-pat.rs [deleted file]
src/test/compile-fail/feature-gate-relaxed-adts-2.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-relaxed-adts.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/auto-trait-leak.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/disallowed-2.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/disallowed.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/equality.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/feature-gate.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/lifetimes.rs [new file with mode: 0644]
src/test/compile-fail/impl-trait/loan-extend.rs [new file with mode: 0644]
src/test/compile-fail/issue-12560-1.rs [deleted file]
src/test/compile-fail/issue-12560-2.rs [deleted file]
src/test/compile-fail/issue-15524.rs
src/test/compile-fail/issue-16819.rs
src/test/compile-fail/issue-17800.rs
src/test/compile-fail/issue-18183.rs
src/test/compile-fail/issue-20692.rs
src/test/compile-fail/issue-26056.rs
src/test/compile-fail/issue-27831.rs [deleted file]
src/test/compile-fail/issue-28514.rs [new file with mode: 0644]
src/test/compile-fail/issue-28776.rs
src/test/compile-fail/issue-30079.rs
src/test/compile-fail/issue-3008-2.rs
src/test/compile-fail/issue-32326.rs
src/test/compile-fail/issue-35450.rs [new file with mode: 0644]
src/test/compile-fail/issue-3779.rs
src/test/compile-fail/issue-4736.rs
src/test/compile-fail/liveness-assign-imm-local-in-loop.rs
src/test/compile-fail/liveness-assign-imm-local-in-op-eq.rs
src/test/compile-fail/liveness-assign-imm-local-with-init.rs
src/test/compile-fail/macro-tt-matchers.rs
src/test/compile-fail/no-patterns-in-args.rs
src/test/compile-fail/numeric-fields.rs [new file with mode: 0644]
src/test/compile-fail/object-safety-generics.rs
src/test/compile-fail/object-safety-mentions-Self.rs
src/test/compile-fail/object-safety-sized.rs
src/test/compile-fail/object-safety-supertrait-mentions-Self.rs
src/test/compile-fail/private-in-public-lint.rs
src/test/compile-fail/private-in-public-warn.rs
src/test/compile-fail/private-in-public.rs
src/test/compile-fail/private-variant-and-crate-reexport.rs
src/test/compile-fail/pub-struct-field-span-26083.rs [deleted file]
src/test/compile-fail/struct-no-fields-enumlike.rs [deleted file]
src/test/compile-fail/trait-safety-fn-body.rs
src/test/compile-fail/transmute-different-sizes.rs
src/test/compile-fail/type-recursive.rs
src/test/compile-fail/unsafe-const-fn.rs
src/test/incremental/callee_caller_cross_crate/b.rs
src/test/incremental/dirty_clean.rs
src/test/incremental/foreign.rs [new file with mode: 0644]
src/test/incremental/hello_world.rs
src/test/incremental/ich_method_call_trait_scope.rs [new file with mode: 0644]
src/test/incremental/ich_nested_items.rs [new file with mode: 0644]
src/test/incremental/ich_resolve_results.rs [new file with mode: 0644]
src/test/incremental/inlined_hir_34991/main.rs [new file with mode: 0644]
src/test/incremental/krate_reassign_34991/auxiliary/a.rs [new file with mode: 0644]
src/test/incremental/krate_reassign_34991/main.rs [new file with mode: 0644]
src/test/incremental/rlib_cross_crate/b.rs
src/test/incremental/spike.rs
src/test/incremental/string_constant.rs
src/test/incremental/struct_add_field.rs
src/test/incremental/struct_change_field_name.rs
src/test/incremental/struct_change_field_type.rs
src/test/incremental/struct_change_field_type_cross_crate/b.rs
src/test/incremental/struct_change_nothing.rs
src/test/incremental/struct_remove_field.rs
src/test/incremental/type_alias_cross_crate/b.rs
src/test/mir-opt/deaggregator_test_enum.rs [new file with mode: 0644]
src/test/run-make/error-found-staticlib-instead-crate/Makefile
src/test/run-make/many-crates-but-no-match/Makefile
src/test/run-make/missing-crate-dependency/Makefile
src/test/run-make/unicode-input/Makefile [deleted file]
src/test/run-make/unicode-input/multiple_files.rs [deleted file]
src/test/run-make/unicode-input/span_length.rs [deleted file]
src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
src/test/run-pass/auxiliary/empty-struct.rs
src/test/run-pass/empty-struct-braces-gate-1.rs [deleted file]
src/test/run-pass/empty-struct-braces-gate-2.rs [deleted file]
src/test/run-pass/empty-struct-braces.rs
src/test/run-pass/impl-trait/auto-trait-leak.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/equality.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/example-calendar.rs [new file with mode: 0644]
src/test/run-pass/impl-trait/example-st.rs [new file with mode: 0644]
src/test/run-pass/issue-22894.rs [new file with mode: 0644]
src/test/run-pass/issue-29053.rs [new file with mode: 0644]
src/test/run-pass/issue-31776.rs
src/test/run-pass/issue-33498.rs [new file with mode: 0644]
src/test/run-pass/numeric-fields.rs [new file with mode: 0644]
src/test/run-pass/transmute-specialization.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/issue-28927-1.rs
src/test/rustdoc/private-type-alias.rs [new file with mode: 0644]
src/test/ui/span/pub-struct-field.rs [new file with mode: 0644]
src/test/ui/span/pub-struct-field.stderr [new file with mode: 0644]
src/tools/cargotest/main.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/errors.rs
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/json.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/procsrv.rs
src/tools/compiletest/src/raise_fd_limit.rs
src/tools/compiletest/src/runtest.rs
src/tools/compiletest/src/uidiff.rs
src/tools/compiletest/src/util.rs

index 5e8c40d03fbeff96ea8c04fe9f9717056b285663..6de43f471d8860229cb72c236b260d9303de1553 100644 (file)
@@ -57,6 +57,7 @@ __pycache__/
 .project
 .settings/
 .valgrindrc
+.vscode/
 /*-*-*-*/
 /*-*-*/
 /Makefile
index edbc6cea0266499c582036320c4b954489dd328f..0eaf89a560fb84a1defe2357d3bbeff71c1845a0 100644 (file)
@@ -264,7 +264,8 @@ which link to the standard library.
 .TP
 \fBRUST_TEST_THREADS\fR
 The test framework Rust provides executes tests in parallel. This variable sets
-the maximum number of threads used for this purpose.
+the maximum number of threads used for this purpose. This setting is overridden
+by the --test-threads option.
 
 .TP
 \fBRUST_TEST_NOCAPTURE\fR
index b50dbd01ad0cc0071bcf20cf8b5ba366ca724dc2..2d63f69960f78a949b952d4fdf8e916c1559c398 100644 (file)
@@ -32,6 +32,11 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
                      $$(call CFG_CC_INCLUDE_$(1),$$(S)src/rustllvm/include)
 RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o)
 
+# Flag that we are building with Rust's llvm fork
+ifeq ($(CFG_LLVM_ROOT),)
+RUSTLLVM_CXXFLAGS_$(1) := -DLLVM_RUSTLLVM
+endif
+
 # Note that we appease `cl.exe` and its need for some sort of exception
 # handling flag with the `EHsc` argument here as well.
 ifeq ($$(findstring msvc,$(1)),msvc)
@@ -55,6 +60,7 @@ $(1)/rustllvm/%.o: $(S)src/rustllvm/%.cpp $$(MKFILE_DEPS) $$(LLVM_CONFIG_$(1))
        $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@,) \
                $$(subst  /,//,$$(LLVM_CXXFLAGS_$(1))) \
                $$(RUSTLLVM_COMPONENTS_$(1)) \
+               $$(RUSTLLVM_CXXFLAGS_$(1)) \
                $$(EXTRA_RUSTLLVM_CXXFLAGS_$(1)) \
                $$(RUSTLLVM_INCS_$(1)) \
                $$<
index 061192ebd1340b318aedbea2441339eebb4282fe..155848901cdb49c8919d1d77f9d0756f18328b4d 100644 (file)
@@ -198,6 +198,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
     if !build.unstable_features {
         cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
     }
+    // Flag that rust llvm is in use
+    if build.is_rust_llvm(target) {
+        cargo.env("LLVM_RUSTLLVM", "1");
+    }
     cargo.env("LLVM_CONFIG", build.llvm_config(target));
     if build.config.llvm_static_stdcpp {
         cargo.env("LLVM_STATIC_STDCPP",
index acb7e0fadd90a5049aeed4de71982625d2cc5a75..5d61abe5e086ad23c54c2d2e42a70ece43d30ff7 100644 (file)
@@ -727,6 +727,16 @@ fn llvm_out(&self, target: &str) -> PathBuf {
         self.out.join(target).join("llvm")
     }
 
+    /// Returns true if no custom `llvm-config` is set for the specified target.
+    ///
+    /// If no custom `llvm-config` was specified then Rust's llvm will be used.
+    fn is_rust_llvm(&self, target: &str) -> bool {
+        match self.config.target_config.get(target) {
+            Some(ref c) => c.llvm_config.is_none(),
+            None => true
+        }
+    }
+
     /// Returns the path to `llvm-config` for the specified target.
     ///
     /// If a custom `llvm-config` was specified for target then that's returned
index 67fe8ba2c11a48e0d5bde95d9a769caeef0a4541..fcb7e0bc7eacd9e2caff84ff60d71026264c9075 100644 (file)
@@ -22,6 +22,7 @@ As an example, let’s make a *phrases* crate, which will give us various phrase
 in different languages. To keep things simple, we’ll stick to ‘greetings’ and
 ‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as
 two languages for those phrases to be in. We’ll use this module layout:
+
 ```text
                                     +-----------+
                                 +---| greetings |
index a0245d4c7b163f724157366db677946dbdd1d8f3..910b13754767facc46acd73885ae9ba02ef73fd1 100644 (file)
@@ -109,14 +109,14 @@ struct Point {
     y: i32,
 }
 
-let origin = Point { x: 0, y: 0 };
+let point = Point { x: 2, y: 3 };
 
-match origin {
+match point {
     Point { x, .. } => println!("x is {}", x),
 }
 ```
 
-This prints `x is 0`.
+This prints `x is 2`.
 
 You can do this kind of match on any member, not only the first:
 
@@ -126,14 +126,14 @@ struct Point {
     y: i32,
 }
 
-let origin = Point { x: 0, y: 0 };
+let point = Point { x: 2, y: 3 };
 
-match origin {
+match point {
     Point { y, .. } => println!("y is {}", y),
 }
 ```
 
-This prints `y is 0`.
+This prints `y is 3`.
 
 This ‘destructuring’ behavior works on any compound data type, like
 [tuples][tuples] or [enums][enums].
index f4ffe5774d27cd0f3dd121f42bb89255e0e11da6..f0ab1488d4015962f432ba4971aeb0b9bc2a2f79 100644 (file)
@@ -3039,7 +3039,7 @@ The precedence of Rust binary operators is ordered as follows, going from
 strong to weak:
 
 ```{.text .precedence}
-as
+as :
 * / %
 + -
 << >>
@@ -3050,6 +3050,7 @@ as
 &&
 ||
 .. ...
+<-
 =
 ```
 
index 70b514afd035f1d17d446c0dbbee6f158b1eb950..c06bde6222ac8410fe9ad6ebdd0c4464da9c2059 100644 (file)
@@ -1180,7 +1180,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
     #[inline]
     #[unstable(feature = "insert_str",
                reason = "recent addition",
-               issue = "0")]
+               issue = "35553")]
     pub fn insert_str(&mut self, idx: usize, string: &str) {
         let len = self.len();
         assert!(idx <= len);
index 8b4fce158de4645d60b1557bde684283d0d21509..a6f817a89624cfeb0c9e9cff55b3ed3c0f9227c9 100644 (file)
@@ -1446,13 +1446,12 @@ impl<T> IntoIterator for Vec<T> {
     #[inline]
     fn into_iter(mut self) -> IntoIter<T> {
         unsafe {
-            let ptr = self.as_mut_ptr();
-            assume(!ptr.is_null());
-            let begin = ptr as *const T;
+            let begin = self.as_mut_ptr();
+            assume(!begin.is_null());
             let end = if mem::size_of::<T>() == 0 {
-                arith_offset(ptr as *const i8, self.len() as isize) as *const T
+                arith_offset(begin as *const i8, self.len() as isize) as *const T
             } else {
-                ptr.offset(self.len() as isize) as *const T
+                begin.offset(self.len() as isize) as *const T
             };
             let buf = ptr::read(&self.buf);
             mem::forget(self);
@@ -1710,10 +1709,52 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
     _buf: RawVec<T>,
-    ptr: *const T,
+    ptr: *mut T,
     end: *const T,
 }
 
+impl<T> IntoIter<T> {
+    /// Returns the remaining items of this iterator as a slice.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(vec_into_iter_as_slice)]
+    /// let vec = vec!['a', 'b', 'c'];
+    /// let mut into_iter = vec.into_iter();
+    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    /// let _ = into_iter.next().unwrap();
+    /// assert_eq!(into_iter.as_slice(), &['b', 'c']);
+    /// ```
+    #[unstable(feature = "vec_into_iter_as_slice", issue = "35601")]
+    pub fn as_slice(&self) -> &[T] {
+        unsafe {
+            slice::from_raw_parts(self.ptr, self.len())
+        }
+    }
+
+    /// Returns the remaining items of this iterator as a mutable slice.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # #![feature(vec_into_iter_as_slice)]
+    /// let vec = vec!['a', 'b', 'c'];
+    /// let mut into_iter = vec.into_iter();
+    /// assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    /// into_iter.as_mut_slice()[2] = 'z';
+    /// assert_eq!(into_iter.next().unwrap(), 'a');
+    /// assert_eq!(into_iter.next().unwrap(), 'b');
+    /// assert_eq!(into_iter.next().unwrap(), 'z');
+    /// ```
+    #[unstable(feature = "vec_into_iter_as_slice", issue = "35601")]
+    pub fn as_mut_slice(&self) -> &mut [T] {
+        unsafe {
+            slice::from_raw_parts_mut(self.ptr, self.len())
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: Send> Send for IntoIter<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1726,14 +1767,14 @@ impl<T> Iterator for IntoIter<T> {
     #[inline]
     fn next(&mut self) -> Option<T> {
         unsafe {
-            if self.ptr == self.end {
+            if self.ptr as *const _ == self.end {
                 None
             } else {
                 if mem::size_of::<T>() == 0 {
                     // purposefully don't use 'ptr.offset' because for
                     // vectors with 0-size elements this would return the
                     // same pointer.
-                    self.ptr = arith_offset(self.ptr as *const i8, 1) as *const T;
+                    self.ptr = arith_offset(self.ptr as *const i8, 1) as *mut T;
 
                     // Use a non-null pointer value
                     Some(ptr::read(EMPTY as *mut T))
@@ -1776,7 +1817,7 @@ fn next_back(&mut self) -> Option<T> {
             } else {
                 if mem::size_of::<T>() == 0 {
                     // See above for why 'ptr.offset' isn't used
-                    self.end = arith_offset(self.end as *const i8, -1) as *const T;
+                    self.end = arith_offset(self.end as *const i8, -1) as *mut T;
 
                     // Use a non-null pointer value
                     Some(ptr::read(EMPTY as *mut T))
@@ -1796,9 +1837,7 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
 #[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
 impl<T: Clone> Clone for IntoIter<T> {
     fn clone(&self) -> IntoIter<T> {
-        unsafe {
-            slice::from_raw_parts(self.ptr, self.len()).to_owned().into_iter()
-        }
+        self.as_slice().to_owned().into_iter()
     }
 }
 
index 8ae63808f27404b9abdc4406b6eab7ef40b251f6..ab3231b2b9955e693540cd5f111a5961b934c632 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(vec_deque_contains)]
+#![feature(vec_into_iter_as_slice)]
 
 extern crate collections;
 extern crate test;
index 7a6bd958a5f8c7cb915c5756e055d1d25a65be78..9556174bd2294dadef86b45edaa6d220d87f2be9 100644 (file)
@@ -478,6 +478,29 @@ fn test_split_off() {
     assert_eq!(vec2, [5, 6]);
 }
 
+#[test]
+fn test_into_iter_as_slice() {
+    let vec = vec!['a', 'b', 'c'];
+    let mut into_iter = vec.into_iter();
+    assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    let _ = into_iter.next().unwrap();
+    assert_eq!(into_iter.as_slice(), &['b', 'c']);
+    let _ = into_iter.next().unwrap();
+    let _ = into_iter.next().unwrap();
+    assert_eq!(into_iter.as_slice(), &[]);
+}
+
+#[test]
+fn test_into_iter_as_mut_slice() {
+    let vec = vec!['a', 'b', 'c'];
+    let mut into_iter = vec.into_iter();
+    assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
+    into_iter.as_mut_slice()[0] = 'x';
+    into_iter.as_mut_slice()[1] = 'y';
+    assert_eq!(into_iter.next().unwrap(), 'x');
+    assert_eq!(into_iter.as_slice(), &['y', 'c']);
+}
+
 #[test]
 fn test_into_iter_count() {
     assert_eq!(vec![1, 2, 3].into_iter().count(), 3);
index 434084d3af8653f9888fb3f41cc75c1a19f5ffd2..17ec325e257b028f43ca709041f1769829309500 100644 (file)
 
 use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use convert::From;
 use default::Default;
 use fmt::{self, Debug, Display};
 use marker::{Copy, PhantomData, Send, Sync, Sized, Unsize};
@@ -329,6 +330,13 @@ fn cmp(&self, other: &Cell<T>) -> Ordering {
     }
 }
 
+#[stable(feature = "cell_from", since = "1.12.0")]
+impl<T: Copy> From<T> for Cell<T> {
+    fn from(t: T) -> Cell<T> {
+        Cell::new(t)
+    }
+}
+
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](index.html) for more.
@@ -742,6 +750,13 @@ fn cmp(&self, other: &RefCell<T>) -> Ordering {
     }
 }
 
+#[stable(feature = "cell_from", since = "1.12.0")]
+impl<T> From<T> for RefCell<T> {
+    fn from(t: T) -> RefCell<T> {
+        RefCell::new(t)
+    }
+}
+
 struct BorrowRef<'b> {
     borrow: &'b Cell<BorrowFlag>,
 }
@@ -1064,3 +1079,10 @@ fn default() -> UnsafeCell<T> {
         UnsafeCell::new(Default::default())
     }
 }
+
+#[stable(feature = "cell_from", since = "1.12.0")]
+impl<T> From<T> for UnsafeCell<T> {
+    fn from(t: T) -> UnsafeCell<T> {
+        UnsafeCell::new(t)
+    }
+}
index b0c79a3a88547b0551436df2d562bc4ea6d0c6d9..c916ad930ff105988b7be772c07b45a595f3aa25 100644 (file)
@@ -229,14 +229,28 @@ macro_rules! try {
     })
 }
 
-/// Use the `format!` syntax to write data into a buffer.
+/// Write formatted data into a buffer
 ///
-/// This macro is typically used with a buffer of `&mut `[`Write`][write].
+/// This macro accepts any value with `write_fmt` method as a writer, a format string, and a list
+/// of arguments to format.
+///
+/// `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write] or
+/// [`std::io::Write`][io_write] traits. These are sometimes called 'writers'.
+///
+/// Passed arguments will be formatted according to the specified format string and the resulting
+/// string will be passed to the writer.
 ///
 /// See [`std::fmt`][fmt] for more information on format syntax.
 ///
+/// Return value is completely dependent on the 'write_fmt' method.
+///
+/// Common return values are: [`Result`][enum_result], [`io::Result`][type_result]
+///
 /// [fmt]: ../std/fmt/index.html
-/// [write]: ../std/io/trait.Write.html
+/// [fmt_write]: ../std/fmt/trait.Write.html
+/// [io_write]: ../std/io/trait.Write.html
+/// [enum_result]: ../std/result/enum.Result.html
+/// [type_result]: ../std/io/type.Result.html
 ///
 /// # Examples
 ///
@@ -255,16 +269,31 @@ macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
 }
 
-/// Use the `format!` syntax to write data into a buffer, appending a newline.
-/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`)
-/// alone (no additional CARRIAGE RETURN (`\r`/`U+000D`).
+/// Write formatted data into a buffer, with appending a newline.
+///
+/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
+/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
 ///
-/// This macro is typically used with a buffer of `&mut `[`Write`][write].
+/// This macro accepts any value with `write_fmt` method as a writer, a format string, and a list
+/// of arguments to format.
+///
+/// `write_fmt` method usually comes from an implementation of [`std::fmt::Write`][fmt_write] or
+/// [`std::io::Write`][io_write] traits. These are sometimes called 'writers'.
+///
+/// Passed arguments will be formatted according to the specified format string and the resulting
+/// string will be passed to the writer.
 ///
 /// See [`std::fmt`][fmt] for more information on format syntax.
 ///
+/// Return value is completely dependent on the 'write_fmt' method.
+///
+/// Common return values are: [`Result`][enum_result], [`io::Result`][type_result]
+///
 /// [fmt]: ../std/fmt/index.html
-/// [write]: ../std/io/trait.Write.html
+/// [fmt_write]: ../std/fmt/trait.Write.html
+/// [io_write]: ../std/io/trait.Write.html
+/// [enum_result]: ../std/result/enum.Result.html
+/// [type_result]: ../std/io/type.Result.html
 ///
 /// # Examples
 ///
index 94c6c636ce8fce6469f374dbfdb730f60051ea3b..c7ca70fc1622d8ea2d811d5a81d2c54bd9104e5e 100644 (file)
@@ -402,8 +402,8 @@ pub fn as_ref(&self) -> Result<&T, &E> {
     /// ```
     /// fn mutate(r: &mut Result<i32, i32>) {
     ///     match r.as_mut() {
-    ///         Ok(&mut ref mut v) => *v = 42,
-    ///         Err(&mut ref mut e) => *e = 0,
+    ///         Ok(v) => *v = 42,
+    ///         Err(e) => *e = 0,
     ///     }
     /// }
     ///
index ece5819829baa67b05adbca4f30a3375dfeda7a7..f16a9b386bb8aeb3c985b6d227cc92a86fc45198 100644 (file)
@@ -134,6 +134,10 @@ to read from it. Similarly, reading from the `tcache` map for item `X`
 (which is a `DepTrackingMap`, described below) automatically invokes
 `dep_graph.read(ItemSignature(X))`.
 
+**Note:** adding `Hir` nodes requires a bit of caution due to the
+"inlining" that old trans and constant evaluation still use. See the
+section on inlining below.
+
 To make this strategy work, a certain amount of indirection is
 required. For example, modules in the HIR do not have direct pointers
 to the items that they contain. Rather, they contain node-ids -- one
@@ -387,3 +391,24 @@ RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckItemBody & bar'
 This will dump out all the nodes that lead from `Hir(foo)` to
 `TypeckItemBody(bar)`, from which you can (hopefully) see the source
 of the erroneous edge.
+
+### Inlining of HIR nodes
+
+For the time being, at least, we still sometimes "inline" HIR nodes
+from other crates into the current HIR map. This creates a weird
+scenario where the same logical item (let's call it `X`) has two
+def-ids: the original def-id `X` and a new, inlined one `X'`. `X'` is
+in the current crate, but it's not like other HIR nodes: in
+particular, when we restart compilation, it will not be available to
+hash. Therefore, we do not want `Hir(X')` nodes appearing in our
+graph.  Instead, we want a "read" of `Hir(X')` to be represented as a
+read of `MetaData(X)`, since the metadata for `X` is where the inlined
+representation originated in the first place.
+
+To achieve this, the HIR map will detect if the def-id originates in
+an inlined node and add a dependency to a suitable `MetaData` node
+instead. If you are reading a HIR node and are not sure if it may be
+inlined or not, you can use `tcx.map.read(node_id)` and it will detect
+whether the node is inlined or not and do the right thing.  You can
+also use `tcx.map.is_inlined_def_id()` and
+`tcx.map.is_inlined_node_id()` to test.
index c9247539990a9a8273508a2ea673a6ce6d65a0aa..40fd3dede3d08b5399312d8fc2fa82719c188d42 100644 (file)
@@ -20,7 +20,7 @@ macro_rules! try_opt {
     )
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum DepNode<D: Clone + Debug> {
     // The `D` type is "how definitions are identified".
     // During compilation, it is always `DefId`, but when serializing
@@ -82,9 +82,11 @@ pub enum DepNode<D: Clone + Debug> {
     Privacy,
     IntrinsicCheck(D),
     MatchCheck(D),
-    MirMapConstruction(D),
-    MirPass(D),
-    MirTypeck(D),
+
+    // Represents the MIR for a fn; also used as the task node for
+    // things read/modify that MIR.
+    Mir(D),
+
     BorrowCheck(D),
     RvalueCheck(D),
     Reachability,
@@ -148,6 +150,7 @@ macro_rules! check {
         check! {
             CollectItem,
             BorrowCheck,
+            Hir,
             TransCrateItem,
             TypeckItemType,
             TypeckItemBody,
@@ -214,9 +217,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             CheckConst(ref d) => op(d).map(CheckConst),
             IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
             MatchCheck(ref d) => op(d).map(MatchCheck),
-            MirMapConstruction(ref d) => op(d).map(MirMapConstruction),
-            MirPass(ref d) => op(d).map(MirPass),
-            MirTypeck(ref d) => op(d).map(MirTypeck),
+            Mir(ref d) => op(d).map(Mir),
             BorrowCheck(ref d) => op(d).map(BorrowCheck),
             RvalueCheck(ref d) => op(d).map(RvalueCheck),
             TransCrateItem(ref d) => op(d).map(TransCrateItem),
@@ -245,6 +246,6 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
 /// some independent path or string that persists between runs without
 /// the need to be mapped or unmapped. (This ensures we can serialize
 /// them even in the absence of a tcx.)
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct WorkProductId(pub String);
 
index 922d32a3067969f626a299f4a19d01ddbc83f69b..88cd1efd3459ac6f703ea35c57f45ac3a5e4d66d 100644 (file)
@@ -61,6 +61,12 @@ pub fn get(&self, k: &M::Key) -> Option<&M::Value> {
         self.map.get(k)
     }
 
+    pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> {
+        self.read(k);
+        self.write(k);
+        self.map.get_mut(k)
+    }
+
     pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option<M::Value> {
         self.write(&k);
         self.map.insert(k, v)
@@ -70,6 +76,10 @@ pub fn contains_key(&self, k: &M::Key) -> bool {
         self.read(k);
         self.map.contains_key(k)
     }
+
+    pub fn keys(&self) -> Vec<M::Key> {
+        self.map.keys().cloned().collect()
+    }
 }
 
 impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
index 5dd71db2f1832870b8e87171499b772c32acf02e..d085c24036cef88ec83b52e4772ff4a0fdebaecd 100644 (file)
@@ -41,6 +41,7 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
             let task_id = (self.dep_node_fn)(item_def_id);
             let _task = self.tcx.dep_graph.in_task(task_id.clone());
             debug!("Started task {:?}", task_id);
+            assert!(!self.tcx.map.is_inlined_def_id(item_def_id));
             self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
             self.visitor.visit_item(i);
             debug!("Ended task {:?}", task_id);
index 74e2c90503cd37fd66477a45e7f024eb485e2480..07e54dc9e8796e77f8ef9fed8ffb4e985ff995ba 100644 (file)
@@ -1399,6 +1399,38 @@ struct Foo<T: 'static> {
 ```
 "##,
 
+E0312: r##"
+A lifetime of reference outlives lifetime of borrowed content.
+
+Erroneous code example:
+
+```compile_fail,E0312
+fn make_child<'human, 'elve>(x: &mut &'human isize, y: &mut &'elve isize) {
+    *x = *y;
+    // error: lifetime of reference outlives lifetime of borrowed content
+}
+```
+
+The compiler cannot determine if the `human` lifetime will live long enough
+to keep up on the elve one. To solve this error, you have to give an
+explicit lifetime hierarchy:
+
+```
+fn make_child<'human, 'elve: 'human>(x: &mut &'human isize,
+                                     y: &mut &'elve isize) {
+    *x = *y; // ok!
+}
+```
+
+Or use the same lifetime for every variable:
+
+```
+fn make_child<'elve>(x: &mut &'elve isize, y: &mut &'elve isize) {
+    *x = *y; // ok!
+}
+```
+"##,
+
 E0398: r##"
 In Rust 1.3, the default object lifetime bounds are expected to change, as
 described in RFC #1156 [1]. You are getting a warning because the compiler
@@ -1674,7 +1706,6 @@ fn cookie() -> ! { // error: definition of an unknown language item: `cookie`
 //  E0304, // expected signed integer constant
 //  E0305, // expected constant
     E0311, // thing may not live long enough
-    E0312, // lifetime of reference outlives lifetime of borrowed content
     E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
index 5e0e6622185f8b50336cc4409b033a5be0f4793b..dd79e14f077e831c5949797dd4b62c4fc08c7bef 100644 (file)
@@ -375,6 +375,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                 TyPolyTraitRef(bounds) => {
                     TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
                 }
+                TyImplTrait(bounds) => {
+                    TyImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+                }
             },
             span: fld.new_span(span),
         }
index aded220c0cdfe6893c854a8c734a560606cd6bff..1162c290f9cfca675f63b14bb52fef53e050e59e 100644 (file)
@@ -427,6 +427,9 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyPolyTraitRef(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
+        TyImplTrait(ref bounds) => {
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+        }
         TyTypeof(ref expression) => {
             visitor.visit_expr(expression)
         }
index 9d124dadb766adb911324f8a5cdc78f1eed57e38..eb98ed77da703df241719e57999b9c37a460930d 100644 (file)
@@ -293,8 +293,10 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                     hir::TyTypeof(self.lower_expr(expr))
                 }
                 PolyTraitRef(ref bounds) => {
-                    let bounds = bounds.iter().map(|b| self.lower_ty_param_bound(b)).collect();
-                    hir::TyPolyTraitRef(bounds)
+                    hir::TyPolyTraitRef(self.lower_bounds(bounds))
+                }
+                ImplTrait(ref bounds) => {
+                    hir::TyImplTrait(self.lower_bounds(bounds))
                 }
                 Mac(_) => panic!("TyMac should have been expanded by now."),
             },
@@ -1854,7 +1856,7 @@ fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMod
 
         let parent_def = self.parent_def;
         let def = self.resolver.definitions().map(|defs| {
-            let def_path_data = DefPathData::Binding(name);
+            let def_path_data = DefPathData::Binding(name.as_str());
             let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data);
             Def::Local(DefId::local(def_index), pat.id)
         }).unwrap_or(Def::Err);
index b3f222b22e8915314c1b1d7883b00a22aa8ac935..b70190181af8fcf80123a70d575af4cc1bda43e9 100644 (file)
@@ -194,6 +194,14 @@ fn visit_stmt(&mut self, stmt: &'ast Stmt) {
         });
     }
 
+    fn visit_ty(&mut self, ty: &'ast Ty) {
+        self.insert(ty.id, NodeTy(ty));
+
+        self.with_parent(ty.id, |this| {
+            intravisit::walk_ty(this, ty);
+        });
+    }
+
     fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
                 b: &'ast Block, s: Span, id: NodeId) {
         assert_eq!(self.parent_node, id);
index 2b89695ab41cad2fdbb39f846547a314f1ece101..752b0e9a253dd9a7ee1cf41cd922c1f8467ce1c2 100644 (file)
@@ -135,11 +135,11 @@ fn visit_item(&mut self, i: &Item) {
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Trait(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name),
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name),
+                DefPathData::TypeNs(i.ident.name.as_str()),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name),
-            ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name),
+                DefPathData::ValueNs(i.ident.name.as_str()),
+            ItemKind::Mac(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Use(..) => DefPathData::Misc,
         };
         let def = self.create_def(i.id, def_data);
@@ -150,12 +150,12 @@ fn visit_item(&mut self, i: &Item) {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.name.name));
+                                            DefPathData::EnumVariant(v.node.name.name.as_str()));
                         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()));
-                                this.create_def(field.id, DefPathData::Field(name));
+                                this.create_def(field.id, DefPathData::Field(name.as_str()));
                             }
 
                             if let Some(ref expr) = v.node.disr_expr {
@@ -172,8 +172,8 @@ fn visit_item(&mut self, i: &Item) {
                     }
 
                     for (index, field) in struct_def.fields().iter().enumerate() {
-                        let name = field.ident.map(|ident| ident.name)
-                            .unwrap_or(token::intern(&index.to_string()));
+                        let name = field.ident.map(|ident| ident.name.as_str())
+                            .unwrap_or(token::intern(&index.to_string()).as_str());
                         this.create_def(field.id, DefPathData::Field(name));
                     }
                 }
@@ -184,7 +184,8 @@ fn visit_item(&mut self, i: &Item) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.ident.name));
+        let def = self.create_def(foreign_item.id,
+                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()));
 
         self.with_parent(def, |this| {
             visit::walk_foreign_item(this, foreign_item);
@@ -193,7 +194,7 @@ fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
 
     fn visit_generics(&mut self, generics: &Generics) {
         for ty_param in generics.ty_params.iter() {
-            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name));
+            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name.as_str()));
         }
 
         visit::walk_generics(self, generics);
@@ -202,9 +203,9 @@ fn visit_generics(&mut self, generics: &Generics) {
     fn visit_trait_item(&mut self, ti: &TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name),
-            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name),
-            TraitItemKind::Macro(..) => DefPathData::MacroDef(ti.ident.name),
+                DefPathData::ValueNs(ti.ident.name.as_str()),
+            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
+            TraitItemKind::Macro(..) => DefPathData::MacroDef(ti.ident.name.as_str()),
         };
 
         let def = self.create_def(ti.id, def_data);
@@ -220,9 +221,9 @@ fn visit_trait_item(&mut self, ti: &TraitItem) {
     fn visit_impl_item(&mut self, ii: &ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name),
-            ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name),
+                DefPathData::ValueNs(ii.ident.name.as_str()),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
+            ImplItemKind::Macro(..) => DefPathData::MacroDef(ii.ident.name.as_str()),
         };
 
         let def = self.create_def(ii.id, def_data);
@@ -239,7 +240,7 @@ fn visit_pat(&mut self, pat: &Pat) {
         let parent_def = self.parent_def;
 
         if let PatKind::Ident(_, id, _) = pat.node {
-            let def = self.create_def(pat.id, DefPathData::Binding(id.node.name));
+            let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str()));
             self.parent_def = Some(def);
         }
 
@@ -267,15 +268,18 @@ fn visit_ty(&mut self, ty: &Ty) {
         if let TyKind::FixedLengthVec(_, ref length) = ty.node {
             self.visit_ast_const_integer(length);
         }
+        if let TyKind::ImplTrait(..) = ty.node {
+            self.create_def(ty.id, DefPathData::ImplTrait);
+        }
         visit::walk_ty(self, ty);
     }
 
     fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
-        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
     }
 
     fn visit_macro_def(&mut self, macro_def: &MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name));
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str()));
     }
 }
 
@@ -301,9 +305,9 @@ fn visit_item(&mut self, i: &'ast hir::Item) {
             hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
             hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
             hir::ItemTy(..) =>
-                DefPathData::TypeNs(i.name),
+                DefPathData::TypeNs(i.name.as_str()),
             hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
-                DefPathData::ValueNs(i.name),
+                DefPathData::ValueNs(i.name.as_str()),
             hir::ItemUse(..) => DefPathData::Misc,
         };
         let def = self.create_def(i.id, def_data);
@@ -314,12 +318,12 @@ fn visit_item(&mut self, i: &'ast hir::Item) {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.name));
+                                            DefPathData::EnumVariant(v.node.name.as_str()));
 
                         this.with_parent(variant_def_index, |this| {
                             for field in v.node.data.fields() {
                                 this.create_def(field.id,
-                                                DefPathData::Field(field.name));
+                                                DefPathData::Field(field.name.as_str()));
                             }
                             if let Some(ref expr) = v.node.disr_expr {
                                 this.visit_hir_const_integer(expr);
@@ -335,7 +339,7 @@ fn visit_item(&mut self, i: &'ast hir::Item) {
                     }
 
                     for field in struct_def.fields() {
-                        this.create_def(field.id, DefPathData::Field(field.name));
+                        this.create_def(field.id, DefPathData::Field(field.name.as_str()));
                     }
                 }
                 _ => {}
@@ -345,7 +349,8 @@ fn visit_item(&mut self, i: &'ast hir::Item) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
-        let def = self.create_def(foreign_item.id, DefPathData::ValueNs(foreign_item.name));
+        let def = self.create_def(foreign_item.id,
+                                  DefPathData::ValueNs(foreign_item.name.as_str()));
 
         self.with_parent(def, |this| {
             intravisit::walk_foreign_item(this, foreign_item);
@@ -354,7 +359,7 @@ fn visit_foreign_item(&mut self, foreign_item: &'ast hir::ForeignItem) {
 
     fn visit_generics(&mut self, generics: &'ast hir::Generics) {
         for ty_param in generics.ty_params.iter() {
-            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name));
+            self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.name.as_str()));
         }
 
         intravisit::walk_generics(self, generics);
@@ -363,8 +368,8 @@ fn visit_generics(&mut self, generics: &'ast hir::Generics) {
     fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
         let def_data = match ti.node {
             hir::MethodTraitItem(..) | hir::ConstTraitItem(..) =>
-                DefPathData::ValueNs(ti.name),
-            hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name),
+                DefPathData::ValueNs(ti.name.as_str()),
+            hir::TypeTraitItem(..) => DefPathData::TypeNs(ti.name.as_str()),
         };
 
         let def = self.create_def(ti.id, def_data);
@@ -380,8 +385,8 @@ fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
     fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
         let def_data = match ii.node {
             hir::ImplItemKind::Method(..) | hir::ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.name),
-            hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name),
+                DefPathData::ValueNs(ii.name.as_str()),
+            hir::ImplItemKind::Type(..) => DefPathData::TypeNs(ii.name.as_str()),
         };
 
         let def = self.create_def(ii.id, def_data);
@@ -398,7 +403,7 @@ fn visit_pat(&mut self, pat: &'ast hir::Pat) {
         let parent_def = self.parent_def;
 
         if let hir::PatKind::Binding(_, name, _) = pat.node {
-            let def = self.create_def(pat.id, DefPathData::Binding(name.node));
+            let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
             self.parent_def = Some(def);
         }
 
@@ -426,14 +431,17 @@ fn visit_ty(&mut self, ty: &'ast hir::Ty) {
         if let hir::TyFixedLengthVec(_, ref length) = ty.node {
             self.visit_hir_const_integer(length);
         }
+        if let hir::TyImplTrait(..) = ty.node {
+            self.create_def(ty.id, DefPathData::ImplTrait);
+        }
         intravisit::walk_ty(self, ty);
     }
 
     fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
-        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
     }
 
     fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name.as_str()));
     }
 }
index 3317585f820aa60b30647c97d7b33c1561a7b784..901a489728eeca0aca5c4ff7d9e26b23985047af 100644 (file)
 use hir::def_id::{DefId, DefIndex};
 use hir::map::def_collector::DefCollector;
 use rustc_data_structures::fnv::FnvHashMap;
+use std::fmt::Write;
+use std::hash::{Hash, Hasher, SipHasher};
 use syntax::{ast, visit};
 use syntax::parse::token::InternedString;
+use ty::TyCtxt;
 use util::nodemap::NodeMap;
 
 /// The definition table containing node definitions
@@ -109,6 +112,40 @@ pub fn make<FN>(start_krate: ast::CrateNum,
         data.reverse();
         DefPath { data: data, krate: krate }
     }
+
+    pub fn to_string(&self, tcx: TyCtxt) -> String {
+        let mut s = String::with_capacity(self.data.len() * 16);
+
+        if self.krate == LOCAL_CRATE {
+            s.push_str(&tcx.crate_name(self.krate));
+        } else {
+            s.push_str(&tcx.sess.cstore.original_crate_name(self.krate));
+        }
+        s.push_str("/");
+        s.push_str(&tcx.crate_disambiguator(self.krate));
+
+        for component in &self.data {
+            write!(s,
+                   "::{}[{}]",
+                   component.data.as_interned_str(),
+                   component.disambiguator)
+                .unwrap();
+        }
+
+        s
+    }
+
+    pub fn deterministic_hash(&self, tcx: TyCtxt) -> u64 {
+        let mut state = SipHasher::new();
+        self.deterministic_hash_to(tcx, &mut state);
+        state.finish()
+    }
+
+    pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
+        tcx.crate_name(self.krate).hash(state);
+        tcx.crate_disambiguator(self.krate).hash(state);
+        self.data.hash(state);
+    }
 }
 
 /// Root of an inlined item. We track the `DefPath` of the item within
@@ -153,31 +190,33 @@ pub enum DefPathData {
     /// An impl
     Impl,
     /// Something in the type NS
-    TypeNs(ast::Name),
+    TypeNs(InternedString),
     /// Something in the value NS
-    ValueNs(ast::Name),
+    ValueNs(InternedString),
     /// A module declaration
-    Module(ast::Name),
+    Module(InternedString),
     /// A macro rule
-    MacroDef(ast::Name),
+    MacroDef(InternedString),
     /// A closure expression
     ClosureExpr,
 
     // Subportions of items
     /// A type parameter (generic parameter)
-    TypeParam(ast::Name),
+    TypeParam(InternedString),
     /// A lifetime definition
-    LifetimeDef(ast::Name),
+    LifetimeDef(InternedString),
     /// A variant of a enum
-    EnumVariant(ast::Name),
+    EnumVariant(InternedString),
     /// A struct field
-    Field(ast::Name),
+    Field(InternedString),
     /// Implicit ctor for a tuple-like struct
     StructCtor,
     /// Initializer for a const
     Initializer,
     /// Pattern binding
-    Binding(ast::Name),
+    Binding(InternedString),
+    /// An `impl Trait` type node.
+    ImplTrait
 }
 
 impl Definitions {
@@ -291,16 +330,16 @@ impl DefPathData {
     pub fn as_interned_str(&self) -> InternedString {
         use self::DefPathData::*;
         match *self {
-            TypeNs(name) |
-            ValueNs(name) |
-            Module(name) |
-            MacroDef(name) |
-            TypeParam(name) |
-            LifetimeDef(name) |
-            EnumVariant(name) |
-            Binding(name) |
-            Field(name) => {
-                name.as_str()
+            TypeNs(ref name) |
+            ValueNs(ref name) |
+            Module(ref name) |
+            MacroDef(ref name) |
+            TypeParam(ref name) |
+            LifetimeDef(ref name) |
+            EnumVariant(ref name) |
+            Binding(ref name) |
+            Field(ref name) => {
+                name.clone()
             }
 
             Impl => {
@@ -332,6 +371,10 @@ pub fn as_interned_str(&self) -> InternedString {
             Initializer => {
                 InternedString::new("{{initializer}}")
             }
+
+            ImplTrait => {
+                InternedString::new("{{impl-Trait}}")
+            }
         }
     }
 
index aed3613f44ed489328e3df2f1a6ae1013fafd684..7e82a4a05a76461216731761e4ed6b1c9b33284e 100644 (file)
@@ -50,6 +50,7 @@ pub enum Node<'ast> {
     NodeVariant(&'ast Variant),
     NodeExpr(&'ast Expr),
     NodeStmt(&'ast Stmt),
+    NodeTy(&'ast Ty),
     NodeLocal(&'ast Pat),
     NodePat(&'ast Pat),
     NodeBlock(&'ast Block),
@@ -76,6 +77,7 @@ pub enum MapEntry<'ast> {
     EntryVariant(NodeId, &'ast Variant),
     EntryExpr(NodeId, &'ast Expr),
     EntryStmt(NodeId, &'ast Stmt),
+    EntryTy(NodeId, &'ast Ty),
     EntryLocal(NodeId, &'ast Pat),
     EntryPat(NodeId, &'ast Pat),
     EntryBlock(NodeId, &'ast Block),
@@ -104,6 +106,7 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
             NodeVariant(n) => EntryVariant(p, n),
             NodeExpr(n) => EntryExpr(p, n),
             NodeStmt(n) => EntryStmt(p, n),
+            NodeTy(n) => EntryTy(p, n),
             NodeLocal(n) => EntryLocal(p, n),
             NodePat(n) => EntryPat(p, n),
             NodeBlock(n) => EntryBlock(p, n),
@@ -122,6 +125,7 @@ fn parent_node(self) -> Option<NodeId> {
             EntryVariant(id, _) => id,
             EntryExpr(id, _) => id,
             EntryStmt(id, _) => id,
+            EntryTy(id, _) => id,
             EntryLocal(id, _) => id,
             EntryPat(id, _) => id,
             EntryBlock(id, _) => id,
@@ -144,6 +148,7 @@ fn to_node(self) -> Option<Node<'ast>> {
             EntryVariant(_, n) => NodeVariant(n),
             EntryExpr(_, n) => NodeExpr(n),
             EntryStmt(_, n) => NodeStmt(n),
+            EntryTy(_, n) => NodeTy(n),
             EntryLocal(_, n) => NodeLocal(n),
             EntryPat(_, n) => NodePat(n),
             EntryBlock(_, n) => NodeBlock(n),
@@ -204,9 +209,21 @@ pub struct Map<'ast> {
     /// All NodeIds that are numerically greater or equal to this value come
     /// from inlined items.
     local_node_id_watermark: NodeId,
+
+    /// All def-indices that are numerically greater or equal to this value come
+    /// from inlined items.
+    local_def_id_watermark: usize,
 }
 
 impl<'ast> Map<'ast> {
+    pub fn is_inlined_def_id(&self, id: DefId) -> bool {
+        id.is_local() && id.index.as_usize() >= self.local_def_id_watermark
+    }
+
+    pub fn is_inlined_node_id(&self, id: NodeId) -> bool {
+        id >= self.local_node_id_watermark
+    }
+
     /// Registers a read in the dependency graph of the AST node with
     /// the given `id`. This needs to be called each time a public
     /// function returns the HIR for a node -- in other words, when it
@@ -214,60 +231,101 @@ impl<'ast> Map<'ast> {
     /// otherwise have had access to those contents, and hence needs a
     /// read recorded). If the function just returns a DefId or
     /// NodeId, no actual content was returned, so no read is needed.
-    fn read(&self, id: NodeId) {
+    pub fn read(&self, id: NodeId) {
         self.dep_graph.read(self.dep_node(id));
     }
 
     fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
         let map = self.map.borrow();
         let mut id = id0;
-        loop {
-            match map[id as usize] {
-                EntryItem(_, item) => {
-                    let def_id = self.local_def_id(item.id);
-                    // NB                          ^~~~~~~
-                    //
-                    // You would expect that `item.id == id`, but this
-                    // is not always the case. In particular, for a
-                    // ViewPath item like `use self::{mem, foo}`, we
-                    // map the ids for `mem` and `foo` to the
-                    // enclosing view path item. This seems mega super
-                    // ultra wrong, but then who am I to judge?
-                    // -nmatsakis
-                    return DepNode::Hir(def_id);
-                }
+        if !self.is_inlined_node_id(id) {
+            loop {
+                match map[id as usize] {
+                    EntryItem(_, item) => {
+                        let def_id = self.local_def_id(item.id);
+                        // NB                          ^~~~~~~
+                        //
+                        // You would expect that `item.id == id`, but this
+                        // is not always the case. In particular, for a
+                        // ViewPath item like `use self::{mem, foo}`, we
+                        // map the ids for `mem` and `foo` to the
+                        // enclosing view path item. This seems mega super
+                        // ultra wrong, but then who am I to judge?
+                        // -nmatsakis
+                        assert!(!self.is_inlined_def_id(def_id));
+                        return DepNode::Hir(def_id);
+                    }
 
-                EntryForeignItem(p, _) |
-                EntryTraitItem(p, _) |
-                EntryImplItem(p, _) |
-                EntryVariant(p, _) |
-                EntryExpr(p, _) |
-                EntryStmt(p, _) |
-                EntryLocal(p, _) |
-                EntryPat(p, _) |
-                EntryBlock(p, _) |
-                EntryStructCtor(p, _) |
-                EntryLifetime(p, _) |
-                EntryTyParam(p, _) =>
-                    id = p,
-
-                RootCrate |
-                RootInlinedParent(_) =>
-                    // FIXME(#32015) clarify story about cross-crate dep tracking
-                    return DepNode::Krate,
-
-                NotPresent =>
-                    // Some nodes, notably struct fields, are not
-                    // present in the map for whatever reason, but
-                    // they *do* have def-ids. So if we encounter an
-                    // empty hole, check for that case.
-                    return self.opt_local_def_id(id)
-                               .map(|def_id| DepNode::Hir(def_id))
-                               .unwrap_or_else(|| {
-                                   bug!("Walking parents from `{}` \
-                                         led to `NotPresent` at `{}`",
-                                        id0, id)
-                               }),
+                    EntryForeignItem(p, _) |
+                    EntryTraitItem(p, _) |
+                    EntryImplItem(p, _) |
+                    EntryVariant(p, _) |
+                    EntryExpr(p, _) |
+                    EntryStmt(p, _) |
+                EntryTy(p, _) |
+                    EntryLocal(p, _) |
+                    EntryPat(p, _) |
+                    EntryBlock(p, _) |
+                    EntryStructCtor(p, _) |
+                    EntryLifetime(p, _) |
+                    EntryTyParam(p, _) =>
+                        id = p,
+
+                    RootCrate =>
+                        return DepNode::Krate,
+
+                    RootInlinedParent(_) =>
+                        bug!("node {} has inlined ancestor but is not inlined", id0),
+
+                    NotPresent =>
+                        // Some nodes, notably struct fields, are not
+                        // present in the map for whatever reason, but
+                        // they *do* have def-ids. So if we encounter an
+                        // empty hole, check for that case.
+                        return self.opt_local_def_id(id)
+                                   .map(|def_id| DepNode::Hir(def_id))
+                                   .unwrap_or_else(|| {
+                                       bug!("Walking parents from `{}` \
+                                             led to `NotPresent` at `{}`",
+                                            id0, id)
+                                   }),
+                }
+            }
+        } else {
+            // reading from an inlined def-id is really a read out of
+            // the metadata from which we loaded the item.
+            loop {
+                match map[id as usize] {
+                    EntryItem(p, _) |
+                    EntryForeignItem(p, _) |
+                    EntryTraitItem(p, _) |
+                    EntryImplItem(p, _) |
+                    EntryVariant(p, _) |
+                    EntryExpr(p, _) |
+                    EntryStmt(p, _) |
+                    EntryTy(p, _) |
+                    EntryLocal(p, _) |
+                    EntryPat(p, _) |
+                    EntryBlock(p, _) |
+                    EntryStructCtor(p, _) |
+                    EntryLifetime(p, _) |
+                    EntryTyParam(p, _) =>
+                        id = p,
+
+                    RootInlinedParent(parent) => match *parent {
+                        InlinedItem::Item(def_id, _) |
+                        InlinedItem::TraitItem(def_id, _) |
+                        InlinedItem::ImplItem(def_id, _) |
+                        InlinedItem::Foreign(def_id, _) =>
+                            return DepNode::MetaData(def_id)
+                    },
+
+                    RootCrate =>
+                        bug!("node {} has crate ancestor but is inlined", id0),
+
+                    NotPresent =>
+                        bug!("node {} is inlined but not present in map", id0),
+                }
             }
         }
     }
@@ -629,6 +687,7 @@ pub fn opt_span(&self, id: NodeId) -> Option<Span> {
             Some(NodeVariant(variant)) => variant.span,
             Some(NodeExpr(expr)) => expr.span,
             Some(NodeStmt(stmt)) => stmt.span,
+            Some(NodeTy(ty)) => ty.span,
             Some(NodeLocal(pat)) => pat.span,
             Some(NodePat(pat)) => pat.span,
             Some(NodeBlock(block)) => block.span,
@@ -664,10 +723,6 @@ pub fn node_to_string(&self, id: NodeId) -> String {
     pub fn node_to_user_string(&self, id: NodeId) -> String {
         node_id_to_string(self, id, false)
     }
-
-    pub fn is_inlined(&self, id: NodeId) -> bool {
-        id >= self.local_node_id_watermark
-    }
 }
 
 pub struct NodesMatchingSuffix<'a, 'ast:'a> {
@@ -846,13 +901,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
     }
 
     let local_node_id_watermark = map.len() as NodeId;
+    let local_def_id_watermark = definitions.len();
 
     Map {
         forest: forest,
         dep_graph: forest.dep_graph.clone(),
         map: RefCell::new(map),
         definitions: RefCell::new(definitions),
-        local_node_id_watermark: local_node_id_watermark
+        local_node_id_watermark: local_node_id_watermark,
+        local_def_id_watermark: local_def_id_watermark,
     }
 }
 
@@ -866,7 +923,8 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
                                           -> &'ast InlinedItem {
     let mut fld = IdAndSpanUpdater::new(fold_ops);
     let ii = match ii {
-        II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
+        II::Item(d, i) => II::Item(fld.fold_ops.new_def_id(d),
+                                   i.map(|i| fld.fold_item(i))),
         II::TraitItem(d, ti) => {
             II::TraitItem(fld.fold_ops.new_def_id(d),
                           ti.map(|ti| fld.fold_trait_item(ti)))
@@ -875,7 +933,8 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
             II::ImplItem(fld.fold_ops.new_def_id(d),
                          ii.map(|ii| fld.fold_impl_item(ii)))
         }
-        II::Foreign(i) => II::Foreign(i.map(|i| fld.fold_foreign_item(i)))
+        II::Foreign(d, i) => II::Foreign(fld.fold_ops.new_def_id(d),
+                                         i.map(|i| fld.fold_foreign_item(i)))
     };
 
     let ii = map.forest.inlined_items.alloc(ii);
@@ -920,6 +979,7 @@ fn print_node(&mut self, node: &Node) -> io::Result<()> {
             NodeVariant(a)     => self.print_variant(&a),
             NodeExpr(a)        => self.print_expr(&a),
             NodeStmt(a)        => self.print_stmt(&a),
+            NodeTy(a)          => self.print_type(&a),
             NodePat(a)         => self.print_pat(&a),
             NodeBlock(a)       => self.print_block(&a),
             NodeLifetime(a)    => self.print_lifetime(&a),
@@ -1008,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeStmt(ref stmt)) => {
             format!("stmt {}{}", pprust::stmt_to_string(&stmt), id_str)
         }
+        Some(NodeTy(ref ty)) => {
+            format!("type {}{}", pprust::ty_to_string(&ty), id_str)
+        }
         Some(NodeLocal(ref pat)) => {
             format!("local {}{}", pprust::pat_to_string(&pat), id_str)
         }
index 9212fda6502532e1ab5fc75e466fac752334ad14..707ef987c2c06e1518c466bccad774f5a9765732 100644 (file)
@@ -1132,6 +1132,8 @@ pub enum Ty_ {
     TyObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
     TyPolyTraitRef(TyParamBounds),
+    /// An `impl TraitA+TraitB` type.
+    TyImplTrait(TyParamBounds),
     /// Unused for now
     TyTypeof(P<Expr>),
     /// TyInfer means the type should be inferred instead of it having been
index 5f2fac5c01b30df8b719ef301e13cafde1a1cbbd..6dedae5ccd75d2761321976ae5a260c343ab7315 100644 (file)
@@ -536,6 +536,9 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
             hir::TyPolyTraitRef(ref bounds) => {
                 self.print_bounds("", &bounds[..])?;
             }
+            hir::TyImplTrait(ref bounds) => {
+                self.print_bounds("impl ", &bounds[..])?;
+            }
             hir::TyFixedLengthVec(ref ty, ref v) => {
                 word(&mut self.s, "[")?;
                 self.print_type(&ty)?;
index 511cc32d2e1e6cfeb47d00fa65076fba5445de64..3ad5ef1e0ff6d438720898027ddbed945692dcde 100644 (file)
@@ -94,7 +94,7 @@
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax_pos::{self, Pos, Span};
-use errors::{DiagnosticBuilder, check_old_school};
+use errors::DiagnosticBuilder;
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn note_and_explain_region(self,
@@ -541,25 +541,19 @@ pub fn note_type_err(&self,
 
         let span = origin.span();
 
-        let mut is_simple_error = false;
-
         if let Some((expected, found)) = expected_found {
-            is_simple_error = if let &TypeError::Sorts(ref values) = terr {
+            let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
                 values.expected.is_primitive() && values.found.is_primitive()
             } else {
                 false
             };
 
-            if !is_simple_error || check_old_school() {
+            if !is_simple_error {
                 diag.note_expected_found(&"type", &expected, &found);
             }
         }
 
-        if !is_simple_error && check_old_school() {
-            diag.span_note(span, &format!("{}", terr));
-        } else {
-            diag.span_label(span, &terr);
-        }
+        diag.span_label(span, &terr);
 
         self.note_error_origin(diag, &origin);
         self.check_and_note_conflicting_crates(diag, terr, span);
index 880661a882af3c38e114390d6d39226b5eccd020..1fb4e59e13189ff07fc14de61e81f58142d9ecff 100644 (file)
@@ -170,7 +170,8 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::TyClosure(..) |
             ty::TyTuple(..) |
             ty::TyProjection(..) |
-            ty::TyParam(..) => {
+            ty::TyParam(..) |
+            ty::TyAnon(..) => {
                 t.super_fold_with(self)
             }
         }
index be9adf7085cd4aee2780ccc5fd00719f656ab1a7..697478015cb7b65a496d0b88ec48555f25fa7e37 100644 (file)
@@ -34,7 +34,7 @@
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::relate::{Relate, RelateResult, TypeRelation};
-use traits::{self, PredicateObligations, ProjectionMode};
+use traits::{self, PredicateObligations, Reveal};
 use rustc_data_structures::unify::{self, UnificationTable};
 use std::cell::{Cell, RefCell, Ref, RefMut};
 use std::fmt;
@@ -147,8 +147,8 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     // Sadly, the behavior of projection varies a bit depending on the
     // stage of compilation. The specifics are given in the
-    // documentation for `ProjectionMode`.
-    projection_mode: ProjectionMode,
+    // documentation for `Reveal`.
+    projection_mode: Reveal,
 
     // When an error occurs, we want to avoid reporting "derived"
     // errors that are due to this original failure. Normally, we
@@ -459,7 +459,7 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     arenas: ty::CtxtArenas<'tcx>,
     tables: Option<RefCell<ty::Tables<'tcx>>>,
     param_env: Option<ty::ParameterEnvironment<'gcx>>,
-    projection_mode: ProjectionMode,
+    projection_mode: Reveal,
     normalize: bool
 }
 
@@ -467,7 +467,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
     pub fn infer_ctxt(self,
                       tables: Option<ty::Tables<'tcx>>,
                       param_env: Option<ty::ParameterEnvironment<'gcx>>,
-                      projection_mode: ProjectionMode)
+                      projection_mode: Reveal)
                       -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         InferCtxtBuilder {
             global_tcx: self,
@@ -479,7 +479,7 @@ pub fn infer_ctxt(self,
         }
     }
 
-    pub fn normalizing_infer_ctxt(self, projection_mode: ProjectionMode)
+    pub fn normalizing_infer_ctxt(self, projection_mode: Reveal)
                                   -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         InferCtxtBuilder {
             global_tcx: self,
@@ -509,7 +509,7 @@ pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>)
             projection_cache: RefCell::new(traits::ProjectionCache::new()),
             reported_trait_errors: RefCell::new(FnvHashSet()),
             normalize: false,
-            projection_mode: ProjectionMode::AnyFinal,
+            projection_mode: Reveal::NotSpecializable,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: self.sess.err_count(),
             obligations_in_snapshot: Cell::new(false),
@@ -641,7 +641,7 @@ pub fn normalize_associated_type<T>(self, value: &T) -> T
             return value;
         }
 
-        self.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| {
+        self.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
             value.trans_normalize(&infcx)
         })
     }
@@ -659,7 +659,7 @@ pub fn normalize_associated_type_in_env<T>(
             return value;
         }
 
-        self.infer_ctxt(None, Some(env.clone()), ProjectionMode::Any).enter(|infcx| {
+        self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| {
             value.trans_normalize(&infcx)
        })
     }
@@ -736,7 +736,7 @@ pub fn drain_fulfillment_cx<T>(&self,
         Ok(self.tcx.erase_regions(&result))
     }
 
-    pub fn projection_mode(&self) -> ProjectionMode {
+    pub fn projection_mode(&self) -> Reveal {
         self.projection_mode
     }
 
index 3230a08c27630bbbd4095a1792d24630265350a7..f0ddcdc07e1206beb5746685b0f7897d833cbb83 100644 (file)
 
 declare_lint! {
     pub PRIVATE_IN_PUBLIC,
-    Warn,
+    Deny,
     "detect private items in public interfaces not caught by the old implementation"
 }
 
index 32344a7b9c8deb1485d2d5ac8e27c8102144c0c3..f1bb3a37e3c273c9ebbfbf39850cff2cd8a3b1f6 100644 (file)
@@ -94,19 +94,19 @@ pub enum DefLike {
 /// that we trans.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum InlinedItem {
-    Item(P<hir::Item>),
+    Item(DefId /* def-id in source crate */, P<hir::Item>),
     TraitItem(DefId /* impl id */, P<hir::TraitItem>),
     ImplItem(DefId /* impl id */, P<hir::ImplItem>),
-    Foreign(P<hir::ForeignItem>),
+    Foreign(DefId /* extern item */, P<hir::ForeignItem>),
 }
 
 /// A borrowed version of `hir::InlinedItem`.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub enum InlinedItemRef<'a> {
-    Item(&'a hir::Item),
+    Item(DefId, &'a hir::Item),
     TraitItem(DefId, &'a hir::TraitItem),
     ImplItem(DefId, &'a hir::ImplItem),
-    Foreign(&'a hir::ForeignItem)
+    Foreign(DefId, &'a hir::ForeignItem)
 }
 
 /// Item definitions in the currently-compiled crate would have the CrateNum
@@ -283,8 +283,8 @@ pub fn visit<'ast,V>(&'ast self, visitor: &mut V)
         where V: Visitor<'ast>
     {
         match *self {
-            InlinedItem::Item(ref i) => visitor.visit_item(&i),
-            InlinedItem::Foreign(ref i) => visitor.visit_foreign_item(&i),
+            InlinedItem::Item(_, ref i) => visitor.visit_item(&i),
+            InlinedItem::Foreign(_, ref i) => visitor.visit_foreign_item(&i),
             InlinedItem::TraitItem(_, ref ti) => visitor.visit_trait_item(ti),
             InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
         }
index 446767ecbcaba1e1cb1daf08da4c0602b2826fff..3ca6cf039979705cc09477902e3912c270daf7d2 100644 (file)
@@ -63,9 +63,11 @@ fn require_unsafe(&mut self, span: Span, description: &str) {
         match self.unsafe_context.root {
             SafeContext => {
                 // Report an error.
-                span_err!(self.tcx.sess, span, E0133,
-                          "{} requires unsafe function or block",
-                          description);
+                struct_span_err!(
+                    self.tcx.sess, span, E0133,
+                    "{} requires unsafe function or block", description)
+                    .span_label(span, &format!("unsafe call requires unsafe function or block"))
+                    .emit();
             }
             UnsafeBlock(block_id) => {
                 // OK, but record this.
index d753381d71e252eb5e9ef15f5a76414a0d581d5e..15f2f21ef25291b2c4df292dada02a9bcd701d19 100644 (file)
@@ -12,7 +12,7 @@
 use hir::def::Def;
 use hir::def_id::DefId;
 use infer::InferCtxt;
-use traits::ProjectionMode;
+use traits::Reveal;
 use ty::{self, Ty, TyCtxt};
 use ty::layout::{LayoutError, Pointer, SizeSkeleton};
 
@@ -36,7 +36,7 @@ struct ItemVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
     fn visit_const(&mut self, item_id: ast::NodeId, expr: &hir::Expr) {
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id);
-        self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| {
+        self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
@@ -114,7 +114,7 @@ fn check_transmute(&self, span: Span, from: Ty<'gcx>, to: Ty<'gcx>, id: ast::Nod
 impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
     // const, static and N in [T; N].
     fn visit_expr(&mut self, expr: &hir::Expr) {
-        self.tcx.infer_ctxt(None, None, ProjectionMode::Any).enter(|infcx| {
+        self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
@@ -144,7 +144,7 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
             span_bug!(s, "intrinsicck: closure outside of function")
         }
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
-        self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Any).enter(|infcx| {
+        self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| {
             let mut visitor = ExprVisitor {
                 infcx: &infcx
             };
index 1222b5f42a19f6aeca5de5d471cadc434a05f1a9..f62c9a5d8823e7586b9d90b77aa420e62f80549c 100644 (file)
 use hir::def::*;
 use hir::pat_util;
 use ty::{self, TyCtxt, ParameterEnvironment};
-use traits::{self, ProjectionMode};
+use traits::{self, Reveal};
 use ty::subst::Subst;
 use lint;
 use util::nodemap::NodeMap;
@@ -1484,7 +1484,7 @@ fn check_ret(&self,
                 let param_env = ParameterEnvironment::for_item(self.ir.tcx, id);
                 let t_ret_subst = t_ret.subst(self.ir.tcx, &param_env.free_substs);
                 let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env),
-                                                    ProjectionMode::Any).enter(|infcx| {
+                                                    Reveal::All).enter(|infcx| {
                     let cause = traits::ObligationCause::dummy();
                     traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil()
                 });
index 7f6614a959c894634e2d3898ed0a89c083863f97..76c73f12f4ebe28c485b3e4c9257d4e9c4cb4073 100644 (file)
@@ -718,10 +718,14 @@ fn check_lifetime_defs(&mut self, old_scope: Scope, lifetimes: &[hir::LifetimeDe
                 let lifetime_j = &lifetimes[j];
 
                 if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
-                    span_err!(self.sess, lifetime_j.lifetime.span, E0263,
-                        "lifetime name `{}` declared twice in \
-                                the same scope",
-                                lifetime_j.lifetime.name);
+                    struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263,
+                                     "lifetime name `{}` declared twice in the same scope",
+                                     lifetime_j.lifetime.name)
+                        .span_label(lifetime_j.lifetime.span,
+                                    &format!("declared twice"))
+                        .span_label(lifetime_i.lifetime.span,
+                                   &format!("previous declaration here"))
+                        .emit();
                 }
             }
 
@@ -828,7 +832,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
         constrained_by_input.visit_ty(&arg.ty);
     }
 
-    let mut appears_in_output = AllCollector { regions: FnvHashSet() };
+    let mut appears_in_output = AllCollector {
+        regions: FnvHashSet(),
+        impl_trait: false
+    };
     intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
 
     debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
@@ -838,7 +845,10 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     //
     // Subtle point: because we disallow nested bindings, we can just
     // ignore binders here and scrape up all names we see.
-    let mut appears_in_where_clause = AllCollector { regions: FnvHashSet() };
+    let mut appears_in_where_clause = AllCollector {
+        regions: FnvHashSet(),
+        impl_trait: false
+    };
     for ty_param in generics.ty_params.iter() {
         walk_list!(&mut appears_in_where_clause,
                    visit_ty_param_bound,
@@ -860,12 +870,16 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
     // Late bound regions are those that:
     // - appear in the inputs
     // - do not appear in the where-clauses
+    // - are not implicitly captured by `impl Trait`
     for lifetime in &generics.lifetimes {
         let name = lifetime.lifetime.name;
 
         // appears in the where clauses? early-bound.
         if appears_in_where_clause.regions.contains(&name) { continue; }
 
+        // any `impl Trait` in the return type? early-bound.
+        if appears_in_output.impl_trait { continue; }
+
         // does not appear in the inputs, but appears in the return
         // type? eventually this will be early-bound, but for now we
         // just mark it so we can issue warnings.
@@ -928,12 +942,20 @@ fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
 
     struct AllCollector {
         regions: FnvHashSet<ast::Name>,
+        impl_trait: bool
     }
 
     impl<'v> Visitor<'v> for AllCollector {
         fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
             self.regions.insert(lifetime_ref.name);
         }
+
+        fn visit_ty(&mut self, ty: &hir::Ty) {
+            if let hir::TyImplTrait(_) = ty.node {
+                self.impl_trait = true;
+            }
+            intravisit::walk_ty(self, ty);
+        }
     }
 }
 
index 1a34699aff491754aea088576fdefa5c47f00106..92de65798d3cbb18db8277631034ce72439f3f6d 100644 (file)
@@ -8,9 +8,31 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use util::nodemap::NodeMap;
+use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
+use hir::def_id::DefId;
 use mir::repr::Mir;
+use std::marker::PhantomData;
 
 pub struct MirMap<'tcx> {
-    pub map: NodeMap<Mir<'tcx>>,
+    pub map: DepTrackingMap<MirMapConfig<'tcx>>,
+}
+
+impl<'tcx> MirMap<'tcx> {
+    pub fn new(graph: DepGraph) -> Self {
+        MirMap {
+            map: DepTrackingMap::new(graph)
+        }
+    }
+}
+
+pub struct MirMapConfig<'tcx> {
+    data: PhantomData<&'tcx ()>
+}
+
+impl<'tcx> DepTrackingMapConfig for MirMapConfig<'tcx> {
+    type Key = DefId;
+    type Value = Mir<'tcx>;
+    fn to_dep_node(key: &DefId) -> DepNode<DefId> {
+        DepNode::Mir(*key)
+    }
 }
index 93507246241de62bde905a68e9fde7acc47e7c47..08614ca253be51867b6c55205ce88aa04ba07b00 100644 (file)
@@ -689,13 +689,17 @@ pub struct Statement<'tcx> {
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum StatementKind<'tcx> {
     Assign(Lvalue<'tcx>, Rvalue<'tcx>),
+    SetDiscriminant{ lvalue: Lvalue<'tcx>, variant_index: usize },
 }
 
 impl<'tcx> Debug for Statement<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
         use self::StatementKind::*;
         match self.kind {
-            Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv)
+            Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
+            SetDiscriminant{lvalue: ref lv, variant_index: index} => {
+                write!(fmt, "discriminant({:?}) = {:?}", lv, index)
+            }
         }
     }
 }
index e3905c39daa9c593d1d750ea54858bb40542e5bc..534bb2c0b2b2a1fde84d4067c3376f7f21f759f3 100644 (file)
@@ -113,75 +113,38 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
     }
 }
 
-impl<'a, 'gcx, 'tcx> Mir<'tcx> {
-    pub fn operand_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                      operand: &Operand<'tcx>)
-                      -> Ty<'tcx>
-    {
-        match *operand {
-            Operand::Consume(ref l) => self.lvalue_ty(tcx, l).to_ty(tcx),
-            Operand::Constant(ref c) => c.ty,
-        }
-    }
-
-    pub fn binop_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                    op: BinOp,
-                    lhs_ty: Ty<'tcx>,
-                    rhs_ty: Ty<'tcx>)
-                    -> Ty<'tcx>
-    {
-        // FIXME: handle SIMD correctly
-        match op {
-            BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div | BinOp::Rem |
-            BinOp::BitXor | BinOp::BitAnd | BinOp::BitOr => {
-                // these should be integers or floats of the same size.
-                assert_eq!(lhs_ty, rhs_ty);
-                lhs_ty
-            }
-            BinOp::Shl | BinOp::Shr => {
-                lhs_ty // lhs_ty can be != rhs_ty
-            }
-            BinOp::Eq | BinOp::Lt | BinOp::Le |
-            BinOp::Ne | BinOp::Ge | BinOp::Gt => {
-                tcx.types.bool
-            }
-        }
-    }
-
-    pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                     lvalue: &Lvalue<'tcx>)
-                     -> LvalueTy<'tcx>
-    {
-        match *lvalue {
-            Lvalue::Var(index) =>
-                LvalueTy::Ty { ty: self.var_decls[index].ty },
-            Lvalue::Temp(index) =>
-                LvalueTy::Ty { ty: self.temp_decls[index].ty },
-            Lvalue::Arg(index) =>
-                LvalueTy::Ty { ty: self.arg_decls[index].ty },
-            Lvalue::Static(def_id) =>
+impl<'tcx> Lvalue<'tcx> {
+    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> LvalueTy<'tcx> {
+        match self {
+            &Lvalue::Var(index) =>
+                LvalueTy::Ty { ty: mir.var_decls[index].ty },
+            &Lvalue::Temp(index) =>
+                LvalueTy::Ty { ty: mir.temp_decls[index].ty },
+            &Lvalue::Arg(index) =>
+                LvalueTy::Ty { ty: mir.arg_decls[index].ty },
+            &Lvalue::Static(def_id) =>
                 LvalueTy::Ty { ty: tcx.lookup_item_type(def_id).ty },
-            Lvalue::ReturnPointer =>
-                LvalueTy::Ty { ty: self.return_ty.unwrap() },
-            Lvalue::Projection(ref proj) =>
-                self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
+            &Lvalue::ReturnPointer =>
+                LvalueTy::Ty { ty: mir.return_ty.unwrap() },
+            &Lvalue::Projection(ref proj) =>
+                proj.base.ty(mir, tcx).projection_ty(tcx, &proj.elem),
         }
     }
+}
 
-    pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                     rvalue: &Rvalue<'tcx>)
-                     -> Option<Ty<'tcx>>
+impl<'tcx> Rvalue<'tcx> {
+    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>>
     {
-        match *rvalue {
-            Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
-            Rvalue::Repeat(ref operand, ref count) => {
-                let op_ty = self.operand_ty(tcx, operand);
+        match self {
+            &Rvalue::Use(ref operand) => Some(operand.ty(mir, tcx)),
+            &Rvalue::Repeat(ref operand, ref count) => {
+                let op_ty = operand.ty(mir, tcx);
                 let count = count.value.as_u64(tcx.sess.target.uint_type);
                 assert_eq!(count as usize as u64, count);
                 Some(tcx.mk_array(op_ty, count as usize))
             }
-            Rvalue::Ref(reg, bk, ref lv) => {
-                let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
+            &Rvalue::Ref(reg, bk, ref lv) => {
+                let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
                 Some(tcx.mk_ref(
                     tcx.mk_region(reg),
                     ty::TypeAndMut {
@@ -190,31 +153,31 @@ pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     }
                 ))
             }
-            Rvalue::Len(..) => Some(tcx.types.usize),
-            Rvalue::Cast(_, _, ty) => Some(ty),
-            Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
-                let lhs_ty = self.operand_ty(tcx, lhs);
-                let rhs_ty = self.operand_ty(tcx, rhs);
-                Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
+            &Rvalue::Len(..) => Some(tcx.types.usize),
+            &Rvalue::Cast(_, _, ty) => Some(ty),
+            &Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
+                let lhs_ty = lhs.ty(mir, tcx);
+                let rhs_ty = rhs.ty(mir, tcx);
+                Some(op.ty(tcx, lhs_ty, rhs_ty))
             }
-            Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
-                let lhs_ty = self.operand_ty(tcx, lhs);
-                let rhs_ty = self.operand_ty(tcx, rhs);
-                let ty = self.binop_ty(tcx, op, lhs_ty, rhs_ty);
+            &Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
+                let lhs_ty = lhs.ty(mir, tcx);
+                let rhs_ty = rhs.ty(mir, tcx);
+                let ty = op.ty(tcx, lhs_ty, rhs_ty);
                 let ty = tcx.mk_tup(vec![ty, tcx.types.bool]);
                 Some(ty)
             }
-            Rvalue::UnaryOp(_, ref operand) => {
-                Some(self.operand_ty(tcx, operand))
+            &Rvalue::UnaryOp(_, ref operand) => {
+                Some(operand.ty(mir, tcx))
             }
-            Rvalue::Box(t) => {
+            &Rvalue::Box(t) => {
                 Some(tcx.mk_box(t))
             }
-            Rvalue::Aggregate(ref ak, ref ops) => {
+            &Rvalue::Aggregate(ref ak, ref ops) => {
                 match *ak {
                     AggregateKind::Vec => {
                         if let Some(operand) = ops.get(0) {
-                            let ty = self.operand_ty(tcx, operand);
+                            let ty = operand.ty(mir, tcx);
                             Some(tcx.mk_array(ty, ops.len()))
                         } else {
                             None
@@ -222,7 +185,7 @@ pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     }
                     AggregateKind::Tuple => {
                         Some(tcx.mk_tup(
-                            ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
+                            ops.iter().map(|op| op.ty(mir, tcx)).collect()
                         ))
                     }
                     AggregateKind::Adt(def, _, substs) => {
@@ -233,7 +196,40 @@ pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     }
                 }
             }
-            Rvalue::InlineAsm { .. } => None
+            &Rvalue::InlineAsm { .. } => None
+        }
+    }
+}
+
+impl<'tcx> Operand<'tcx> {
+    pub fn ty<'a, 'gcx>(&self, mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
+        match self {
+            &Operand::Consume(ref l) => l.ty(mir, tcx).to_ty(tcx),
+            &Operand::Constant(ref c) => c.ty,
+        }
+    }
+}
+
+impl<'tcx> BinOp {
+      pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                    lhs_ty: Ty<'tcx>,
+                    rhs_ty: Ty<'tcx>)
+                    -> Ty<'tcx> {
+        // FIXME: handle SIMD correctly
+        match self {
+            &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
+            &BinOp::BitXor | &BinOp::BitAnd | &BinOp::BitOr => {
+                // these should be integers or floats of the same size.
+                assert_eq!(lhs_ty, rhs_ty);
+                lhs_ty
+            }
+            &BinOp::Shl | &BinOp::Shr => {
+                lhs_ty // lhs_ty can be != rhs_ty
+            }
+            &BinOp::Eq | &BinOp::Lt | &BinOp::Le |
+            &BinOp::Ne | &BinOp::Ge | &BinOp::Gt => {
+                tcx.types.bool
+            }
         }
     }
 }
index 4ca3907d4e602bcf94c9945818b91eed0b6eab13..57601e67504328f7f422a631be2c174c61852781 100644 (file)
@@ -11,7 +11,6 @@
 use dep_graph::DepNode;
 use hir;
 use hir::map::DefPathData;
-use hir::def_id::DefId;
 use mir::mir_map::MirMap;
 use mir::repr::{Mir, Promoted};
 use ty::TyCtxt;
@@ -73,9 +72,6 @@ pub fn item_id(&self) -> NodeId {
 /// Various information about pass.
 pub trait Pass {
     // fn should_run(Session) to check if pass should run?
-    fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
-        DepNode::MirPass(def_id)
-    }
     fn name(&self) -> &str {
         let name = unsafe { ::std::intrinsics::type_name::<Self>() };
         if let Some(tail) = name.rfind(":") {
@@ -119,10 +115,11 @@ fn run_pass<'a>(&mut self,
                     map: &mut MirMap<'tcx>,
                     hooks: &mut [Box<for<'s> MirPassHook<'s>>])
     {
-        for (&id, mir) in &mut map.map {
-            let def_id = tcx.map.local_def_id(id);
-            let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
-
+        let def_ids = map.map.keys();
+        for def_id in def_ids {
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let mir = map.map.get_mut(&def_id).unwrap();
+            let id = tcx.map.as_local_node_id(def_id).unwrap();
             let src = MirSource::from_node(tcx, id);
 
             for hook in &mut *hooks {
index 3f714ff4d5152b3eef0a134fc49b92232e4b0d62..d44f00ed2cbe2abb4636a3b631b04fb27f8aa4ab 100644 (file)
@@ -323,6 +323,9 @@ fn super_statement(&mut self,
                                           ref $($mutability)* rvalue) => {
                         self.visit_assign(block, lvalue, rvalue);
                     }
+                    StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
+                        self.visit_lvalue(lvalue, LvalueContext::Store);
+                    }
                 }
             }
 
index 6ed91cdbe18bc3c2551c7dbee48803ba11eabb61..0fb4d0f8fea5e63f171c5ddbc642505775b894f8 100644 (file)
@@ -176,6 +176,10 @@ pub enum PrintRequest {
     CrateName,
     Cfg,
     TargetList,
+    TargetCPUs,
+    TargetFeatures,
+    RelocationModels,
+    CodeModels,
 }
 
 pub enum Input {
@@ -629,9 +633,9 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
     lto: bool = (false, parse_bool,
         "perform LLVM link-time optimizations"),
     target_cpu: Option<String> = (None, parse_opt_string,
-        "select target processor (llc -mcpu=help for details)"),
+        "select target processor (rustc --print target-cpus for details)"),
     target_feature: String = ("".to_string(), parse_string,
-        "target specific attributes (llc -mattr=help for details)"),
+        "target specific attributes (rustc --print target-features for details)"),
     passes: Vec<String> = (Vec::new(), parse_list,
         "a list of extra LLVM passes to run (space separated)"),
     llvm_args: Vec<String> = (Vec::new(), parse_list,
@@ -655,9 +659,9 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
     no_redzone: Option<bool> = (None, parse_opt_bool,
         "disable the use of the redzone"),
     relocation_model: Option<String> = (None, parse_opt_string,
-         "choose the relocation model to use (llc -relocation-model for details)"),
+         "choose the relocation model to use (rustc --print relocation-models for details)"),
     code_model: Option<String> = (None, parse_opt_string,
-         "choose the code model to use (llc -code-model for details)"),
+         "choose the code model to use (rustc --print code-models for details)"),
     metadata: Vec<String> = (Vec::new(), parse_list,
          "metadata to mangle symbol names with"),
     extra_filename: String = ("".to_string(), parse_string,
@@ -745,6 +749,8 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
           "attempt to recover from parse errors (experimental)"),
     incremental: Option<String> = (None, parse_opt_string,
           "enable incremental compilation (experimental)"),
+    incremental_info: bool = (false, parse_bool,
+        "print high-level information about incremental reuse (or the lack thereof)"),
     dump_dep_graph: bool = (false, parse_bool,
           "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
     query_dep_graph: bool = (false, parse_bool,
@@ -1022,7 +1028,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
                  "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
         opt::multi_s("", "print", "Comma separated list of compiler information to \
                                print on stdout",
-                 "[crate-name|file-names|sysroot|cfg|target-list]"),
+                 "[crate-name|file-names|sysroot|cfg|target-list|target-cpus|\
+                   target-features|relocation-models|code-models]"),
         opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
         opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
         opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
@@ -1055,7 +1062,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                      "NAME=PATH"),
         opt::opt_s("", "sysroot", "Override the system root", "PATH"),
         opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
-        opt::opt_ubnr("", "error-format",
+        opt::opt_s("", "error-format",
                       "How errors and other messages are produced",
                       "human|json"),
         opt::opt_s("", "color", "Configure coloring of output:
@@ -1236,6 +1243,24 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         early_error(error_format, "Value for codegen units must be a positive nonzero integer");
     }
 
+    let mut prints = Vec::<PrintRequest>::new();
+    if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
+        prints.push(PrintRequest::TargetCPUs);
+        cg.target_cpu = None;
+    };
+    if cg.target_feature == "help" {
+        prints.push(PrintRequest::TargetFeatures);
+        cg.target_feature = "".to_string();
+    }
+    if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
+        prints.push(PrintRequest::RelocationModels);
+        cg.relocation_model = None;
+    }
+    if cg.code_model.as_ref().map_or(false, |s| s == "help") {
+        prints.push(PrintRequest::CodeModels);
+        cg.code_model = None;
+    }
+
     let cg = cg;
 
     let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
@@ -1313,18 +1338,22 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
     let test = matches.opt_present("test");
 
-    let prints = matches.opt_strs("print").into_iter().map(|s| {
+    prints.extend(matches.opt_strs("print").into_iter().map(|s| {
         match &*s {
             "crate-name" => PrintRequest::CrateName,
             "file-names" => PrintRequest::FileNames,
             "sysroot" => PrintRequest::Sysroot,
             "cfg" => PrintRequest::Cfg,
             "target-list" => PrintRequest::TargetList,
+            "target-cpus" => PrintRequest::TargetCPUs,
+            "target-features" => PrintRequest::TargetFeatures,
+            "relocation-models" => PrintRequest::RelocationModels,
+            "code-models" => PrintRequest::CodeModels,
             req => {
                 early_error(error_format, &format!("unknown print request `{}`", req))
             }
         }
-    }).collect::<Vec<_>>();
+    }));
 
     if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
         early_warn(error_format, "-C remark will not show source locations without \
index cee18232ec98a05b71e2400ffc63b9a30bb833b3..9ab75c8a5a20c8e17a9c47c3d5c70c18d779ccc0 100644 (file)
@@ -23,7 +23,6 @@
 use syntax::ast::{NodeId, Name};
 use errors::{self, DiagnosticBuilder};
 use errors::emitter::{Emitter, EmitterWriter};
-use errors::snippet::FormatMode;
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
 use syntax::parse;
@@ -369,9 +368,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
     let emitter: Box<Emitter> = match sopts.error_format {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config,
-                                           Some(registry),
-                                           Some(codemap.clone()),
-                                           errors::snippet::FormatMode::EnvironmentSelected))
+                                           Some(codemap.clone())))
         }
         config::ErrorOutputType::Json => {
             Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
@@ -509,9 +506,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config,
-                                           None,
-                                           None,
-                                           FormatMode::EnvironmentSelected))
+                                           None))
         }
         config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
     };
@@ -524,9 +519,7 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config,
-                                           None,
-                                           None,
-                                           FormatMode::EnvironmentSelected))
+                                           None))
         }
         config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
     };
index 4344eb1ebf6645faf708d6f0c55677fd10c5b004..37193d45e68852245a523c298b94e01689ce8164 100644 (file)
@@ -281,7 +281,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
             true
         }
 
-        ty::TyClosure(..) => {
+        ty::TyClosure(..) | ty::TyAnon(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
index 9950560b13a5a7cda70ccd0d38ccc2fedf6a6c46..09b5a34fdf33722cb048348fe8e70b16d6c13a3b 100644 (file)
@@ -211,6 +211,7 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::TyTuple(..) => Some(12),
                 ty::TyProjection(..) => Some(13),
                 ty::TyParam(..) => Some(14),
+                ty::TyAnon(..) => Some(15),
                 ty::TyInfer(..) | ty::TyError => None
             }
         }
@@ -654,6 +655,7 @@ pub fn recursive_type_with_infinite_size_error(self,
         let mut err = struct_span_err!(self.sess, span, E0072,
                                        "recursive type `{}` has infinite size",
                                        self.item_path_str(type_def_id));
+        err.span_label(span, &format!("recursive type has infinite size"));
         err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
                            at some point to make `{}` representable",
                           self.item_path_str(type_def_id)));
@@ -670,10 +672,15 @@ pub fn report_object_safety_error(self,
         let mut err = match warning_node_id {
             Some(_) => None,
             None => {
-                Some(struct_span_err!(
-                    self.sess, span, E0038,
-                    "the trait `{}` cannot be made into an object",
-                    self.item_path_str(trait_def_id)))
+                let trait_str = self.item_path_str(trait_def_id);
+                let mut db = struct_span_err!(
+                            self.sess, span, E0038,
+                            "the trait `{}` cannot be made into an object",
+                            trait_str);
+                db.span_label(span,
+                              &format!("the trait `{}` cannot be made \
+                              into an object", trait_str));
+                Some(db)
             }
         };
 
index 23ffa4db96f77549b9382d7910c968d63ab64b14..5ba7b914d6591ba57c6cf42452c853165e477dcd 100644 (file)
@@ -10,7 +10,8 @@
 
 use dep_graph::DepGraph;
 use infer::{InferCtxt, InferOk};
-use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt};
+use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, TyCtxt, ToPredicate};
+use ty::subst::{Substs, Subst};
 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
 use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
 use std::marker::PhantomData;
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
-use super::FulfillmentError;
-use super::FulfillmentErrorCode;
-use super::ObligationCause;
-use super::PredicateObligation;
+use super::{FulfillmentError, FulfillmentErrorCode, SelectionError};
+use super::{ObligationCause, BuiltinDerivedObligation};
+use super::{PredicateObligation, TraitObligation, Obligation};
 use super::project;
 use super::select::SelectionContext;
 use super::Unimplemented;
@@ -51,6 +51,7 @@ pub struct GlobalFulfilledPredicates<'tcx> {
 /// along. Once all type inference constraints have been generated, the
 /// method `select_all_or_error` can be used to report any remaining
 /// ambiguous cases as errors.
+
 pub struct FulfillmentContext<'tcx> {
     // A list of all obligations that have been registered with this
     // fulfillment context.
@@ -84,6 +85,10 @@ pub struct FulfillmentContext<'tcx> {
     // obligations (otherwise, it's easy to fail to walk to a
     // particular node-id).
     region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
+
+    // A list of obligations that need to be deferred to
+    // a later time for them to be properly fulfilled.
+    deferred_obligations: Vec<DeferredObligation<'tcx>>,
 }
 
 #[derive(Clone)]
@@ -99,6 +104,90 @@ pub struct PendingPredicateObligation<'tcx> {
     pub stalled_on: Vec<Ty<'tcx>>,
 }
 
+/// An obligation which cannot be fulfilled in the context
+/// it was registered in, such as auto trait obligations on
+/// `impl Trait`, which require the concrete type to be
+/// available, only guaranteed after finishing type-checking.
+#[derive(Clone, Debug)]
+pub struct DeferredObligation<'tcx> {
+    pub predicate: ty::PolyTraitPredicate<'tcx>,
+    pub cause: ObligationCause<'tcx>
+}
+
+impl<'a, 'gcx, 'tcx> DeferredObligation<'tcx> {
+    /// If possible, create a `DeferredObligation` from
+    /// a trait predicate which had failed selection,
+    /// but could succeed later.
+    pub fn from_select_error(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                             obligation: &TraitObligation<'tcx>,
+                             selection_err: &SelectionError<'tcx>)
+                             -> Option<DeferredObligation<'tcx>> {
+        if let Unimplemented = *selection_err {
+            if DeferredObligation::must_defer(tcx, &obligation.predicate) {
+                return Some(DeferredObligation {
+                    predicate: obligation.predicate.clone(),
+                    cause: obligation.cause.clone()
+                });
+            }
+        }
+
+        None
+    }
+
+    /// Returns true if the given trait predicate can be
+    /// fulfilled at a later time.
+    pub fn must_defer(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                      predicate: &ty::PolyTraitPredicate<'tcx>)
+                      -> bool {
+        // Auto trait obligations on `impl Trait`.
+        if tcx.trait_has_default_impl(predicate.def_id()) {
+            let substs = predicate.skip_binder().trait_ref.substs;
+            if substs.types.as_slice().len() == 1 && substs.regions.is_empty() {
+                if let ty::TyAnon(..) = predicate.skip_binder().self_ty().sty {
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    /// If possible, return the nested obligations required
+    /// to fulfill this obligation.
+    pub fn try_select(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+                      -> Option<Vec<PredicateObligation<'tcx>>> {
+        if let ty::TyAnon(def_id, substs) = self.predicate.skip_binder().self_ty().sty {
+            // We can resolve the `impl Trait` to its concrete type.
+            if let Some(ty_scheme) = tcx.opt_lookup_item_type(def_id) {
+                let concrete_ty = ty_scheme.ty.subst(tcx, substs);
+                let concrete_substs = Substs::new_trait(vec![], vec![], concrete_ty);
+                let predicate = ty::TraitRef {
+                    def_id: self.predicate.def_id(),
+                    substs: tcx.mk_substs(concrete_substs)
+                }.to_predicate();
+
+                let original_obligation = Obligation::new(self.cause.clone(),
+                                                          self.predicate.clone());
+                let cause = original_obligation.derived_cause(BuiltinDerivedObligation);
+                return Some(vec![Obligation::new(cause, predicate)]);
+            }
+        }
+
+        None
+    }
+
+    /// Return the `PredicateObligation` this was created from.
+    pub fn to_obligation(&self) -> PredicateObligation<'tcx> {
+        let predicate = ty::Predicate::Trait(self.predicate.clone());
+        Obligation::new(self.cause.clone(), predicate)
+    }
+
+    /// Return an error as if this obligation had failed.
+    pub fn to_error(&self) -> FulfillmentError<'tcx> {
+        FulfillmentError::new(self.to_obligation(), CodeSelectionError(Unimplemented))
+    }
+}
+
 impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
     pub fn new() -> FulfillmentContext<'tcx> {
@@ -106,6 +195,7 @@ pub fn new() -> FulfillmentContext<'tcx> {
             predicates: ObligationForest::new(),
             rfc1592_obligations: Vec::new(),
             region_obligations: NodeMap(),
+            deferred_obligations: vec![],
         }
     }
 
@@ -224,10 +314,16 @@ pub fn select_all_or_error(&mut self,
     {
         self.select_where_possible(infcx)?;
 
+        // Fail all of the deferred obligations that haven't
+        // been otherwise removed from the context.
+        let deferred_errors = self.deferred_obligations.iter()
+                                  .map(|d| d.to_error());
+
         let errors: Vec<_> =
             self.predicates.to_errors(CodeAmbiguity)
                            .into_iter()
                            .map(|e| to_fulfillment_error(e))
+                           .chain(deferred_errors)
                            .collect();
         if errors.is_empty() {
             Ok(())
@@ -248,6 +344,10 @@ pub fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
         self.predicates.pending_obligations()
     }
 
+    pub fn take_deferred_obligations(&mut self) -> Vec<DeferredObligation<'tcx>> {
+        mem::replace(&mut self.deferred_obligations, vec![])
+    }
+
     /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
     /// only attempts to select obligations that haven't been seen before.
     fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
@@ -261,9 +361,10 @@ fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
 
             // Process pending obligations.
             let outcome = self.predicates.process_obligations(&mut FulfillProcessor {
-                    selcx: selcx,
-                    region_obligations: &mut self.region_obligations,
-                    rfc1592_obligations: &mut self.rfc1592_obligations
+                selcx: selcx,
+                region_obligations: &mut self.region_obligations,
+                rfc1592_obligations: &mut self.rfc1592_obligations,
+                deferred_obligations: &mut self.deferred_obligations
             });
             debug!("select: outcome={:?}", outcome);
 
@@ -298,7 +399,8 @@ fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>)
 struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
     selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
     region_obligations: &'a mut NodeMap<Vec<RegionObligation<'tcx>>>,
-    rfc1592_obligations: &'a mut Vec<PredicateObligation<'tcx>>
+    rfc1592_obligations: &'a mut Vec<PredicateObligation<'tcx>>,
+    deferred_obligations: &'a mut Vec<DeferredObligation<'tcx>>
 }
 
 impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> {
@@ -312,7 +414,8 @@ fn process_obligation(&mut self,
         process_predicate(self.selcx,
                           obligation,
                           self.region_obligations,
-                          self.rfc1592_obligations)
+                          self.rfc1592_obligations,
+                          self.deferred_obligations)
             .map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation {
                 obligation: o,
                 stalled_on: vec![]
@@ -354,7 +457,8 @@ fn process_predicate<'a, 'gcx, 'tcx>(
     selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
     pending_obligation: &mut PendingPredicateObligation<'tcx>,
     region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
-    rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>)
+    rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>,
+    deferred_obligations: &mut Vec<DeferredObligation<'tcx>>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>,
               FulfillmentErrorCode<'tcx>>
 {
@@ -422,7 +526,22 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                 Err(selection_err) => {
                     info!("selecting trait `{:?}` at depth {} yielded Err",
                           data, obligation.recursion_depth);
-                    Err(CodeSelectionError(selection_err))
+
+                    let defer = DeferredObligation::from_select_error(selcx.tcx(),
+                                                                      &trait_obligation,
+                                                                      &selection_err);
+                    if let Some(deferred_obligation) = defer {
+                        if let Some(nested) = deferred_obligation.try_select(selcx.tcx()) {
+                            Ok(Some(nested))
+                        } else {
+                            // Pretend that the obligation succeeded,
+                            // but record it for later.
+                            deferred_obligations.push(deferred_obligation);
+                            Ok(Some(vec![]))
+                        }
+                    } else {
+                        Err(CodeSelectionError(selection_err))
+                    }
                 }
             }
         }
@@ -629,6 +748,12 @@ fn add_if_global(&mut self, tcx: TyCtxt<'a, 'gcx, 'tcx>, key: &ty::Predicate<'tc
             // already has the required read edges, so we don't need
             // to add any more edges here.
             if data.is_global() {
+                // Don't cache predicates which were fulfilled
+                // by deferring them for later fulfillment.
+                if DeferredObligation::must_defer(tcx, data) {
+                    return;
+                }
+
                 if let Some(data) = tcx.lift_to_global(data) {
                     if self.set.insert(data.clone()) {
                         debug!("add_if_global: global predicate `{:?}` added", data);
index 17aa6544fe798d169244c092d16fa17ecf6a45e4..dc0807ba38faea39962ab3f576f55087a11f9223 100644 (file)
 pub use self::coherence::overlapping_impls;
 pub use self::coherence::OrphanCheckErr;
 pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
+pub use self::fulfill::DeferredObligation;
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::{normalize, normalize_projection_type, Normalized};
-pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, ProjectionMode};
+pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal};
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::object_safety::MethodViolationCode;
 pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
@@ -435,7 +436,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
 
-    tcx.infer_ctxt(None, Some(elaborated_env), ProjectionMode::AnyFinal).enter(|infcx| {
+    tcx.infer_ctxt(None, Some(elaborated_env), Reveal::NotSpecializable).enter(|infcx| {
         let predicates = match fully_normalize(&infcx, cause,
                                                &infcx.parameter_environment.caller_bounds) {
             Ok(predicates) => predicates,
index 30faf1a5f8b91b75fc13bf0ea69aaaec3f7acef3..aed4f4393241191d1f2d655f2ba594a709d67b10 100644 (file)
@@ -38,7 +38,7 @@
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum ProjectionMode {
+pub enum Reveal {
     /// FIXME (#32205)
     /// At coherence-checking time, we're still constructing the
     /// specialization graph, and thus we only project
@@ -67,7 +67,7 @@ pub enum ProjectionMode {
     ///
     /// The projection would succeed if `Output` had been defined
     /// directly in the impl for `u8`.
-    Topmost,
+    ExactMatch,
 
     /// At type-checking time, we refuse to project any associated
     /// type that is marked `default`. Non-`default` ("final") types
@@ -91,36 +91,22 @@ pub enum ProjectionMode {
     /// fn main() {
     ///     let <() as Assoc>::Output = true;
     /// }
-    AnyFinal,
+    NotSpecializable,
 
-    /// At trans time, all projections will succeed.
-    Any,
-}
-
-impl ProjectionMode {
-    pub fn is_topmost(&self) -> bool {
-        match *self {
-            ProjectionMode::Topmost => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_any_final(&self) -> bool {
-        match *self {
-            ProjectionMode::AnyFinal => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_any(&self) -> bool {
-        match *self {
-            ProjectionMode::Any => true,
-            _ => false,
-        }
-    }
+    /// At trans time, all monomorphic projections will succeed.
+    /// Also, `impl Trait` is normalized to the concrete type,
+    /// which has to be already collected by type-checking.
+    ///
+    /// NOTE: As `impl Trait`'s concrete type should *never*
+    /// be observable directly by the user, `Reveal::All`
+    /// should not be used by checks which may expose
+    /// type equality or type contents to the user.
+    /// There are some exceptions, e.g. around OIBITS and
+    /// transmute-checking, which expose some details, but
+    /// not the whole concrete type of the `impl Trait`.
+    All,
 }
 
-
 pub type PolyProjectionObligation<'tcx> =
     Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
 
@@ -322,6 +308,17 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
+            ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+                // Only normalize `impl Trait` after type-checking, usually in trans.
+                if self.selcx.projection_mode() == Reveal::All {
+                    let generic_ty = self.tcx().lookup_item_type(def_id).ty;
+                    let concrete_ty = generic_ty.subst(self.tcx(), substs);
+                    self.fold_ty(concrete_ty)
+                } else {
+                    ty
+                }
+            }
+
             ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
 
                 // (*) This is kind of hacky -- we need to be able to
@@ -797,8 +794,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
     debug!("assemble_candidates_from_trait_def(..)");
 
     // Check whether the self-type is itself a projection.
-    let trait_ref = match obligation_trait_ref.self_ty().sty {
-        ty::TyProjection(ref data) => data.trait_ref.clone(),
+    let (def_id, substs) = match obligation_trait_ref.self_ty().sty {
+        ty::TyProjection(ref data) => {
+            (data.trait_ref.def_id, data.trait_ref.substs)
+        }
+        ty::TyAnon(def_id, substs) => (def_id, substs),
         ty::TyInfer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -809,8 +809,8 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
     };
 
     // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = selcx.tcx().lookup_predicates(trait_ref.def_id);
-    let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
+    let trait_predicates = selcx.tcx().lookup_predicates(def_id);
+    let bounds = trait_predicates.instantiate(selcx.tcx(), substs);
     let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
     assemble_candidates_from_predicates(selcx,
                                         obligation,
@@ -902,7 +902,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
 
                 candidate_set.vec.push(ProjectionTyCandidate::Select);
             }
-            super::VtableImpl(ref impl_data) if !selcx.projection_mode().is_any() => {
+            super::VtableImpl(ref impl_data) => {
                 // We have to be careful when projecting out of an
                 // impl because of specialization. If we are not in
                 // trans (i.e., projection mode is not "any"), and the
@@ -926,37 +926,43 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                                                  impl_data.impl_def_id,
                                                  obligation.predicate.item_name);
                 let new_candidate = if let Some(node_item) = opt_node_item {
-                    if node_item.node.is_from_trait() {
-                        if node_item.item.ty.is_some() {
-                            // The impl inherited a `type Foo =
-                            // Bar` given in the trait, which is
-                            // implicitly default. No candidate.
-                            None
-                        } else {
-                            // The impl did not specify `type` and neither
-                            // did the trait:
-                            //
-                            // ```rust
-                            // trait Foo { type T; }
-                            // impl Foo for Bar { }
-                            // ```
-                            //
-                            // This is an error, but it will be
-                            // reported in `check_impl_items_against_trait`.
-                            // We accept it here but will flag it as
-                            // an error when we confirm the candidate
-                            // (which will ultimately lead to `normalize_to_error`
-                            // being invoked).
+                    let is_default = if node_item.node.is_from_trait() {
+                        // If true, the impl inherited a `type Foo = Bar`
+                        // given in the trait, which is implicitly default.
+                        // Otherwise, the impl did not specify `type` and
+                        // neither did the trait:
+                        //
+                        // ```rust
+                        // trait Foo { type T; }
+                        // impl Foo for Bar { }
+                        // ```
+                        //
+                        // This is an error, but it will be
+                        // reported in `check_impl_items_against_trait`.
+                        // We accept it here but will flag it as
+                        // an error when we confirm the candidate
+                        // (which will ultimately lead to `normalize_to_error`
+                        // being invoked).
+                        node_item.item.ty.is_some()
+                    } else {
+                        node_item.item.defaultness.is_default()
+                    };
+
+                    // Only reveal a specializable default if we're past type-checking
+                    // and the obligations is monomorphic, otherwise passes such as
+                    // transmute checking and polymorphic MIR optimizations could
+                    // get a result which isn't correct for all monomorphizations.
+                    if !is_default {
+                        Some(ProjectionTyCandidate::Select)
+                    } else if selcx.projection_mode() == Reveal::All {
+                        assert!(!poly_trait_ref.needs_infer());
+                        if !poly_trait_ref.needs_subst() {
                             Some(ProjectionTyCandidate::Select)
+                        } else {
+                            None
                         }
-                    } else if node_item.item.defaultness.is_default() {
-                        // The impl specified `default type Foo =
-                        // Bar`. No candidate.
-                        None
                     } else {
-                        // The impl specified `type Foo = Bar`
-                        // with no default. Add a candidate.
-                        Some(ProjectionTyCandidate::Select)
+                        None
                     }
                 } else {
                     // This is saying that neither the trait nor
@@ -1006,11 +1012,6 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                 };
                 candidate_set.vec.extend(new_candidate);
             }
-            super::VtableImpl(_) => {
-                // In trans mode, we can just project out of impls, no prob.
-                assert!(selcx.projection_mode().is_any());
-                candidate_set.vec.push(ProjectionTyCandidate::Select);
-            }
             super::VtableParam(..) => {
                 // This case tell us nothing about the value of an
                 // associated type. Consider:
@@ -1332,7 +1333,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
 /// starting from the given impl.
 ///
 /// Based on the "projection mode", this lookup may in fact only examine the
-/// topmost impl. See the comments for `ProjectionMode` for more details.
+/// topmost impl. See the comments for `Reveal` for more details.
 fn assoc_ty_def<'cx, 'gcx, 'tcx>(
     selcx: &SelectionContext<'cx, 'gcx, 'tcx>,
     impl_def_id: DefId,
@@ -1341,7 +1342,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
 {
     let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id;
 
-    if selcx.projection_mode().is_topmost() {
+    if selcx.projection_mode() == Reveal::ExactMatch {
         let impl_node = specialization_graph::Node::Impl(impl_def_id);
         for item in impl_node.items(selcx.tcx()) {
             if let ty::TypeTraitItem(assoc_ty) = item {
index 7a20b43b8f2e69a470c67810c95a1be71a48a819..2df492e507bdcd5ea0b7757370201b18a997206c 100644 (file)
@@ -23,7 +23,7 @@
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
 use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
 use super::{ObjectCastObligation, Obligation};
-use super::ProjectionMode;
+use super::Reveal;
 use super::TraitNotObjectSafe;
 use super::Selection;
 use super::SelectionResult;
@@ -343,7 +343,7 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
         self.infcx
     }
 
-    pub fn projection_mode(&self) -> ProjectionMode {
+    pub fn projection_mode(&self) -> Reveal {
         self.infcx.projection_mode()
     }
 
@@ -1158,20 +1158,17 @@ fn assemble_candidates_from_projected_tys(&mut self,
 
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
-        let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty {
-            ty::TyProjection(ref data) => data.trait_ref.def_id,
+        match obligation.predicate.0.trait_ref.self_ty().sty {
+            ty::TyProjection(_) | ty::TyAnon(..) => {}
             ty::TyInfer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
                     "Self=_ should have been handled by assemble_candidates");
             }
-            _ => { return; }
-        };
-
-        debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}",
-               trait_def_id);
+            _ => return
+        }
 
         let result = self.probe(|this, snapshot| {
-            this.match_projection_obligation_against_bounds_from_trait(obligation,
+            this.match_projection_obligation_against_definition_bounds(obligation,
                                                                        snapshot)
         });
 
@@ -1180,7 +1177,7 @@ fn assemble_candidates_from_projected_tys(&mut self,
         }
     }
 
-    fn match_projection_obligation_against_bounds_from_trait(
+    fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
         snapshot: &infer::CombinedSnapshot)
@@ -1190,28 +1187,29 @@ fn match_projection_obligation_against_bounds_from_trait(
             self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
         let (skol_trait_predicate, skol_map) =
             self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        debug!("match_projection_obligation_against_definition_bounds: \
                 skol_trait_predicate={:?} skol_map={:?}",
                skol_trait_predicate,
                skol_map);
 
-        let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
-            ty::TyProjection(ref data) => &data.trait_ref,
+        let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
+            ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
+            ty::TyAnon(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
-                    "match_projection_obligation_against_bounds_from_trait() called \
+                    "match_projection_obligation_against_definition_bounds() called \
                      but self-ty not a projection: {:?}",
                     skol_trait_predicate.trait_ref.self_ty());
             }
         };
-        debug!("match_projection_obligation_against_bounds_from_trait: \
-                projection_trait_ref={:?}",
-               projection_trait_ref);
+        debug!("match_projection_obligation_against_definition_bounds: \
+                def_id={:?}, substs={:?}",
+               def_id, substs);
 
-        let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id);
-        let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        let item_predicates = self.tcx().lookup_predicates(def_id);
+        let bounds = item_predicates.instantiate(self.tcx(), substs);
+        debug!("match_projection_obligation_against_definition_bounds: \
                 bounds={:?}",
                bounds);
 
@@ -1226,7 +1224,7 @@ fn match_projection_obligation_against_bounds_from_trait(
                                                     &skol_map,
                                                     snapshot)));
 
-        debug!("match_projection_obligation_against_bounds_from_trait: \
+        debug!("match_projection_obligation_against_definition_bounds: \
                 matching_bound={:?}",
                matching_bound);
         match matching_bound {
@@ -1472,7 +1470,8 @@ fn assemble_candidates_from_default_impls(&mut self,
                     }
                 }
                 ty::TyParam(..) |
-                ty::TyProjection(..) => {
+                ty::TyProjection(..) |
+                ty::TyAnon(..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -1796,7 +1795,7 @@ fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 }))
             }
 
-            ty::TyProjection(_) | ty::TyParam(_) => None,
+            ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
             ty::TyInfer(ty::TyVar(_)) => Ambiguous,
 
             ty::TyInfer(ty::FreshTy(_))
@@ -1842,7 +1841,8 @@ fn copy_conditions(&mut self, obligation: &TraitObligation<'tcx>)
                 Where(ty::Binder(tys.to_vec()))
             }
 
-            ty::TyStruct(..) | ty::TyEnum(..) | ty::TyProjection(..) | ty::TyParam(..) => {
+            ty::TyStruct(..) | ty::TyEnum(..) |
+            ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -1893,6 +1893,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             ty::TyTrait(..) |
             ty::TyParam(..) |
             ty::TyProjection(..) |
+            ty::TyAnon(..) |
             ty::TyInfer(ty::TyVar(_)) |
             ty::TyInfer(ty::FreshTy(_)) |
             ty::TyInfer(ty::FreshIntTy(_)) |
@@ -2073,7 +2074,7 @@ fn confirm_projection_candidate(&mut self,
     {
         self.in_snapshot(|this, snapshot| {
             let result =
-                this.match_projection_obligation_against_bounds_from_trait(obligation,
+                this.match_projection_obligation_against_definition_bounds(obligation,
                                                                            snapshot);
             assert!(result);
         })
@@ -2127,7 +2128,7 @@ fn confirm_builtin_candidate(&mut self,
                           obligation)
             };
 
-            let cause = self.derived_cause(obligation, BuiltinDerivedObligation);
+            let cause = obligation.derived_cause(BuiltinDerivedObligation);
             self.collect_predicates_for_types(cause,
                                               obligation.recursion_depth+1,
                                               trait_def,
@@ -2207,7 +2208,7 @@ fn vtable_default_impl(&mut self,
     {
         debug!("vtable_default_impl: nested={:?}", nested);
 
-        let cause = self.derived_cause(obligation, BuiltinDerivedObligation);
+        let cause = obligation.derived_cause(BuiltinDerivedObligation);
         let mut obligations = self.collect_predicates_for_types(
             cause,
             obligation.recursion_depth+1,
@@ -2218,7 +2219,7 @@ fn vtable_default_impl(&mut self,
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let (trait_ref, skol_map) =
                 this.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot);
-            let cause = this.derived_cause(obligation, ImplDerivedObligation);
+            let cause = obligation.derived_cause(ImplDerivedObligation);
             this.impl_or_trait_obligations(cause,
                                            obligation.recursion_depth + 1,
                                            trait_def_id,
@@ -2253,7 +2254,7 @@ fn confirm_impl_candidate(&mut self,
                 this.rematch_impl(impl_def_id, obligation,
                                   snapshot);
             debug!("confirm_impl_candidate substs={:?}", substs);
-            let cause = this.derived_cause(obligation, ImplDerivedObligation);
+            let cause = obligation.derived_cause(ImplDerivedObligation);
             this.vtable_impl(impl_def_id, substs, cause,
                              obligation.recursion_depth + 1,
                              skol_map, snapshot)
@@ -2906,12 +2907,13 @@ fn impl_or_trait_obligations(&mut self,
             }).collect();
         self.infcx().plug_leaks(skol_map, snapshot, &predicates)
     }
+}
 
+impl<'tcx> TraitObligation<'tcx> {
     #[allow(unused_comparisons)]
-    fn derived_cause(&self,
-                     obligation: &TraitObligation<'tcx>,
-                     variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
-                     -> ObligationCause<'tcx>
+    pub fn derived_cause(&self,
+                        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
+                        -> ObligationCause<'tcx>
     {
         /*!
          * Creates a cause for obligations that are derived from
@@ -2923,6 +2925,8 @@ fn derived_cause(&self,
          * reporting.
          */
 
+        let obligation = self;
+
         // NOTE(flaper87): As of now, it keeps track of the whole error
         // chain. Ideally, we should have a way to configure this either
         // by using -Z verbose or just a CLI argument.
index 9348def1311eb01de1616d24878b3e00769a3c25..38cccb9753df60ba69e80e83586a84656c06a534 100644 (file)
@@ -25,7 +25,7 @@
 use infer::{InferCtxt, TypeOrigin};
 use middle::region;
 use ty::subst::{Subst, Substs};
-use traits::{self, ProjectionMode, ObligationCause, Normalized};
+use traits::{self, Reveal, ObligationCause, Normalized};
 use ty::{self, TyCtxt};
 use syntax_pos::DUMMY_SP;
 
@@ -151,7 +151,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              .unwrap()
                              .subst(tcx, &penv.free_substs);
 
-    let result = tcx.normalizing_infer_ctxt(ProjectionMode::Topmost).enter(|mut infcx| {
+    let result = tcx.normalizing_infer_ctxt(Reveal::ExactMatch).enter(|mut infcx| {
         // Normalize the trait reference, adding any obligations
         // that arise into the impl1 assumptions.
         let Normalized { value: impl1_trait_ref, obligations: normalization_obligations } = {
index ae7deb48f8677900ab93a6558bd20a0b29fa093a..a47cd23c64aa6f7145868c142a50f6af542b8a8f 100644 (file)
@@ -14,7 +14,7 @@
 use super::{OverlapError, specializes};
 
 use hir::def_id::DefId;
-use traits::{self, ProjectionMode};
+use traits::{self, Reveal};
 use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable};
 use ty::fast_reject::{self, SimplifiedType};
 use syntax::ast::Name;
@@ -111,8 +111,7 @@ fn insert(&mut self,
             let possible_sibling = *slot;
 
             let tcx = tcx.global_tcx();
-            let (le, ge) = tcx.infer_ctxt(None, None,
-                                          ProjectionMode::Topmost).enter(|infcx| {
+            let (le, ge) = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| {
                 let overlap = traits::overlapping_impls(&infcx,
                                                         possible_sibling,
                                                         impl_def_id);
index e210d2da94cfd4db09435da2ae56025172f31c4b..022566642f646720f467a417e9349fc43a6d010c 100644 (file)
@@ -14,6 +14,7 @@
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 
 use std::fmt;
+use std::rc::Rc;
 
 // structural impls for the structs in traits
 
@@ -162,6 +163,86 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
+    type Lifted = traits::ObligationCauseCode<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            super::MiscObligation => Some(super::MiscObligation),
+            super::SliceOrArrayElem => Some(super::SliceOrArrayElem),
+            super::TupleElem => Some(super::TupleElem),
+            super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
+            super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
+            super::ReferenceOutlivesReferent(ty) => {
+                tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
+            }
+            super::ObjectCastObligation(ty) => {
+                tcx.lift(&ty).map(super::ObjectCastObligation)
+            }
+            super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
+            super::StructInitializerSized => Some(super::StructInitializerSized),
+            super::VariableType(id) => Some(super::VariableType(id)),
+            super::ReturnType => Some(super::ReturnType),
+            super::RepeatVec => Some(super::RepeatVec),
+            super::ClosureCapture(node_id, span, bound) => {
+                Some(super::ClosureCapture(node_id, span, bound))
+            }
+            super::FieldSized => Some(super::FieldSized),
+            super::ConstSized => Some(super::ConstSized),
+            super::SharedStatic => Some(super::SharedStatic),
+            super::BuiltinDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::BuiltinDerivedObligation)
+            }
+            super::ImplDerivedObligation(ref cause) => {
+                tcx.lift(cause).map(super::ImplDerivedObligation)
+            }
+            super::CompareImplMethodObligation => {
+                Some(super::CompareImplMethodObligation)
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
+    type Lifted = traits::DerivedObligationCause<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
+            tcx.lift(&*self.parent_code).map(|code| {
+                traits::DerivedObligationCause {
+                    parent_trait_ref: trait_ref,
+                    parent_code: Rc::new(code)
+                }
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCause<'a> {
+    type Lifted = traits::ObligationCause<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.code).map(|code| {
+            traits::ObligationCause {
+                span: self.span,
+                body_id: self.body_id,
+                code: code,
+            }
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for traits::DeferredObligation<'a> {
+    type Lifted = traits::DeferredObligation<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.predicate).and_then(|predicate| {
+            tcx.lift(&self.cause).map(|cause| {
+                traits::DeferredObligation {
+                    predicate: predicate,
+                    cause: cause
+                }
+            })
+        })
+    }
+}
+
 // For trans only.
 impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> {
     type Lifted = traits::Vtable<'tcx, ()>;
@@ -361,3 +442,103 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         self.value.visit_with(visitor) || self.obligations.visit_with(visitor)
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match *self {
+            super::MiscObligation |
+            super::SliceOrArrayElem |
+            super::TupleElem |
+            super::ItemObligation(_) |
+            super::AssignmentLhsSized |
+            super::StructInitializerSized |
+            super::VariableType(_) |
+            super::ReturnType |
+            super::RepeatVec |
+            super::ClosureCapture(..) |
+            super::FieldSized |
+            super::ConstSized |
+            super::SharedStatic |
+            super::CompareImplMethodObligation => self.clone(),
+
+            super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)),
+            super::ReferenceOutlivesReferent(ty) => {
+                super::ReferenceOutlivesReferent(ty.fold_with(folder))
+            }
+            super::ObjectCastObligation(ty) => {
+                super::ObjectCastObligation(ty.fold_with(folder))
+            }
+            super::BuiltinDerivedObligation(ref cause) => {
+                super::BuiltinDerivedObligation(cause.fold_with(folder))
+            }
+            super::ImplDerivedObligation(ref cause) => {
+                super::ImplDerivedObligation(cause.fold_with(folder))
+            }
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            super::MiscObligation |
+            super::SliceOrArrayElem |
+            super::TupleElem |
+            super::ItemObligation(_) |
+            super::AssignmentLhsSized |
+            super::StructInitializerSized |
+            super::VariableType(_) |
+            super::ReturnType |
+            super::RepeatVec |
+            super::ClosureCapture(..) |
+            super::FieldSized |
+            super::ConstSized |
+            super::SharedStatic |
+            super::CompareImplMethodObligation => false,
+
+            super::ProjectionWf(proj) => proj.visit_with(visitor),
+            super::ReferenceOutlivesReferent(ty) => ty.visit_with(visitor),
+            super::ObjectCastObligation(ty) => ty.visit_with(visitor),
+            super::BuiltinDerivedObligation(ref cause) => cause.visit_with(visitor),
+            super::ImplDerivedObligation(ref cause) => cause.visit_with(visitor)
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::DerivedObligationCause<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        traits::DerivedObligationCause {
+            parent_trait_ref: self.parent_trait_ref.fold_with(folder),
+            parent_code: self.parent_code.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.parent_trait_ref.visit_with(visitor) || self.parent_code.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCause<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        traits::ObligationCause {
+            span: self.span,
+            body_id: self.body_id,
+            code: self.code.fold_with(folder),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.code.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for traits::DeferredObligation<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        traits::DeferredObligation {
+            predicate: self.predicate.fold_with(folder),
+            cause: self.cause.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.predicate.visit_with(visitor) || self.cause.visit_with(visitor)
+    }
+}
index 14b0a8070983c84a3628b665e1d07648689768ea..8da7568c558a70b6d16b7fbcc8854122fd02c983 100644 (file)
@@ -240,7 +240,8 @@ fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
 
                 ty::TyProjection(..) |
-                ty::TyParam(_) => {
+                ty::TyParam(_) |
+                ty::TyAnon(..) => {
                     TC::All
                 }
 
index 5444dd9476120ed2f8cb01418c7bb14b81afb83c..13401e91265eb9ac8db3f4ae39490b01ec67d0fd 100644 (file)
@@ -14,6 +14,7 @@
 use session::Session;
 use middle;
 use middle::cstore::LOCAL_CRATE;
+use hir::TraitMap;
 use hir::def::DefMap;
 use hir::def_id::{DefId, DefIndex};
 use hir::map as ast_map;
@@ -299,8 +300,16 @@ pub struct GlobalCtxt<'tcx> {
     pub types: CommonTypes<'tcx>,
 
     pub sess: &'tcx Session,
+
+    /// Map from path id to the results from resolve; generated
+    /// initially by resolve and updated during typeck in some cases
+    /// (e.g., UFCS paths)
     pub def_map: RefCell<DefMap>,
 
+    /// Map indicating what traits are in scope for places where this
+    /// is relevant; generated by resolve.
+    pub trait_map: TraitMap,
+
     pub named_region_map: resolve_lifetime::NamedRegionMap,
 
     pub region_maps: RegionMaps,
@@ -525,7 +534,7 @@ pub fn def_index_for_def_key(self, krate: ast::CrateNum, key: DefKey)
     }
 
     pub fn retrace_path(self, path: &DefPath) -> Option<DefId> {
-        debug!("retrace_path(path={:?})", path);
+        debug!("retrace_path(path={:?}, krate={:?})", path, self.crate_name(path.krate));
 
         let root_key = DefKey {
             parent: None,
@@ -666,6 +675,7 @@ fn is_global(self) -> bool {
     pub fn create_and_enter<F, R>(s: &'tcx Session,
                                   arenas: &'tcx CtxtArenas<'tcx>,
                                   def_map: DefMap,
+                                  trait_map: TraitMap,
                                   named_region_map: resolve_lifetime::NamedRegionMap,
                                   map: ast_map::Map<'tcx>,
                                   freevars: FreevarMap,
@@ -694,6 +704,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             variance_computed: Cell::new(false),
             sess: s,
             def_map: RefCell::new(def_map),
+            trait_map: trait_map,
             tables: RefCell::new(Tables::empty()),
             impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
@@ -1005,7 +1016,7 @@ pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
             TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
-            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
+            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
@@ -1344,6 +1355,10 @@ pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
         self.mk_param(def.space, def.index, def.name)
     }
 
+    pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyAnon(def_id, substs))
+    }
+
     pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> {
         self.trait_items_cache.memoize(trait_did, || {
             let def_ids = self.trait_item_def_ids(trait_did);
index bddc2dbdb7e779e63c6237837ecda20a86ce89cf..66165ec6ff7d06aa179c4c7c5279aa4daadd51ae 100644 (file)
@@ -247,6 +247,7 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
                     "type parameter".to_string()
                 }
             }
+            ty::TyAnon(..) => "anonymized type".to_string(),
             ty::TyError => "type error".to_string(),
         }
     }
index 25f3552b565e720cccd1a0ec86b9bda1b759d1b2..e6f2ba8b650f1c77851ceb6c3eeaaeee93489295 100644 (file)
@@ -30,6 +30,7 @@ pub enum SimplifiedType {
     TraitSimplifiedType(DefId),
     StructSimplifiedType(DefId),
     ClosureSimplifiedType(DefId),
+    AnonSimplifiedType(DefId),
     FunctionSimplifiedType(usize),
     ParameterSimplifiedType,
 }
@@ -98,6 +99,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 None
             }
         }
+        ty::TyAnon(def_id, _) => {
+            Some(AnonSimplifiedType(def_id))
+        }
         ty::TyInfer(_) | ty::TyError => None,
     }
 }
index 44b450784ed2a9c51e87cb1b6d891cbd7cecb234..85b7d66a2eb085e8a1740d66d87387479277f602 100644 (file)
@@ -110,6 +110,11 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_projection_ty(data);
             }
 
+            &ty::TyAnon(_, substs) => {
+                self.add_flags(TypeFlags::HAS_PROJECTION);
+                self.add_substs(substs);
+            }
+
             &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
                 computation.add_substs(principal.0.substs);
index b334964bf489b4e4fac8e9e533e4fc771b887b88..3580013c2a9129aa973bf308a31b5bded98fb2a2 100644 (file)
@@ -695,7 +695,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         // in the normalized form
         if self.just_constrained {
             match t.sty {
-                ty::TyProjection(..) => { return false; }
+                ty::TyProjection(..) | ty::TyAnon(..) => { return false; }
                 _ => { }
             }
         }
index 74c05feb6d16a5822464da1319f591f3b8d62b69..bfe6303d8a328a7bf8793d78a0c9a95853475a72 100644 (file)
@@ -188,7 +188,8 @@ pub fn push_item_path<T>(self, buffer: &mut T, def_id: DefId)
             data @ DefPathData::Initializer |
             data @ DefPathData::MacroDef(..) |
             data @ DefPathData::ClosureExpr |
-            data @ DefPathData::Binding(..) => {
+            data @ DefPathData::Binding(..) |
+            data @ DefPathData::ImplTrait => {
                 let parent_def_id = self.parent_def_id(def_id).unwrap();
                 self.push_item_path(buffer, parent_def_id);
                 buffer.push(&data.as_interned_str());
@@ -345,6 +346,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         ty::TyFnPtr(_) |
         ty::TyProjection(_) |
         ty::TyParam(_) |
+        ty::TyAnon(..) |
         ty::TyInfer(_) |
         ty::TyError |
         ty::TyFloat(_) => None,
index 88327ab19a5cb66350a06e707fa9954766d62b55..634599406afb2fc49627a734559fccb5e0c4abc1 100644 (file)
@@ -52,8 +52,10 @@ pub fn get(&self, dep_node: DepNode<DefId>) -> Option<Ty<'tcx>> {
         self.untracked_get()
     }
 
+    /// Reads the ivar without registered a dep-graph read. Use with
+    /// caution.
     #[inline]
-    fn untracked_get(&self) -> Option<Ty<'tcx>> {
+    pub fn untracked_get(&self) -> Option<Ty<'tcx>> {
         match self.0.get() {
             None => None,
             // valid because of invariant (A)
index 27ed88e929e76dba833a9702e52d896b03072391..d73e412f55f267c7b1e40d5c18ccb5890aa209ff 100644 (file)
@@ -558,8 +558,7 @@ pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
             (&Univariant { non_zero: true, .. }, &ty::TyStruct(def, substs)) => {
                 let fields = &def.struct_variant().fields;
                 assert_eq!(fields.len(), 1);
-                let ty = normalize_associated_type(infcx, fields[0].ty(tcx, substs));
-                match *ty.layout(infcx)? {
+                match *fields[0].ty(tcx, substs).layout(infcx)? {
                     // FIXME(eddyb) also allow floating-point types here.
                     Scalar { value: Int(_), non_zero: false } |
                     Scalar { value: Pointer, non_zero: false } => {
@@ -577,7 +576,7 @@ pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
             (_, &ty::TyStruct(def, substs)) => {
                 Struct::non_zero_field_path(infcx, def.struct_variant().fields
                                                       .iter().map(|field| {
-                    normalize_associated_type(infcx, field.ty(tcx, substs))
+                    field.ty(tcx, substs)
                 }))
             }
 
@@ -595,6 +594,14 @@ pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                 Struct::non_zero_field_path(infcx, Some(ety).into_iter())
             }
 
+            (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
+                let normalized = normalize_associated_type(infcx, ty);
+                if ty == normalized {
+                    return Ok(None);
+                }
+                return Struct::non_zero_field_in_type(infcx, normalized);
+            }
+
             // Anything else is not a non-zero type.
             _ => Ok(None)
         }
@@ -762,8 +769,9 @@ fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
 impl<'a, 'gcx, 'tcx> Layout {
     pub fn compute_uncached(ty: Ty<'gcx>,
                             infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                            -> Result<Layout, LayoutError<'gcx>> {
+                            -> Result<&'gcx Layout, LayoutError<'gcx>> {
         let tcx = infcx.tcx.global_tcx();
+        let success = |layout| Ok(tcx.intern_layout(layout));
         let dl = &tcx.data_layout;
         assert!(!ty.has_infer_types());
 
@@ -795,6 +803,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
                     Scalar { value: Pointer, non_zero: non_zero }
                 } else {
+                    let pointee = normalize_associated_type(infcx, pointee);
                     let unsized_part = tcx.struct_tail(pointee);
                     let meta = match unsized_part.sty {
                         ty::TySlice(_) | ty::TyStr => {
@@ -860,7 +869,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     let element = ty.simd_type(tcx);
                     match *element.layout(infcx)? {
                         Scalar { value, .. } => {
-                            return Ok(Vector {
+                            return success(Vector {
                                 element: value,
                                 count: ty.simd_size(tcx) as u64
                             });
@@ -873,8 +882,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     }
                 }
                 let fields = def.struct_variant().fields.iter().map(|field| {
-                    normalize_associated_type(infcx, field.ty(tcx, substs))
-                        .layout(infcx)
+                    field.ty(tcx, substs).layout(infcx)
                 });
                 let packed = tcx.lookup_packed(def.did);
                 let mut st = Struct::new(dl, packed);
@@ -914,7 +922,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
 
                     let mut st = Struct::new(dl, false);
                     st.extend(dl, drop_flag.iter().map(Ok), ty)?;
-                    return Ok(Univariant { variant: st, non_zero: false });
+                    return success(Univariant { variant: st, non_zero: false });
                 }
 
                 if !dtor && def.variants.iter().all(|v| v.fields.is_empty()) {
@@ -927,7 +935,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     }
 
                     let (discr, signed) = Integer::repr_discr(tcx, hint, min, max);
-                    return Ok(CEnum {
+                    return success(CEnum {
                         discr: discr,
                         signed: signed,
                         min: min as u64,
@@ -950,19 +958,16 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     // (Typechecking will reject discriminant-sizing attrs.)
                     assert_eq!(hint, attr::ReprAny);
                     let fields = def.variants[0].fields.iter().map(|field| {
-                        normalize_associated_type(infcx, field.ty(tcx, substs))
-                            .layout(infcx)
+                        field.ty(tcx, substs).layout(infcx)
                     });
                     let mut st = Struct::new(dl, false);
                     st.extend(dl, fields.chain(drop_flag.iter().map(Ok)), ty)?;
-                    return Ok(Univariant { variant: st, non_zero: false });
+                    return success(Univariant { variant: st, non_zero: false });
                 }
 
                 // Cache the substituted and normalized variant field types.
                 let variants = def.variants.iter().map(|v| {
-                    v.fields.iter().map(|field| {
-                        normalize_associated_type(infcx, field.ty(tcx, substs))
-                    }).collect::<Vec<_>>()
+                    v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
                 }).collect::<Vec<_>>();
 
                 if !dtor && variants.len() == 2 && hint == attr::ReprAny {
@@ -982,7 +987,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         if path == &[0] && variants[discr].len() == 1 {
                             match *variants[discr][0].layout(infcx)? {
                                 Scalar { value, .. } => {
-                                    return Ok(RawNullablePointer {
+                                    return success(RawNullablePointer {
                                         nndiscr: discr as u64,
                                         value: value
                                     });
@@ -998,10 +1003,8 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         path.push(0); // For GEP through a pointer.
                         path.reverse();
                         let mut st = Struct::new(dl, false);
-                        st.extend(dl, variants[discr].iter().map(|ty| {
-                            ty.layout(infcx)
-                        }), ty)?;
-                        return Ok(StructWrappedNullablePointer {
+                        st.extend(dl, variants[discr].iter().map(|ty| ty.layout(infcx)), ty)?;
+                        return success(StructWrappedNullablePointer {
                             nndiscr: discr as u64,
                             nonnull: st,
                             discrfield: path
@@ -1105,7 +1108,14 @@ pub fn compute_uncached(ty: Ty<'gcx>,
             }
 
             // Types with no meaningful known layout.
-            ty::TyProjection(_) | ty::TyParam(_) => {
+            ty::TyProjection(_) | ty::TyAnon(..) => {
+                let normalized = normalize_associated_type(infcx, ty);
+                if ty == normalized {
+                    return Err(LayoutError::Unknown(ty));
+                }
+                return normalized.layout(infcx);
+            }
+            ty::TyParam(_) => {
                 return Err(LayoutError::Unknown(ty));
             }
             ty::TyInfer(_) | ty::TyError => {
@@ -1113,7 +1123,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
             }
         };
 
-        Ok(layout)
+        success(layout)
     }
 
     /// Returns true if the layout corresponds to an unsized type.
@@ -1272,8 +1282,7 @@ pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
                 // Get a zero-sized variant or a pointer newtype.
                 let zero_or_ptr_variant = |i: usize| {
                     let fields = def.variants[i].fields.iter().map(|field| {
-                        let ty = normalize_associated_type(infcx, &field.ty(tcx, substs));
-                        SizeSkeleton::compute(ty, infcx)
+                        SizeSkeleton::compute(field.ty(tcx, substs), infcx)
                     });
                     let mut ptr = None;
                     for field in fields {
@@ -1323,6 +1332,15 @@ pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
                 }
             }
 
+            ty::TyProjection(_) | ty::TyAnon(..) => {
+                let normalized = normalize_associated_type(infcx, ty);
+                if ty == normalized {
+                    Err(err)
+                } else {
+                    SizeSkeleton::compute(normalized, infcx)
+                }
+            }
+
             _ => Err(err)
         }
     }
index 03e893727d1b58c7d88142ee72bb336dfe509cfd..8e89b3c60879f4555d8f95d57493e61b44d2d38a 100644 (file)
@@ -1404,9 +1404,13 @@ pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     }
                 }
             }
-            Some(ast_map::NodeExpr(..)) => {
+            Some(ast_map::NodeExpr(expr)) => {
                 // This is a convenience to allow closures to work.
-                ParameterEnvironment::for_item(tcx, tcx.map.get_parent(id))
+                if let hir::ExprClosure(..) = expr.node {
+                    ParameterEnvironment::for_item(tcx, tcx.map.get_parent(id))
+                } else {
+                    tcx.empty_parameter_environment()
+                }
             }
             Some(ast_map::NodeForeignItem(item)) => {
                 let def_id = tcx.map.local_def_id(id);
@@ -1757,8 +1761,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        let dep_node = DepNode::SizedConstraint(self.did);
-        match self.sized_constraint.get(dep_node) {
+        match self.sized_constraint.get(DepNode::SizedConstraint(self.did)) {
             None => {
                 let global_tcx = tcx.global_tcx();
                 let this = global_tcx.lookup_adt_def_master(self.did);
@@ -1786,12 +1789,18 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     ///       such.
     ///     - a TyError, if a type contained itself. The representability
     ///       check should catch this case.
-    fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn calculate_sized_constraint_inner(&'tcx self,
+                                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         stack: &mut Vec<AdtDefMaster<'tcx>>)
     {
-
         let dep_node = || DepNode::SizedConstraint(self.did);
-        if self.sized_constraint.get(dep_node()).is_some() {
+
+        // Follow the memoization pattern: push the computation of
+        // DepNode::SizedConstraint as our current task.
+        let _task = tcx.dep_graph.in_task(dep_node());
+        if self.sized_constraint.untracked_get().is_some() {
+            //                   ---------------
+            // can skip the dep-graph read since we just pushed the task
             return;
         }
 
@@ -1880,7 +1889,7 @@ fn sized_constraint_for_ty(
                 }
             }
 
-            TyProjection(..) => {
+            TyProjection(..) | TyAnon(..) => {
                 // must calculate explicitly.
                 // FIXME: consider special-casing always-Sized projections
                 vec![ty]
index 9ae3325c2588f5f7749206f780b1be0a72b609ed..df907c26f71420b3e091c36ab02c96d5e5df394a 100644 (file)
@@ -174,6 +174,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
             ty::TyEnum(..) |        // OutlivesNominalType
             ty::TyStruct(..) |      // OutlivesNominalType
             ty::TyBox(..) |         // OutlivesNominalType (ish)
+            ty::TyAnon(..) |        // OutlivesNominalType (ish)
             ty::TyStr |             // OutlivesScalar (ish)
             ty::TyArray(..) |       // ...
             ty::TySlice(..) |       // ...
index 80c727f022127745809e6e299b2725486a76d0fb..f9263947c0379c099562fc55c35046ffc025dd0e 100644 (file)
@@ -582,6 +582,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name))
         }
 
+        (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs))
+            if a_def_id == b_def_id =>
+        {
+            let substs = relate_substs(relation, None, a_substs, b_substs)?;
+            Ok(tcx.mk_anon(a_def_id, substs))
+        }
+
         _ =>
         {
             Err(TypeError::Sorts(expected_found(relation, &a, &b)))
index 16a54c20925deda7b8417a3747be29e6e0289bec..8c10806fda768a46c0e31a9103470d5273f939e5 100644 (file)
@@ -115,16 +115,26 @@ fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lif
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> {
+    type Lifted = ty::ProjectionTy<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
+                             -> Option<ty::ProjectionTy<'tcx>> {
+        tcx.lift(&self.trait_ref).map(|trait_ref| {
+            ty::ProjectionTy {
+                trait_ref: trait_ref,
+                item_name: self.item_name
+            }
+        })
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
     type Lifted = ty::ProjectionPredicate<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
                              -> Option<ty::ProjectionPredicate<'tcx>> {
-        tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| {
+        tcx.lift(&(self.projection_ty, self.ty)).map(|(projection_ty, ty)| {
             ty::ProjectionPredicate {
-                projection_ty: ty::ProjectionTy {
-                    trait_ref: trait_ref,
-                    item_name: self.projection_ty.item_name
-                },
+                projection_ty: projection_ty,
                 ty: ty
             }
         })
@@ -485,6 +495,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)),
             ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)),
             ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
+            ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
             ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
             ty::TyParam(..) => self.sty.clone(),
@@ -513,6 +524,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
             ty::TyProjection(ref data) => data.visit_with(visitor),
+            ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
             ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
             ty::TyParam(..) => false,
index 7c69618068a6b7c89597d3ae6cf23270d622e693..912cb39face0a6d9ec910ce33194618826999551 100644 (file)
@@ -166,6 +166,12 @@ pub enum TypeVariants<'tcx> {
     /// `<T as Trait<..>>::N`.
     TyProjection(ProjectionTy<'tcx>),
 
+    /// Anonymized (`impl Trait`) type found in a return type.
+    /// The DefId comes from the `impl Trait` ast::Ty node, and the
+    /// substitutions are for the generics of the function in question.
+    /// After typeck, the concrete type can be found in the `tcache` map.
+    TyAnon(DefId, &'tcx Substs<'tcx>),
+
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
     TyParam(ParamTy),
 
@@ -1232,7 +1238,8 @@ pub fn regions(&self) -> Vec<ty::Region> {
                 v
             }
             TyEnum(_, substs) |
-            TyStruct(_, substs) => {
+            TyStruct(_, substs) |
+            TyAnon(_, substs) => {
                 substs.regions.as_slice().to_vec()
             }
             TyClosure(_, ref substs) => {
index d9ffe36ea47fbe3610cb927d346cdf4d7a3008d0..e7bcfbfd823453dd2893fae3044744e7a8ee4b5c 100644 (file)
@@ -14,7 +14,7 @@
 use ty::subst;
 use infer::InferCtxt;
 use hir::pat_util;
-use traits::{self, ProjectionMode};
+use traits::{self, Reveal};
 use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
 use ty::{Disr, ParameterEnvironment};
 use ty::fold::TypeVisitor;
@@ -137,8 +137,7 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        self_type: Ty<'tcx>, span: Span)
                                        -> Result<(),CopyImplementationError> {
         // FIXME: (@jroesch) float this code up
-        tcx.infer_ctxt(None, Some(self.clone()),
-                       ProjectionMode::Topmost).enter(|infcx| {
+        tcx.infer_ctxt(None, Some(self.clone()), Reveal::ExactMatch).enter(|infcx| {
             let adt = match self_type.sty {
                 ty::TyStruct(struct_def, substs) => {
                     for field in struct_def.all_fields() {
@@ -438,6 +437,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyRawPtr(m) |
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
+            TyAnon(def_id, _) |
             TyFnDef(def_id, _, _) => self.def_id(def_id),
             TyFnPtr(f) => {
                 self.hash(f.unsafety);
@@ -533,7 +533,7 @@ fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    param_env: &ParameterEnvironment<'tcx>,
                    bound: ty::BuiltinBound, span: Span) -> bool
     {
-        tcx.infer_ctxt(None, Some(param_env.clone()), ProjectionMode::Topmost).enter(|infcx| {
+        tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch).enter(|infcx| {
             traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span)
         })
     }
@@ -560,7 +560,7 @@ pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }) => Some(true),
 
             TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
-            TyClosure(..) | TyEnum(..) | TyStruct(..) |
+            TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) |
             TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
         }.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span));
 
@@ -601,7 +601,7 @@ fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             TyStr | TyTrait(..) | TySlice(_) => Some(false),
 
             TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
-            TyInfer(..) | TyError => None
+            TyInfer(..) | TyAnon(..) | TyError => None
         }.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span));
 
         if !self.has_param_types() && !self.has_self_ty() {
@@ -627,7 +627,6 @@ pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
         }
 
         let layout = Layout::compute_uncached(self, infcx)?;
-        let layout = tcx.intern_layout(layout);
         if can_cache {
             tcx.layout_cache.borrow_mut().insert(self, layout);
         }
index fa7c9b782311f955a1c4c637586c13c77be2f05e..ebc2642678bfd80bb3b9d0a794dd0704dc88c263 100644 (file)
@@ -88,7 +88,8 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
             }).collect::<Vec<_>>());
         }
         ty::TyEnum(_, ref substs) |
-        ty::TyStruct(_, ref substs) => {
+        ty::TyStruct(_, ref substs) |
+        ty::TyAnon(_, ref substs) => {
             push_reversed(stack, substs.types.as_slice());
         }
         ty::TyClosure(_, ref substs) => {
index 37ba936d2f42a73f71a6e3193cdfbf183345d6e5..f6ddfe60d40e6804c7ffee6f72b0276a303bcbe6 100644 (file)
@@ -383,6 +383,12 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     // types appearing in the fn signature
                 }
 
+                ty::TyAnon(..) => {
+                    // all of the requirements on type parameters
+                    // should've been checked by the instantiation
+                    // of whatever returned this exact `impl Trait`.
+                }
+
                 ty::TyTrait(ref data) => {
                     // WfObject
                     //
index 60977a80946ff6e23950ef024d739eb4764a45a1..a17c01068139a376cd6c5b1aaa83d1a16e1fb57a 100644 (file)
@@ -907,6 +907,37 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             }
             TyTrait(ref data) => write!(f, "{}", data),
             ty::TyProjection(ref data) => write!(f, "{}", data),
+            ty::TyAnon(def_id, substs) => {
+                ty::tls::with(|tcx| {
+                    // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+                    // by looking up the projections associated with the def_id.
+                    let item_predicates = tcx.lookup_predicates(def_id);
+                    let substs = tcx.lift(&substs).unwrap_or_else(|| {
+                        tcx.mk_substs(subst::Substs::empty())
+                    });
+                    let bounds = item_predicates.instantiate(tcx, substs);
+
+                    let mut first = true;
+                    let mut is_sized = false;
+                    write!(f, "impl")?;
+                    for predicate in bounds.predicates.into_vec() {
+                        if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
+                            // Don't print +Sized, but rather +?Sized if absent.
+                            if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
+                                is_sized = true;
+                                continue;
+                            }
+
+                            write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?;
+                            first = false;
+                        }
+                    }
+                    if !is_sized {
+                        write!(f, "{}?Sized", if first { " " } else { "+" })?;
+                    }
+                    Ok(())
+                })
+            }
             TyStr => write!(f, "str"),
             TyClosure(did, substs) => ty::tls::with(|tcx| {
                 write!(f, "[closure")?;
index 3d24fd8ab67e4a2d4b1bd1d1a25ff95f3336933b..18686e3f1d6489e642f0735755485cba953fbe62 100644 (file)
@@ -94,7 +94,7 @@ fn load_specific(target: &str) -> TargetResult {
         pub fn get_targets() -> Box<Iterator<Item=String>> {
             Box::new(TARGETS.iter().filter_map(|t| -> Option<String> {
                 load_specific(t)
-                    .map(|t| t.llvm_target)
+                    .and(Ok(t.to_string()))
                     .ok()
             }))
         }
index 932b748520170ac11c594920a74f047c7eca3345..57b335bd5eee41f5c1d51f8a5fd216366eda5b14 100644 (file)
@@ -442,6 +442,9 @@ fn statement_effect(&self,
         }
         let bits_per_block = self.bits_per_block(ctxt);
         match stmt.kind {
+            repr::StatementKind::SetDiscriminant { .. } => {
+                span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
+            }
             repr::StatementKind::Assign(ref lvalue, _) => {
                 // assigning into this `lvalue` kills all
                 // MoveOuts from it, and *also* all MoveOuts
index d59bdf93f3225e4e33fb32689fd74b172e9aa238..ccde429a17113f8f5e798cb396385a31a141b0d2 100644 (file)
@@ -104,6 +104,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             repr::StatementKind::Assign(ref lvalue, ref rvalue) => {
                 (lvalue, rvalue)
             }
+            repr::StatementKind::SetDiscriminant{ .. } =>
+                span_bug!(stmt.source_info.span,
+                          "sanity_check should run before Deaggregator inserts SetDiscriminant"),
         };
 
         if lvalue == peek_arg_lval {
index 623ea60c5a6d88c508da63434985d1f01ef5ddab..f6e9484eda1a4ca54d363454e2531319a8f83e7c 100644 (file)
@@ -185,7 +185,7 @@ fn path_needs_drop(&self, path: MovePathIndex) -> bool
     {
         match self.move_data().move_paths[path].content {
             MovePathContent::Lvalue(ref lvalue) => {
-                let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+                let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
                 debug!("path_needs_drop({:?}, {:?} : {:?})", path, lvalue, ty);
 
                 self.tcx.type_needs_drop_given_env(ty, self.param_env())
@@ -555,7 +555,7 @@ fn drop_ladder<'a>(&mut self,
 
         let mut fields = fields;
         fields.retain(|&(ref lvalue, _)| {
-            let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+            let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
             self.tcx.type_needs_drop_given_env(ty, self.param_env())
         });
 
@@ -706,7 +706,7 @@ fn open_drop_for_adt<'a>(&mut self, c: &DropCtxt<'a, 'tcx>,
     /// This creates a "drop ladder" that drops the needed fields of the
     /// ADT, both in the success case or if one of the destructors fail.
     fn open_drop<'a>(&mut self, c: &DropCtxt<'a, 'tcx>) -> BasicBlock {
-        let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
+        let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
         match ty.sty {
             ty::TyStruct(def, substs) | ty::TyEnum(def, substs) => {
                 self.open_drop_for_adt(c, def, substs)
@@ -892,7 +892,7 @@ fn must_complete_drop<'a>(&self, c: &DropCtxt<'a, 'tcx>) -> bool {
         // dataflow can create unneeded children in some cases
         // - be sure to ignore them.
 
-        let ty = self.mir.lvalue_ty(self.tcx, c.lvalue).to_ty(self.tcx);
+        let ty = c.lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
 
         match ty.sty {
             ty::TyStruct(def, _) | ty::TyEnum(def, _) => {
index 05412216d487c9e7153b6b2ed9c05d1928cf9c53..e965dcc169c2de9abe6c55eb4ee05020b2c6d3f1 100644 (file)
@@ -616,6 +616,10 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveD
                         Rvalue::InlineAsm { .. } => {}
                     }
                 }
+                StatementKind::SetDiscriminant{ .. } => {
+                    span_bug!(stmt.source_info.span,
+                              "SetDiscriminant should not exist during borrowck");
+                }
             }
         }
 
index 7481b15685e6991c62b185e00be446523a952026..c563fdb8f44e6dd8a18db69f49bcb89914cbbbbe 100644 (file)
@@ -256,7 +256,7 @@ fn move_path_children_matching<'tcx, F>(move_paths: &MovePathData<'tcx>,
 fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                       mir: &Mir<'tcx>,
                                                       lv: &repr::Lvalue<'tcx>) -> bool {
-    let ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
+    let ty = lv.ty(mir, tcx).to_ty(tcx);
     match ty.sty {
         ty::TyArray(..) | ty::TySlice(..) | ty::TyRef(..) | ty::TyRawPtr(..) => {
             debug!("lvalue_contents_drop_state_cannot_differ lv: {:?} ty: {:?} refd => false",
@@ -355,7 +355,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
 
         // don't move out of non-Copy things
         if let MovePathContent::Lvalue(ref lvalue) = move_data.move_paths[path].content {
-            let ty = mir.lvalue_ty(tcx, lvalue).to_ty(tcx);
+            let ty = lvalue.ty(mir, tcx).to_ty(tcx);
             if !ty.moves_by_default(tcx, param_env, DUMMY_SP) {
                 continue;
             }
@@ -369,6 +369,9 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
     let block = &mir[loc.block];
     match block.statements.get(loc.index) {
         Some(stmt) => match stmt.kind {
+            repr::StatementKind::SetDiscriminant{ .. } => {
+                span_bug!(stmt.source_info.span, "SetDiscrimant should not exist during borrowck");
+            }
             repr::StatementKind::Assign(ref lvalue, _) => {
                 debug!("drop_flag_effects: assignment {:?}", stmt);
                  on_all_children_bits(tcx, mir, move_data,
index 9115fd42be870e02aec87792b163d02ca5657720..e0cbd972bd37f9f3c62fc9d65e26b18bb47915af 100644 (file)
@@ -168,8 +168,10 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
                attributes: &[ast::Attribute]) {
     debug!("borrowck_fn(id={})", id);
 
+    let def_id = this.tcx.map.local_def_id(id);
+
     if attributes.iter().any(|item| item.check_name("rustc_mir_borrowck")) {
-        let mir = this.mir_map.unwrap().map.get(&id).unwrap();
+        let mir = this.mir_map.unwrap().map.get(&def_id).unwrap();
         this.with_temp_region_map(id, |this| {
             mir::borrowck_mir(this, fk, decl, mir, body, sp, id, attributes)
         });
@@ -758,12 +760,16 @@ pub fn report_reassigned_immutable_variable(&self,
                                                 lp: &LoanPath<'tcx>,
                                                 assign:
                                                 &move_data::Assignment) {
-        struct_span_err!(
+        let mut err = struct_span_err!(
             self.tcx.sess, span, E0384,
             "re-assignment of immutable variable `{}`",
-            self.loan_path_to_string(lp))
-            .span_note(assign.span, "prior assignment occurs here")
-            .emit();
+            self.loan_path_to_string(lp));
+        err.span_label(span, &format!("re-assignment of immutable variable"));
+        if span != assign.span {
+            err.span_label(assign.span, &format!("first assignment to `{}`",
+                                              self.loan_path_to_string(lp)));
+        }
+        err.emit();
     }
 
     pub fn span_err(&self, s: Span, m: &str) {
index 400ae186010e3fb15d594615c6b5dc4705e9b395..88f739d1c74bb24089ede620f38c6e737430238d 100644 (file)
@@ -17,7 +17,7 @@
 when that data may no longer exist. It's most commonly seen when attempting to
 return a closure:
 
-```compile_fail
+```compile_fail,E0373
 fn foo() -> Box<Fn(u32) -> u32> {
     let x = 0u32;
     Box::new(|y| x + y)
@@ -31,7 +31,7 @@ fn foo() -> Box<Fn(u32) -> u32> {
 
 Another situation where this might be encountered is when spawning threads:
 
-```compile_fail
+```compile_fail,E0373
 fn foo() {
     let x = 0u32;
     let y = 1u32;
@@ -66,7 +66,7 @@ fn foo() -> Box<Fn(u32) -> u32> {
 E0381: r##"
 It is not allowed to use or capture an uninitialized variable. For example:
 
-```compile_fail
+```compile_fail,E0381
 fn main() {
     let x: i32;
     let y = x; // error, use of possibly uninitialized variable
@@ -88,7 +88,7 @@ fn main() {
 This error occurs when an attempt is made to use a variable after its contents
 have been moved elsewhere. For example:
 
-```compile_fail
+```compile_fail,E0382
 struct MyStruct { s: u32 }
 
 fn main() {
@@ -180,8 +180,8 @@ struct Foo {
 This error occurs when an attempt is made to reassign an immutable variable.
 For example:
 
-```compile_fail
-fn main(){
+```compile_fail,E0384
+fn main() {
     let x = 3;
     x = 5; // error, reassignment of immutable variable
 }
@@ -191,7 +191,7 @@ fn main(){
 `mut` after the keyword `let` when declaring the variable. For example:
 
 ```
-fn main(){
+fn main() {
     let mut x = 3;
     x = 5;
 }
@@ -204,7 +204,7 @@ fn main(){
 
 For example, this can happen when storing a `&mut` inside an immutable `Box`:
 
-```compile_fail
+```compile_fail,E0386
 let mut x: i64 = 1;
 let y: Box<_> = Box::new(&mut x);
 **y = 2; // error, cannot assign to data in an immutable container
@@ -234,7 +234,7 @@ fn main(){
 This error occurs when an attempt is made to mutate or mutably reference data
 that a closure has captured immutably. Examples of this error are shown below:
 
-```compile_fail
+```compile_fail,E0387
 // Accepts a function or a closure that captures its environment immutably.
 // Closures passed to foo will not be able to mutate their closed-over state.
 fn foo<F: Fn()>(f: F) { }
@@ -286,6 +286,30 @@ fn mutable() {
 https://doc.rust-lang.org/std/cell/
 "##,
 
+E0388: r##"
+A mutable borrow was attempted in a static location.
+
+Erroneous code example:
+
+```compile_fail,E0388
+static X: i32 = 1;
+
+static STATIC_REF: &'static mut i32 = &mut X;
+// error: cannot borrow data mutably in a static location
+
+const CONST_REF: &'static mut i32 = &mut X;
+// error: cannot borrow data mutably in a static location
+```
+
+To fix this error, you have to use constant borrow:
+
+```
+static X: i32 = 1;
+
+static STATIC_REF: &'static i32 = &X;
+```
+"##,
+
 E0389: r##"
 An attempt was made to mutate data using a non-mutable reference. This
 commonly occurs when attempting to assign to a non-mutable reference of a
@@ -293,9 +317,9 @@ fn mutable() {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0389
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -315,7 +339,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -353,7 +377,7 @@ fn main() {
 E0499: r##"
 A variable was borrowed as mutable more than once. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0499
 let mut i = 0;
 let mut x = &mut i;
 let mut a = &mut i;
@@ -438,7 +462,7 @@ fn you_know_nothing(jon_snow: &mut i32) {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0501
 fn inside_closure(x: &mut i32) {
     // Actions which require unique access
 }
@@ -508,7 +532,7 @@ fn foo(a: &mut i32) {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0502
 fn bar(x: &mut i32) {}
 fn foo(a: &mut i32) {
     let ref y = a; // a is borrowed as immutable.
@@ -537,7 +561,7 @@ fn foo(a: &mut i32) {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0503
 fn main() {
     let mut value = 3;
     // Create a mutable borrow of `value`. This borrow
@@ -594,9 +618,9 @@ fn main() {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0504
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -622,7 +646,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -645,7 +669,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -674,7 +698,7 @@ fn main() {
 use std::thread;
 
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -692,14 +716,94 @@ fn main() {
 ```
 "##,
 
+E0505: r##"
+A value was moved out while it was still borrowed.
+
+Erroneous code example:
+
+```compile_fail,E0505
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(x);
+    }
+}
+```
+
+Here, the function `eat` takes the ownership of `x`. However,
+`x` cannot be moved because it was borrowed to `_ref_to_val`.
+To fix that you can do few different things:
+
+* Try to avoid moving the variable.
+* Release borrow before move.
+* Implement the `Copy` trait on the type.
+
+Examples:
+
+```
+struct Value {}
+
+fn eat(val: &Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(&x); // pass by reference, if it's possible
+    }
+}
+```
+
+Or:
+
+```
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+    }
+    eat(x); // release borrow and then move it.
+}
+```
+
+Or:
+
+```
+#[derive(Clone, Copy)] // implement Copy trait
+struct Value {}
+
+fn eat(val: Value) {}
+
+fn main() {
+    let x = Value{};
+    {
+        let _ref_to_val: &Value = &x;
+        eat(x); // it will be copied here.
+    }
+}
+```
+
+You can find more information about borrowing in the rust-book:
+http://doc.rust-lang.org/stable/book/references-and-borrowing.html
+"##,
+
 E0506: r##"
 This error occurs when an attempt is made to assign to a borrowed value.
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0506
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -719,7 +823,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -736,7 +840,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -757,7 +861,7 @@ fn main() {
 
 ```
 struct FancyNum {
-    num: u8
+    num: u8,
 }
 
 fn main() {
@@ -776,89 +880,10 @@ fn print_fancy_ref(fancy_ref: &FancyNum){
 ```
 "##,
 
-E0505: r##"
-A value was moved out while it was still borrowed.
-Erroneous code example:
-
-```compile_fail
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(x);
-    }
-}
-```
-
-Here, the function `eat` takes the ownership of `x`. However,
-`x` cannot be moved because it was borrowed to `_ref_to_val`.
-To fix that you can do few different things:
-
-* Try to avoid moving the variable.
-* Release borrow before move.
-* Implement the `Copy` trait on the type.
-
-Examples:
-
-```
-struct Value {}
-
-fn eat(val: &Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(&x); // pass by reference, if it's possible
-    }
-}
-```
-
-Or:
-
-```
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-    }
-    eat(x); // release borrow and then move it.
-}
-```
-
-Or:
-
-```
-#[derive(Clone, Copy)] // implement Copy trait
-struct Value {}
-
-fn eat(val: Value) {}
-
-fn main() {
-    let x = Value{};
-    {
-        let _ref_to_val: &Value = &x;
-        eat(x); // it will be copied here.
-    }
-}
-```
-
-You can find more information about borrowing in the rust-book:
-http://doc.rust-lang.org/stable/book/references-and-borrowing.html
-"##,
-
 E0507: r##"
 You tried to move out of a value which was borrowed. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0507
 use std::cell::RefCell;
 
 struct TheDarkKnight;
@@ -975,7 +1000,7 @@ fn main() {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0508
 struct NonCopy;
 
 fn main() {
@@ -1020,7 +1045,7 @@ fn main() {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0509
 struct FancyNum {
     num: usize
 }
@@ -1113,6 +1138,5 @@ fn main() {
 
 register_diagnostics! {
     E0385, // {} in an aliasable location
-    E0388, // {} in a static location
     E0524, // two closures require unique access to `..` at the same time
 }
index 599e3ec871a8327cdcc08f18083a042806bd7945..3e88dec8cb27a0c31e8aec233937be99ead96c62 100644 (file)
@@ -25,7 +25,7 @@
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization::{cmt};
 use rustc::hir::pat_util::*;
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::ty::*;
 use rustc::ty;
 use std::cmp::Ordering;
@@ -235,12 +235,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
                 .flat_map(|arm| &arm.0)
                 .map(|pat| vec![wrap_pat(cx, &pat)])
                 .collect();
-            let match_span = Span {
-                lo: ex.span.lo,
-                hi: scrut.span.hi,
-                expn_id: ex.span.expn_id
-            };
-            check_exhaustive(cx, match_span, &matrix, source);
+            check_exhaustive(cx, scrut.span, &matrix, source);
         },
         _ => ()
     }
@@ -316,7 +311,10 @@ fn check_arms(cx: &MatchCheckCtxt,
                                 let &(ref first_arm_pats, _) = &arms[0];
                                 let first_pat = &first_arm_pats[0];
                                 let span = first_pat.span;
-                                span_err!(cx.tcx.sess, span, E0162, "irrefutable if-let pattern");
+                                struct_span_err!(cx.tcx.sess, span, E0162,
+                                                "irrefutable if-let pattern")
+                                    .span_label(span, &format!("irrefutable pattern"))
+                                    .emit();
                                 printed_if_let_err = true;
                             }
                         },
@@ -1112,9 +1110,15 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
 
         // x @ Foo(..) is legal, but x @ Foo(y) isn't.
         if sub.map_or(false, |p| pat_contains_bindings(&p)) {
-            span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings");
+            struct_span_err!(cx.tcx.sess, p.span, E0007,
+                             "cannot bind by-move with sub-bindings")
+                .span_label(p.span, &format!("binds an already bound by-move value by moving it"))
+                .emit();
         } else if has_guard {
-            span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
+            struct_span_err!(cx.tcx.sess, p.span, E0008,
+                      "cannot bind by-move into a pattern guard")
+                .span_label(p.span, &format!("moves value into pattern guard"))
+                .emit();
         } else if by_ref_span.is_some() {
             let mut err = struct_span_err!(cx.tcx.sess, p.span, E0009,
                                            "cannot bind by-move and by-ref in the same pattern");
@@ -1129,7 +1133,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                 let pat_ty = cx.tcx.node_id_to_type(p.id);
                 //FIXME: (@jroesch) this code should be floated up as well
                 cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()),
-                                  ProjectionMode::AnyFinal).enter(|infcx| {
+                                  Reveal::NotSpecializable).enter(|infcx| {
                     if infcx.type_moves_by_default(pat_ty, pat.span) {
                         check_move(p, sub.as_ref().map(|p| &**p));
                     }
@@ -1145,7 +1149,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
 fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
                                          guard: &hir::Expr) {
     cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()),
-                      ProjectionMode::AnyFinal).enter(|infcx| {
+                      Reveal::NotSpecializable).enter(|infcx| {
         let mut checker = MutationChecker {
             cx: cx,
         };
index 43d9725baaf004e9e970fb466452d714186a1c87..73b54c4374ffb65dce75dcf20a6a0bbe29545af5 100644 (file)
@@ -24,7 +24,7 @@
 use rustc::hir::pat_util::def_to_path;
 use rustc::ty::{self, Ty, TyCtxt, subst};
 use rustc::ty::util::IntTypeExt;
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::lint;
@@ -44,7 +44,7 @@
 use std::collections::hash_map::Entry::Vacant;
 
 use rustc_const_math::*;
-use rustc_errors::{DiagnosticBuilder, check_old_school};
+use rustc_errors::DiagnosticBuilder;
 
 macro_rules! math {
     ($e:expr, $op:expr) => {
@@ -142,7 +142,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
         let mut used_substs = false;
         let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-            Some((&InlinedItem::Item(ref item), _)) => match item.node {
+            Some((&InlinedItem::Item(_, ref item), _)) => match item.node {
                 hir::ItemConst(ref ty, ref const_expr) => {
                     Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
                 },
@@ -198,7 +198,7 @@ fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     let fn_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
-        Some((&InlinedItem::Item(ref item), _)) => Some(item.id),
+        Some((&InlinedItem::Item(_, ref item), _)) => Some(item.id),
         Some((&InlinedItem::ImplItem(_, ref item), _)) => Some(item.id),
         _ => None
     };
@@ -378,11 +378,7 @@ pub fn note_const_eval_err<'a, 'tcx>(
 {
     match err.description() {
         ConstEvalErrDescription::Simple(message) => {
-            if check_old_school() {
-                diag.note(&message);
-            } else {
-                diag.span_label(err.span, &message);
-            }
+            diag.span_label(err.span, &message);
         }
     }
 
@@ -1059,7 +1055,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            trait_ref);
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-    tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
+    tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
         let mut selcx = traits::SelectionContext::new(&infcx);
         let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
                                                  trait_ref.to_poly_trait_predicate());
@@ -1077,9 +1073,9 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         };
 
         // NOTE: this code does not currently account for specialization, but when
-        // it does so, it should hook into the ProjectionMode to determine when the
+        // it does so, it should hook into the Reveal to determine when the
         // constant should resolve; this will also require plumbing through to this
-        // function whether we are in "trans mode" to pick the right ProjectionMode
+        // function whether we are in "trans mode" to pick the right Reveal
         // when constructing the inference context above.
         match selection {
             traits::VtableImpl(ref impl_data) => {
index 2c3a2e8ef6c3b97c9514bdf0cca99b850e3fdedd..0dab230f47a2d036bac2fc9b520417d592c249ef 100644 (file)
@@ -22,6 +22,12 @@ pub fn new(num_bits: usize) -> BitVector {
         BitVector { data: vec![0; num_words] }
     }
 
+    pub fn clear(&mut self) {
+        for p in &mut self.data {
+            *p = 0;
+        }
+    }
+
     pub fn contains(&self, bit: usize) -> bool {
         let (word, mask) = word_mask(bit);
         (self.data[word] & mask) != 0
@@ -118,32 +124,32 @@ fn from_iter<I>(iter: I) -> BitVector where I: IntoIterator<Item=bool> {
     }
 }
 
-/// A "bit matrix" is basically a square matrix of booleans
-/// represented as one gigantic bitvector. In other words, it is as if
-/// you have N bitvectors, each of length N. Note that `elements` here is `N`/
+/// A "bit matrix" is basically a matrix of booleans represented as
+/// one gigantic bitvector. In other words, it is as if you have
+/// `rows` bitvectors, each of length `columns`.
 #[derive(Clone)]
 pub struct BitMatrix {
-    elements: usize,
+    columns: usize,
     vector: Vec<u64>,
 }
 
 impl BitMatrix {
-    // Create a new `elements x elements` matrix, initially empty.
-    pub fn new(elements: usize) -> BitMatrix {
+    // Create a new `rows x columns` matrix, initially empty.
+    pub fn new(rows: usize, columns: usize) -> BitMatrix {
         // For every element, we need one bit for every other
         // element. Round up to an even number of u64s.
-        let u64s_per_elem = u64s(elements);
+        let u64s_per_row = u64s(columns);
         BitMatrix {
-            elements: elements,
-            vector: vec![0; elements * u64s_per_elem],
+            columns: columns,
+            vector: vec![0; rows * u64s_per_row],
         }
     }
 
-    /// The range of bits for a given element.
-    fn range(&self, element: usize) -> (usize, usize) {
-        let u64s_per_elem = u64s(self.elements);
-        let start = element * u64s_per_elem;
-        (start, start + u64s_per_elem)
+    /// The range of bits for a given row.
+    fn range(&self, row: usize) -> (usize, usize) {
+        let u64s_per_row = u64s(self.columns);
+        let start = row * u64s_per_row;
+        (start, start + u64s_per_row)
     }
 
     pub fn add(&mut self, source: usize, target: usize) -> bool {
@@ -173,7 +179,7 @@ pub fn contains(&self, source: usize, target: usize) -> bool {
     pub fn intersection(&self, a: usize, b: usize) -> Vec<usize> {
         let (a_start, a_end) = self.range(a);
         let (b_start, b_end) = self.range(b);
-        let mut result = Vec::with_capacity(self.elements);
+        let mut result = Vec::with_capacity(self.columns);
         for (base, (i, j)) in (a_start..a_end).zip(b_start..b_end).enumerate() {
             let mut v = self.vector[i] & self.vector[j];
             for bit in 0..64 {
@@ -209,6 +215,15 @@ pub fn merge(&mut self, read: usize, write: usize) -> bool {
         }
         changed
     }
+
+    pub fn iter<'a>(&'a self, row: usize) -> BitVectorIter<'a> {
+        let (start, end) = self.range(row);
+        BitVectorIter {
+            iter: self.vector[start..end].iter(),
+            current: 0,
+            idx: 0,
+        }
+    }
 }
 
 fn u64s(elements: usize) -> usize {
@@ -294,7 +309,7 @@ fn grow() {
 
 #[test]
 fn matrix_intersection() {
-    let mut vec1 = BitMatrix::new(200);
+    let mut vec1 = BitMatrix::new(200, 200);
 
     // (*) Elements reachable from both 2 and 65.
 
@@ -322,3 +337,45 @@ fn matrix_intersection() {
     let intersection = vec1.intersection(2, 65);
     assert_eq!(intersection, &[10, 64, 160]);
 }
+
+#[test]
+fn matrix_iter() {
+    let mut matrix = BitMatrix::new(64, 100);
+    matrix.add(3, 22);
+    matrix.add(3, 75);
+    matrix.add(2, 99);
+    matrix.add(4, 0);
+    matrix.merge(3, 5);
+
+    let expected = [99];
+    let mut iter = expected.iter();
+    for i in matrix.iter(2) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(3) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [0];
+    let mut iter = expected.iter();
+    for i in matrix.iter(4) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+
+    let expected = [22, 75];
+    let mut iter = expected.iter();
+    for i in matrix.iter(5) {
+        let j = *iter.next().unwrap();
+        assert_eq!(i, j);
+    }
+    assert!(iter.next().is_none());
+}
index 731471b0600f3cfe635e813d997d6d5f3223bb52..4561a3d084c2064183aac1d611cf1850d514b608 100644 (file)
@@ -296,12 +296,7 @@ pub fn depth_traverse<'a>(&'a self,
                               start: NodeIndex,
                               direction: Direction)
                               -> DepthFirstTraversal<'a, N, E> {
-        DepthFirstTraversal {
-            graph: self,
-            stack: vec![start],
-            visited: BitVector::new(self.nodes.len()),
-            direction: direction,
-        }
+        DepthFirstTraversal::with_start_node(self, start, direction)
     }
 }
 
@@ -378,26 +373,57 @@ pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
     direction: Direction,
 }
 
+impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
+    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
+        let visited = BitVector::new(graph.len_nodes());
+        DepthFirstTraversal {
+            graph: graph,
+            stack: vec![],
+            visited: visited,
+            direction: direction
+        }
+    }
+
+    pub fn with_start_node(graph: &'g Graph<N, E>,
+                           start_node: NodeIndex,
+                           direction: Direction)
+                           -> Self {
+        let mut visited = BitVector::new(graph.len_nodes());
+        visited.insert(start_node.node_id());
+        DepthFirstTraversal {
+            graph: graph,
+            stack: vec![start_node],
+            visited: visited,
+            direction: direction
+        }
+    }
+
+    pub fn reset(&mut self, start_node: NodeIndex) {
+        self.stack.truncate(0);
+        self.stack.push(start_node);
+        self.visited.clear();
+        self.visited.insert(start_node.node_id());
+    }
+
+    fn visit(&mut self, node: NodeIndex) {
+        if self.visited.insert(node.node_id()) {
+            self.stack.push(node);
+        }
+    }
+}
+
 impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
     type Item = NodeIndex;
 
     fn next(&mut self) -> Option<NodeIndex> {
-        while let Some(idx) = self.stack.pop() {
-            if !self.visited.insert(idx.node_id()) {
-                continue;
-            }
-
+        let next = self.stack.pop();
+        if let Some(idx) = next {
             for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                 let target = edge.source_or_target(self.direction);
-                if !self.visited.contains(target.node_id()) {
-                    self.stack.push(target);
-                }
+                self.visit(target);
             }
-
-            return Some(idx);
         }
-
-        return None;
+        next
     }
 }
 
index c3a2f978e1a8a4945f39ed8c091edbe5857ef762..e09e260afc8d99c0e0fddc6d0c3b6a85f26deb49 100644 (file)
@@ -252,7 +252,8 @@ fn with_closure<OP, R>(&self, op: OP) -> R
     }
 
     fn compute_closure(&self) -> BitMatrix {
-        let mut matrix = BitMatrix::new(self.elements.len());
+        let mut matrix = BitMatrix::new(self.elements.len(),
+                                        self.elements.len());
         let mut changed = true;
         while changed {
             changed = false;
index f1f5e194da4d16538418838c23725cad0f45e392..70b1261730b07092aca68f7cd721d75bb7a7121f 100644 (file)
@@ -673,13 +673,11 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session,
                                                       cfg,
                                                       &mut loader);
         syntax_ext::register_builtins(&mut ecx.syntax_env);
-        let (ret, macro_names) = syntax::ext::expand::expand_crate(ecx,
-                                                                   syntax_exts,
-                                                                   krate);
+        let ret = syntax::ext::expand::expand_crate(&mut ecx, syntax_exts, krate);
         if cfg!(windows) {
             env::set_var("PATH", &old_path);
         }
-        *sess.available_macros.borrow_mut() = macro_names;
+        *sess.available_macros.borrow_mut() = ecx.syntax_env.names;
         ret
     });
 
@@ -846,10 +844,10 @@ macro_rules! try_with_f {
 
     let index = stability::Index::new(&hir_map);
 
-    let trait_map = resolutions.trait_map;
     TyCtxt::create_and_enter(sess,
                              arenas,
                              resolutions.def_map,
+                             resolutions.trait_map,
                              named_region_map,
                              hir_map,
                              resolutions.freevars,
@@ -864,7 +862,7 @@ macro_rules! try_with_f {
              || rustc_incremental::load_dep_graph(tcx));
 
         // passes are timed inside typeck
-        try_with_f!(typeck::check_crate(tcx, trait_map), (tcx, None, analysis));
+        try_with_f!(typeck::check_crate(tcx), (tcx, None, analysis));
 
         time(time_passes,
              "const checking",
index 772c59b34dd02725897eca4d397c6d5bac309aa8..98860c8f900eb397a68851509144182c89bc8364 100644 (file)
@@ -68,6 +68,7 @@
 use rustc_resolve as resolve;
 use rustc_save_analysis as save;
 use rustc_trans::back::link;
+use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
 use syntax::parse::{self, PResult};
 use syntax_pos::MultiSpan;
 use errors::emitter::Emitter;
-use errors::snippet::FormatMode;
 
 #[cfg(test)]
 pub mod test;
@@ -141,9 +141,7 @@ pub fn run(args: Vec<String>) -> isize {
                     None => {
                         let emitter =
                             errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
-                                                                   None,
-                                                                   None,
-                                                                   FormatMode::EnvironmentSelected);
+                                                                   None);
                         let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
                         handler.emit(&MultiSpan::new(),
                                      &abort_msg(err_count),
@@ -381,10 +379,7 @@ fn check_cfg(sopts: &config::Options,
              output: ErrorOutputType) {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(errors::emitter::EmitterWriter::stderr(color_config,
-                                                            None,
-                                                            None,
-                                                            FormatMode::EnvironmentSelected))
+            Box::new(errors::emitter::EmitterWriter::stderr(color_config, None))
         }
         config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()),
     };
@@ -660,6 +655,28 @@ fn print_crate_info(sess: &Session,
                         }
                     }
                 }
+                PrintRequest::TargetCPUs => {
+                    let tm = create_target_machine(sess);
+                    unsafe { llvm::LLVMRustPrintTargetCPUs(tm); }
+                }
+                PrintRequest::TargetFeatures => {
+                    let tm = create_target_machine(sess);
+                    unsafe { llvm::LLVMRustPrintTargetFeatures(tm); }
+                }
+                PrintRequest::RelocationModels => {
+                    println!("Available relocation models:");
+                    for &(name, _) in RELOC_MODEL_ARGS.iter() {
+                        println!("    {}", name);
+                    }
+                    println!("");
+                }
+                PrintRequest::CodeModels => {
+                    println!("Available code models:");
+                    for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){
+                        println!("    {}", name);
+                    }
+                    println!("");
+                }
             }
         }
         return Compilation::Stop;
@@ -1050,10 +1067,7 @@ fn flush(&mut self) -> io::Result<()> {
         // Thread panicked without emitting a fatal diagnostic
         if !value.is::<errors::FatalError>() {
             let emitter =
-                Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
-                                                       None,
-                                                       None,
-                                                       FormatMode::EnvironmentSelected));
+                Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None));
             let handler = errors::Handler::with_emitter(true, false, emitter);
 
             // a .span_bug or .bug call has already printed what
index 14476cc997ff3eb35968e2540a7a99902d81205c..e3e06963ad43bf59f242c1025decbd173fe729ff 100644 (file)
@@ -956,20 +956,24 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
             PpmMir | PpmMirCFG => {
                 if let Some(mir_map) = mir_map {
                     if let Some(nodeid) = nodeid {
-                        let mir = mir_map.map.get(&nodeid).unwrap_or_else(|| {
-                            sess.fatal(&format!("no MIR map entry for node {}", nodeid))
-                        });
+                        let def_id = tcx.map.local_def_id(nodeid);
                         match ppm {
-                            PpmMir => write_mir_pretty(tcx, iter::once((&nodeid, mir)), &mut out),
+                            PpmMir => write_mir_pretty(tcx, iter::once(def_id), &mir_map, &mut out),
                             PpmMirCFG => {
-                                write_mir_graphviz(tcx, iter::once((&nodeid, mir)), &mut out)
+                                write_mir_graphviz(tcx, iter::once(def_id), &mir_map, &mut out)
                             }
                             _ => unreachable!(),
                         }?;
                     } else {
                         match ppm {
-                            PpmMir => write_mir_pretty(tcx, mir_map.map.iter(), &mut out),
-                            PpmMirCFG => write_mir_graphviz(tcx, mir_map.map.iter(), &mut out),
+                            PpmMir => write_mir_pretty(tcx,
+                                                       mir_map.map.keys().into_iter(),
+                                                       &mir_map,
+                                                       &mut out),
+                            PpmMirCFG => write_mir_graphviz(tcx,
+                                                            mir_map.map.keys().into_iter(),
+                                                            &mir_map,
+                                                            &mut out),
                             _ => unreachable!(),
                         }?;
                     }
index 39763bfa0eb61c6d279054166cf57eaeab03de87..30fe38a0603a563f71791bc8ac58fa7124d80c5e 100644 (file)
@@ -22,7 +22,7 @@
 use rustc::middle::stability;
 use rustc::ty::subst;
 use rustc::ty::subst::Subst;
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
 use rustc_metadata::cstore::CStore;
@@ -131,6 +131,7 @@ fn test_env<F>(source_string: &str,
     TyCtxt::create_and_enter(&sess,
                              &arenas,
                              resolutions.def_map,
+                             resolutions.trait_map,
                              named_region_map.unwrap(),
                              ast_map,
                              resolutions.freevars,
@@ -140,7 +141,7 @@ fn test_env<F>(source_string: &str,
                              index,
                              "test_crate",
                              |tcx| {
-        tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
+        tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
 
             body(Env { infcx: &infcx });
             let free_regions = FreeRegionMap::new();
index 893f8a6e4ddb01b4a09963ec5afe445964d81cc1..981729ddb839581ceecabe70f30093b388313de1 100644 (file)
 
 use self::Destination::*;
 
-use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, LineInfo, CharPos};
-use registry;
+use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, CharPos};
 
-use check_old_school;
 use {Level, CodeSuggestion, DiagnosticBuilder, CodeMapper};
 use RenderSpan::*;
-use snippet::{StyledString, Style, FormatMode, Annotation, Line};
+use snippet::{StyledString, Style, Annotation, Line};
 use styled_buffer::StyledBuffer;
 
-use std::cmp;
 use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
@@ -33,18 +30,7 @@ pub trait Emitter {
 
 impl Emitter for EmitterWriter {
     fn emit(&mut self, db: &DiagnosticBuilder) {
-        // Pick old school mode either from env or let the test dictate the format
-        let old_school = match self.format_mode {
-            FormatMode::NewErrorFormat => false,
-            FormatMode::OriginalErrorFormat => true,
-            FormatMode::EnvironmentSelected => check_old_school()
-        };
-
-        if old_school {
-            self.emit_messages_old_school(db);
-        } else {
-            self.emit_messages_default(db);
-        }
+        self.emit_messages_default(db);
     }
 }
 
@@ -70,11 +56,7 @@ fn use_color(&self) -> bool {
 
 pub struct EmitterWriter {
     dst: Destination,
-    registry: Option<registry::Registry>,
     cm: Option<Rc<CodeMapper>>,
-
-    // For now, allow an old-school mode while we transition
-    format_mode: FormatMode
 }
 
 struct FileWithAnnotatedLines {
@@ -99,33 +81,23 @@ macro_rules! println_maybe_styled {
 
 impl EmitterWriter {
     pub fn stderr(color_config: ColorConfig,
-                  registry: Option<registry::Registry>,
-                  code_map: Option<Rc<CodeMapper>>,
-                  format_mode: FormatMode)
+                  code_map: Option<Rc<CodeMapper>>)
                   -> EmitterWriter {
         if color_config.use_color() {
             let dst = Destination::from_stderr();
             EmitterWriter { dst: dst,
-                            registry: registry,
-                            cm: code_map,
-                            format_mode: format_mode.clone() }
+                            cm: code_map}
         } else {
             EmitterWriter { dst: Raw(Box::new(io::stderr())),
-                            registry: registry,
-                            cm: code_map,
-                            format_mode: format_mode.clone() }
+                            cm: code_map}
         }
     }
 
     pub fn new(dst: Box<Write + Send>,
-               registry: Option<registry::Registry>,
-               code_map: Option<Rc<CodeMapper>>,
-               format_mode: FormatMode)
+               code_map: Option<Rc<CodeMapper>>)
                -> EmitterWriter {
         EmitterWriter { dst: Raw(dst),
-                        registry: registry,
-                        cm: code_map,
-                        format_mode: format_mode.clone() }
+                        cm: code_map}
     }
 
     fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
@@ -668,240 +640,6 @@ fn emit_messages_default(&mut self, db: &DiagnosticBuilder) {
             _ => ()
         }
     }
-    fn emit_message_old_school(&mut self,
-                               msp: &MultiSpan,
-                               msg: &str,
-                               code: &Option<String>,
-                               level: &Level,
-                               show_snippet: bool)
-                               -> io::Result<()> {
-        let mut buffer = StyledBuffer::new();
-
-        let loc = match msp.primary_span() {
-            Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
-            Some(ps) => if let Some(ref cm) = self.cm {
-                cm.span_to_string(ps)
-            } else {
-                "".to_string()
-            },
-            None => {
-                "".to_string()
-            }
-        };
-        if loc != "" {
-            buffer.append(0, &loc, Style::NoStyle);
-            buffer.append(0, " ", Style::NoStyle);
-        }
-        buffer.append(0, &level.to_string(), Style::Level(level.clone()));
-        buffer.append(0, ": ", Style::HeaderMsg);
-        buffer.append(0, msg, Style::HeaderMsg);
-        buffer.append(0, " ", Style::NoStyle);
-        match code {
-            &Some(ref code) => {
-                buffer.append(0, "[", Style::ErrorCode);
-                buffer.append(0, &code, Style::ErrorCode);
-                buffer.append(0, "]", Style::ErrorCode);
-            }
-            _ => {}
-        }
-
-        if !show_snippet {
-            emit_to_destination(&buffer.render(), level, &mut self.dst)?;
-            return Ok(());
-        }
-
-        // Watch out for various nasty special spans; don't try to
-        // print any filename or anything for those.
-        match msp.primary_span() {
-            Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => {
-                emit_to_destination(&buffer.render(), level, &mut self.dst)?;
-                return Ok(());
-            }
-            _ => { }
-        }
-
-        let annotated_files = self.preprocess_annotations(msp);
-
-        if let (Some(ref cm), Some(ann_file), Some(ref primary_span)) =
-            (self.cm.as_ref(), annotated_files.first(), msp.primary_span().as_ref()) {
-
-            // Next, print the source line and its squiggle
-            // for old school mode, we will render them to the buffer, then insert the file loc
-            // (or space the same amount) in front of the line and the squiggle
-            let source_string = ann_file.file.get_line(ann_file.lines[0].line_index - 1)
-                .unwrap_or("");
-
-            let line_offset = buffer.num_lines();
-
-            let lo = cm.lookup_char_pos(primary_span.lo);
-            //Before each secondary line in old skool-mode, print the label
-            //as an old-style note
-            let file_pos = format!("{}:{} ", lo.file.name.clone(), lo.line);
-            let file_pos_len = file_pos.len();
-
-            // First create the source line we will highlight.
-            buffer.puts(line_offset, 0, &file_pos, Style::FileNameStyle);
-            buffer.puts(line_offset, file_pos_len, &source_string, Style::Quotation);
-            // Sort the annotations by (start, end col)
-            let annotations = ann_file.lines[0].annotations.clone();
-
-            // Next, create the highlight line.
-            for annotation in &annotations {
-                for p in annotation.start_col..annotation.end_col {
-                    if p == annotation.start_col {
-                        buffer.putc(line_offset + 1,
-                                    file_pos_len + p,
-                                    '^',
-                                    if annotation.is_primary {
-                                        Style::UnderlinePrimary
-                                    } else {
-                                        Style::OldSchoolNote
-                                    });
-                    } else {
-                        buffer.putc(line_offset + 1,
-                                    file_pos_len + p,
-                                    '~',
-                                    if annotation.is_primary {
-                                        Style::UnderlinePrimary
-                                    } else {
-                                        Style::OldSchoolNote
-                                    });
-                    }
-                }
-            }
-        }
-        if let Some(ref primary_span) = msp.primary_span().as_ref() {
-            self.render_macro_backtrace_old_school(primary_span, &mut buffer)?;
-        }
-
-        match code {
-            &Some(ref code) if self.registry.as_ref()
-                                           .and_then(|registry| registry.find_description(code))
-                                           .is_some() => {
-                let msg = "run `rustc --explain ".to_string() + &code.to_string() +
-                    "` to see a detailed explanation";
-
-                let line_offset = buffer.num_lines();
-                buffer.append(line_offset, &loc, Style::NoStyle);
-                buffer.append(line_offset, " ", Style::NoStyle);
-                buffer.append(line_offset, &Level::Help.to_string(), Style::Level(Level::Help));
-                buffer.append(line_offset, ": ", Style::HeaderMsg);
-                buffer.append(line_offset, &msg, Style::HeaderMsg);
-            }
-            _ => ()
-        }
-
-        // final step: take our styled buffer, render it, then output it
-        emit_to_destination(&buffer.render(), level, &mut self.dst)?;
-        Ok(())
-    }
-    fn emit_suggestion_old_school(&mut self,
-                                  suggestion: &CodeSuggestion,
-                                  level: &Level,
-                                  msg: &str)
-                                  -> io::Result<()> {
-        use std::borrow::Borrow;
-
-        let primary_span = suggestion.msp.primary_span().unwrap();
-        if let Some(ref cm) = self.cm {
-            let mut buffer = StyledBuffer::new();
-
-            let loc = cm.span_to_string(primary_span);
-
-            if loc != "" {
-                buffer.append(0, &loc, Style::NoStyle);
-                buffer.append(0, " ", Style::NoStyle);
-            }
-
-            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
-            buffer.append(0, ": ", Style::HeaderMsg);
-            buffer.append(0, msg, Style::HeaderMsg);
-
-            let lines = cm.span_to_lines(primary_span).unwrap();
-
-            assert!(!lines.lines.is_empty());
-
-            let complete = suggestion.splice_lines(cm.borrow());
-            let line_count = cmp::min(lines.lines.len(), MAX_HIGHLIGHT_LINES);
-            let display_lines = &lines.lines[..line_count];
-
-            let fm = &*lines.file;
-            // Calculate the widest number to format evenly
-            let max_digits = line_num_max_digits(display_lines.last().unwrap());
-
-            // print the suggestion without any line numbers, but leave
-            // space for them. This helps with lining up with previous
-            // snippets from the actual error being reported.
-            let mut lines = complete.lines();
-            let mut row_num = 1;
-            for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
-                buffer.append(row_num, &fm.name, Style::FileNameStyle);
-                for _ in 0..max_digits+2 {
-                    buffer.append(row_num, &" ", Style::NoStyle);
-                }
-                buffer.append(row_num, line, Style::NoStyle);
-                row_num += 1;
-            }
-
-            // if we elided some lines, add an ellipsis
-            if let Some(_) = lines.next() {
-                buffer.append(row_num, "...", Style::NoStyle);
-            }
-            emit_to_destination(&buffer.render(), level, &mut self.dst)?;
-        }
-        Ok(())
-    }
-
-    fn emit_messages_old_school(&mut self, db: &DiagnosticBuilder) {
-        match self.emit_message_old_school(&db.span,
-                                           &db.message,
-                                           &db.code,
-                                           &db.level,
-                                           true) {
-            Ok(()) => {
-                for child in &db.children {
-                    let (span, show_snippet) = if child.span.primary_spans().is_empty() {
-                        (db.span.clone(), false)
-                    } else {
-                        (child.span.clone(), true)
-                    };
-
-                    match child.render_span {
-                        Some(FullSpan(_)) => {
-                            match self.emit_message_old_school(&span,
-                                                               &child.message,
-                                                               &None,
-                                                               &child.level,
-                                                               show_snippet) {
-                                Err(e) => panic!("failed to emit error: {}", e),
-                                _ => ()
-                            }
-                        },
-                        Some(Suggestion(ref cs)) => {
-                            match self.emit_suggestion_old_school(cs,
-                                                                  &child.level,
-                                                                  &child.message) {
-                                Err(e) => panic!("failed to emit error: {}", e),
-                                _ => ()
-                            }
-                        },
-                        None => {
-                            match self.emit_message_old_school(&span,
-                                                               &child.message,
-                                                               &None,
-                                                               &child.level,
-                                                               show_snippet) {
-                                Err(e) => panic!("failed to emit error: {}", e),
-                                _ => ()
-                            }
-                        }
-                    }
-                }
-            }
-            Err(e) => panic!("failed to emit error: {}", e)
-        }
-    }
-
     fn render_macro_backtrace_old_school(&mut self,
                                          sp: &Span,
                                          buffer: &mut StyledBuffer) -> io::Result<()> {
@@ -958,16 +696,6 @@ fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
     Ok(())
 }
 
-fn line_num_max_digits(line: &LineInfo) -> usize {
-    let mut max_line_num = line.line_index + 1;
-    let mut digits = 0;
-    while max_line_num > 0 {
-        max_line_num /= 10;
-        digits += 1;
-    }
-    digits
-}
-
 #[cfg(unix)]
 fn stderr_isatty() -> bool {
     use libc;
index 610e5647d6d12893547923c65d361474d0914c00..172e27d56d4852b83bb80be3e0ff00112a0c1500 100644 (file)
@@ -420,13 +420,11 @@ pub struct Handler {
 
 impl Handler {
     pub fn with_tty_emitter(color_config: ColorConfig,
-                            registry: Option<registry::Registry>,
                             can_emit_warnings: bool,
                             treat_err_as_bug: bool,
                             cm: Option<Rc<CodeMapper>>)
                             -> Handler {
-        let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm,
-                               snippet::FormatMode::EnvironmentSelected));
+        let emitter = Box::new(EmitterWriter::stderr(color_config, cm));
         Handler::with_emitter(can_emit_warnings, treat_err_as_bug, emitter)
     }
 
@@ -750,21 +748,4 @@ pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
         Some(t) => t,
         None => diag.bug(&msg()),
     }
-}
-
-/// True if we should use the old-skool error format style. This is
-/// the default setting until the new errors are deemed stable enough
-/// for general use.
-///
-/// FIXME(#33240)
-#[cfg(not(test))]
-pub fn check_old_school() -> bool {
-    use std::env;
-    env::var("RUST_NEW_ERROR_FORMAT").is_err()
-}
-
-/// For unit tests, use the new format.
-#[cfg(test)]
-pub fn check_old_school() -> bool {
-    false
-}
+}
\ No newline at end of file
index 2f94a7f6832fe34401b3a52b6d54cb7d610023ef..5ade8cd9bad82be4f2c34b6ffe98fe5d7494e02c 100644 (file)
 use std::rc::Rc;
 use {Level};
 
-#[derive(Clone)]
-pub enum FormatMode {
-    NewErrorFormat,
-    OriginalErrorFormat,
-    EnvironmentSelected
-}
-
 #[derive(Clone)]
 pub struct SnippetData {
     codemap: Rc<CodeMapper>,
-    files: Vec<FileInfo>,
-    format_mode: FormatMode,
+    files: Vec<FileInfo>
 }
 
 #[derive(Clone)]
@@ -41,10 +33,6 @@ pub struct FileInfo {
     primary_span: Option<Span>,
 
     lines: Vec<Line>,
-
-    /// The type of error format to render.  We keep it here so that
-    /// it's easy to configure for both tests and regular usage
-    format_mode: FormatMode,
 }
 
 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
index 774c5ca6d6b239a75b8a72ad583f23248e698280..420c88e89be0d0373aff440bc5bbc9173a1543b8 100644 (file)
@@ -71,6 +71,13 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         dump_graph(tcx);
     }
 
+    // if the `rustc_attrs` feature is not enabled, then the
+    // attributes we are interested in cannot be present anyway, so
+    // skip the walk.
+    if !tcx.sess.features.borrow().rustc_attrs {
+        return;
+    }
+
     // Find annotations supplied by user (if any).
     let (if_this_changed, then_this_would_need) = {
         let mut visitor = IfThisChanged { tcx: tcx,
diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs
deleted file mode 100644 (file)
index bea6b7e..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright 2012-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.
-
-//! Calculation of a Strict Version Hash for crates.  For a length
-//! comment explaining the general idea, see `librustc/middle/svh.rs`.
-
-use syntax::attr::AttributeMethods;
-use std::hash::{Hash, SipHasher, Hasher};
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
-use rustc::hir::svh::Svh;
-use rustc::ty::TyCtxt;
-use rustc::hir::intravisit::{self, Visitor};
-
-use self::svh_visitor::StrictVersionHashVisitor;
-
-pub trait SvhCalculate {
-    /// Calculate the SVH for an entire krate.
-    fn calculate_krate_hash(self) -> Svh;
-
-    /// Calculate the SVH for a particular item.
-    fn calculate_item_hash(self, def_id: DefId) -> u64;
-}
-
-impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
-    fn calculate_krate_hash(self) -> Svh {
-        // FIXME (#14132): This is better than it used to be, but it still not
-        // ideal. We now attempt to hash only the relevant portions of the
-        // Crate AST as well as the top-level crate attributes. (However,
-        // the hashing of the crate attributes should be double-checked
-        // to ensure it is not incorporating implementation artifacts into
-        // the hash that are not otherwise visible.)
-
-        let crate_disambiguator = self.sess.local_crate_disambiguator();
-        let krate = self.map.krate();
-
-        // FIXME: this should use SHA1, not SipHash. SipHash is not built to
-        //        avoid collisions.
-        let mut state = SipHasher::new();
-        debug!("state: {:?}", state);
-
-        // FIXME(#32753) -- at (*) we `to_le` for endianness, but is
-        // this enough, and does it matter anyway?
-        "crate_disambiguator".hash(&mut state);
-        crate_disambiguator.len().to_le().hash(&mut state); // (*)
-        crate_disambiguator.hash(&mut state);
-
-        debug!("crate_disambiguator: {:?}", crate_disambiguator);
-        debug!("state: {:?}", state);
-
-        {
-            let mut visit = StrictVersionHashVisitor::new(&mut state, self);
-            krate.visit_all_items(&mut visit);
-        }
-
-        // FIXME (#14132): This hash is still sensitive to e.g. the
-        // spans of the crate Attributes and their underlying
-        // MetaItems; we should make ContentHashable impl for those
-        // types and then use hash_content.  But, since all crate
-        // attributes should appear near beginning of the file, it is
-        // not such a big deal to be sensitive to their spans for now.
-        //
-        // We hash only the MetaItems instead of the entire Attribute
-        // to avoid hashing the AttrId
-        for attr in &krate.attrs {
-            debug!("krate attr {:?}", attr);
-            attr.meta().hash(&mut state);
-        }
-
-        Svh::new(state.finish())
-    }
-
-    fn calculate_item_hash(self, def_id: DefId) -> u64 {
-        assert!(def_id.is_local());
-
-        debug!("calculate_item_hash(def_id={:?})", def_id);
-
-        let mut state = SipHasher::new();
-
-        {
-            let mut visit = StrictVersionHashVisitor::new(&mut state, self);
-            if def_id.index == CRATE_DEF_INDEX {
-                // the crate root itself is not registered in the map
-                // as an item, so we have to fetch it this way
-                let krate = self.map.krate();
-                intravisit::walk_crate(&mut visit, krate);
-            } else {
-                let node_id = self.map.as_local_node_id(def_id).unwrap();
-                let item = self.map.expect_item(node_id);
-                visit.visit_item(item);
-            }
-        }
-
-        let hash = state.finish();
-
-        debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, hash);
-
-        hash
-    }
-}
-
-// FIXME (#14132): Even this SVH computation still has implementation
-// artifacts: namely, the order of item declaration will affect the
-// hash computation, but for many kinds of items the order of
-// declaration should be irrelevant to the ABI.
-
-mod svh_visitor {
-    pub use self::SawExprComponent::*;
-    pub use self::SawStmtComponent::*;
-    use self::SawAbiComponent::*;
-    use syntax::ast::{self, Name, NodeId};
-    use syntax::parse::token;
-    use syntax_pos::Span;
-    use rustc::ty::TyCtxt;
-    use rustc::hir;
-    use rustc::hir::*;
-    use rustc::hir::map::DefPath;
-    use rustc::hir::intravisit as visit;
-    use rustc::hir::intravisit::{Visitor, FnKind};
-
-    use std::hash::{Hash, SipHasher};
-
-    pub struct StrictVersionHashVisitor<'a, 'tcx: 'a> {
-        pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        pub st: &'a mut SipHasher,
-    }
-
-    impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
-        pub fn new(st: &'a mut SipHasher,
-                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                   -> Self {
-            StrictVersionHashVisitor { st: st, tcx: tcx }
-        }
-
-        fn hash_def_path(&mut self, path: &DefPath) {
-            self.tcx.crate_name(path.krate).hash(self.st);
-            self.tcx.crate_disambiguator(path.krate).hash(self.st);
-            for data in &path.data {
-                data.data.as_interned_str().hash(self.st);
-                data.disambiguator.hash(self.st);
-            }
-        }
-    }
-
-    // To off-load the bulk of the hash-computation on #[derive(Hash)],
-    // we define a set of enums corresponding to the content that our
-    // crate visitor will encounter as it traverses the ast.
-    //
-    // The important invariant is that all of the Saw*Component enums
-    // do not carry any Spans, Names, or Idents.
-    //
-    // Not carrying any Names/Idents is the important fix for problem
-    // noted on PR #13948: using the ident.name as the basis for a
-    // hash leads to unstable SVH, because ident.name is just an index
-    // into intern table (i.e. essentially a random address), not
-    // computed from the name content.
-    //
-    // With the below enums, the SVH computation is not sensitive to
-    // artifacts of how rustc was invoked nor of how the source code
-    // was laid out.  (Or at least it is *less* sensitive.)
-
-    // This enum represents the different potential bits of code the
-    // visitor could encounter that could affect the ABI for the crate,
-    // and assigns each a distinct tag to feed into the hash computation.
-    #[derive(Hash)]
-    enum SawAbiComponent<'a> {
-
-        // FIXME (#14132): should we include (some function of)
-        // ident.ctxt as well?
-        SawIdent(token::InternedString),
-        SawStructDef(token::InternedString),
-
-        SawLifetime(token::InternedString),
-        SawLifetimeDef(token::InternedString),
-
-        SawMod,
-        SawForeignItem,
-        SawItem,
-        SawDecl,
-        SawTy,
-        SawGenerics,
-        SawFn,
-        SawTraitItem,
-        SawImplItem,
-        SawStructField,
-        SawVariant,
-        SawPath,
-        SawBlock,
-        SawPat,
-        SawLocal,
-        SawArm,
-        SawExpr(SawExprComponent<'a>),
-        SawStmt(SawStmtComponent),
-    }
-
-    /// SawExprComponent carries all of the information that we want
-    /// to include in the hash that *won't* be covered by the
-    /// subsequent recursive traversal of the expression's
-    /// substructure by the visitor.
-    ///
-    /// We know every Expr_ variant is covered by a variant because
-    /// `fn saw_expr` maps each to some case below.  Ensuring that
-    /// each variant carries an appropriate payload has to be verified
-    /// by hand.
-    ///
-    /// (However, getting that *exactly* right is not so important
-    /// because the SVH is just a developer convenience; there is no
-    /// guarantee of collision-freedom, hash collisions are just
-    /// (hopefully) unlikely.)
-    #[derive(Hash)]
-    pub enum SawExprComponent<'a> {
-
-        SawExprLoop(Option<token::InternedString>),
-        SawExprField(token::InternedString),
-        SawExprTupField(usize),
-        SawExprBreak(Option<token::InternedString>),
-        SawExprAgain(Option<token::InternedString>),
-
-        SawExprBox,
-        SawExprVec,
-        SawExprCall,
-        SawExprMethodCall,
-        SawExprTup,
-        SawExprBinary(hir::BinOp_),
-        SawExprUnary(hir::UnOp),
-        SawExprLit(ast::LitKind),
-        SawExprCast,
-        SawExprType,
-        SawExprIf,
-        SawExprWhile,
-        SawExprMatch,
-        SawExprClosure,
-        SawExprBlock,
-        SawExprAssign,
-        SawExprAssignOp(hir::BinOp_),
-        SawExprIndex,
-        SawExprPath(Option<usize>),
-        SawExprAddrOf(hir::Mutability),
-        SawExprRet,
-        SawExprInlineAsm(&'a hir::InlineAsm),
-        SawExprStruct,
-        SawExprRepeat,
-    }
-
-    fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
-        match *node {
-            ExprBox(..)              => SawExprBox,
-            ExprVec(..)              => SawExprVec,
-            ExprCall(..)             => SawExprCall,
-            ExprMethodCall(..)       => SawExprMethodCall,
-            ExprTup(..)              => SawExprTup,
-            ExprBinary(op, _, _)     => SawExprBinary(op.node),
-            ExprUnary(op, _)         => SawExprUnary(op),
-            ExprLit(ref lit)         => SawExprLit(lit.node.clone()),
-            ExprCast(..)             => SawExprCast,
-            ExprType(..)             => SawExprType,
-            ExprIf(..)               => SawExprIf,
-            ExprWhile(..)            => SawExprWhile,
-            ExprLoop(_, id)          => SawExprLoop(id.map(|id| id.node.as_str())),
-            ExprMatch(..)            => SawExprMatch,
-            ExprClosure(..)          => SawExprClosure,
-            ExprBlock(..)            => SawExprBlock,
-            ExprAssign(..)           => SawExprAssign,
-            ExprAssignOp(op, _, _)   => SawExprAssignOp(op.node),
-            ExprField(_, name)       => SawExprField(name.node.as_str()),
-            ExprTupField(_, id)      => SawExprTupField(id.node),
-            ExprIndex(..)            => SawExprIndex,
-            ExprPath(ref qself, _)   => SawExprPath(qself.as_ref().map(|q| q.position)),
-            ExprAddrOf(m, _)         => SawExprAddrOf(m),
-            ExprBreak(id)            => SawExprBreak(id.map(|id| id.node.as_str())),
-            ExprAgain(id)            => SawExprAgain(id.map(|id| id.node.as_str())),
-            ExprRet(..)              => SawExprRet,
-            ExprInlineAsm(ref a,_,_) => SawExprInlineAsm(a),
-            ExprStruct(..)           => SawExprStruct,
-            ExprRepeat(..)           => SawExprRepeat,
-        }
-    }
-
-    /// SawStmtComponent is analogous to SawExprComponent, but for statements.
-    #[derive(Hash)]
-    pub enum SawStmtComponent {
-        SawStmtDecl,
-        SawStmtExpr,
-        SawStmtSemi,
-    }
-
-    fn saw_stmt(node: &Stmt_) -> SawStmtComponent {
-        match *node {
-            StmtDecl(..) => SawStmtDecl,
-            StmtExpr(..) => SawStmtExpr,
-            StmtSemi(..) => SawStmtSemi,
-        }
-    }
-
-    impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> {
-        fn visit_nested_item(&mut self, item: ItemId) {
-            let def_path = self.tcx.map.def_path_from_id(item.id).unwrap();
-            debug!("visit_nested_item: def_path={:?} st={:?}", def_path, self.st);
-            self.hash_def_path(&def_path);
-        }
-
-        fn visit_variant_data(&mut self, s: &'a VariantData, name: Name,
-                              g: &'a Generics, _: NodeId, _: Span) {
-            debug!("visit_variant_data: st={:?}", self.st);
-            SawStructDef(name.as_str()).hash(self.st);
-            visit::walk_generics(self, g);
-            visit::walk_struct_def(self, s)
-        }
-
-        fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
-            debug!("visit_variant: st={:?}", self.st);
-            SawVariant.hash(self.st);
-            // walk_variant does not call walk_generics, so do it here.
-            visit::walk_generics(self, g);
-            visit::walk_variant(self, v, g, item_id)
-        }
-
-        // All of the remaining methods just record (in the hash
-        // SipHasher) that the visitor saw that particular variant
-        // (with its payload), and continue walking as the default
-        // visitor would.
-        //
-        // Some of the implementations have some notes as to how one
-        // might try to make their SVH computation less discerning
-        // (e.g. by incorporating reachability analysis).  But
-        // currently all of their implementations are uniform and
-        // uninteresting.
-        //
-        // (If you edit a method such that it deviates from the
-        // pattern, please move that method up above this comment.)
-
-        fn visit_name(&mut self, _: Span, name: Name) {
-            debug!("visit_name: st={:?}", self.st);
-            SawIdent(name.as_str()).hash(self.st);
-        }
-
-        fn visit_lifetime(&mut self, l: &'a Lifetime) {
-            debug!("visit_lifetime: st={:?}", self.st);
-            SawLifetime(l.name.as_str()).hash(self.st);
-        }
-
-        fn visit_lifetime_def(&mut self, l: &'a LifetimeDef) {
-            debug!("visit_lifetime_def: st={:?}", self.st);
-            SawLifetimeDef(l.lifetime.name.as_str()).hash(self.st);
-        }
-
-        // We do recursively walk the bodies of functions/methods
-        // (rather than omitting their bodies from the hash) since
-        // monomorphization and cross-crate inlining generally implies
-        // that a change to a crate body will require downstream
-        // crates to be recompiled.
-        fn visit_expr(&mut self, ex: &'a Expr) {
-            debug!("visit_expr: st={:?}", self.st);
-            SawExpr(saw_expr(&ex.node)).hash(self.st); visit::walk_expr(self, ex)
-        }
-
-        fn visit_stmt(&mut self, s: &'a Stmt) {
-            debug!("visit_stmt: st={:?}", self.st);
-            SawStmt(saw_stmt(&s.node)).hash(self.st); visit::walk_stmt(self, s)
-        }
-
-        fn visit_foreign_item(&mut self, i: &'a ForeignItem) {
-            debug!("visit_foreign_item: st={:?}", self.st);
-
-            // FIXME (#14132) ideally we would incorporate privacy (or
-            // perhaps reachability) somewhere here, so foreign items
-            // that do not leak into downstream crates would not be
-            // part of the ABI.
-            SawForeignItem.hash(self.st); visit::walk_foreign_item(self, i)
-        }
-
-        fn visit_item(&mut self, i: &'a Item) {
-            debug!("visit_item: {:?} st={:?}", i, self.st);
-
-            // FIXME (#14132) ideally would incorporate reachability
-            // analysis somewhere here, so items that never leak into
-            // downstream crates (e.g. via monomorphisation or
-            // inlining) would not be part of the ABI.
-            SawItem.hash(self.st); visit::walk_item(self, i)
-        }
-
-        fn visit_mod(&mut self, m: &'a Mod, _s: Span, n: NodeId) {
-            debug!("visit_mod: st={:?}", self.st);
-            SawMod.hash(self.st); visit::walk_mod(self, m, n)
-        }
-
-        fn visit_decl(&mut self, d: &'a Decl) {
-            debug!("visit_decl: st={:?}", self.st);
-            SawDecl.hash(self.st); visit::walk_decl(self, d)
-        }
-
-        fn visit_ty(&mut self, t: &'a Ty) {
-            debug!("visit_ty: st={:?}", self.st);
-            SawTy.hash(self.st); visit::walk_ty(self, t)
-        }
-
-        fn visit_generics(&mut self, g: &'a Generics) {
-            debug!("visit_generics: st={:?}", self.st);
-            SawGenerics.hash(self.st); visit::walk_generics(self, g)
-        }
-
-        fn visit_fn(&mut self, fk: FnKind<'a>, fd: &'a FnDecl,
-                    b: &'a Block, s: Span, n: NodeId) {
-            debug!("visit_fn: st={:?}", self.st);
-            SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s, n)
-        }
-
-        fn visit_trait_item(&mut self, ti: &'a TraitItem) {
-            debug!("visit_trait_item: st={:?}", self.st);
-            SawTraitItem.hash(self.st); visit::walk_trait_item(self, ti)
-        }
-
-        fn visit_impl_item(&mut self, ii: &'a ImplItem) {
-            debug!("visit_impl_item: st={:?}", self.st);
-            SawImplItem.hash(self.st); visit::walk_impl_item(self, ii)
-        }
-
-        fn visit_struct_field(&mut self, s: &'a StructField) {
-            debug!("visit_struct_field: st={:?}", self.st);
-            SawStructField.hash(self.st); visit::walk_struct_field(self, s)
-        }
-
-        fn visit_path(&mut self, path: &'a Path, _: ast::NodeId) {
-            debug!("visit_path: st={:?}", self.st);
-            SawPath.hash(self.st); visit::walk_path(self, path)
-        }
-
-        fn visit_block(&mut self, b: &'a Block) {
-            debug!("visit_block: st={:?}", self.st);
-            SawBlock.hash(self.st); visit::walk_block(self, b)
-        }
-
-        fn visit_pat(&mut self, p: &'a Pat) {
-            debug!("visit_pat: st={:?}", self.st);
-            SawPat.hash(self.st); visit::walk_pat(self, p)
-        }
-
-        fn visit_local(&mut self, l: &'a Local) {
-            debug!("visit_local: st={:?}", self.st);
-            SawLocal.hash(self.st); visit::walk_local(self, l)
-        }
-
-        fn visit_arm(&mut self, a: &'a Arm) {
-            debug!("visit_arm: st={:?}", self.st);
-            SawArm.hash(self.st); visit::walk_arm(self, a)
-        }
-    }
-}
diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs
new file mode 100644 (file)
index 0000000..d7caf8c
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2012-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.
+
+//! Calculation of a Strict Version Hash for crates.  For a length
+//! comment explaining the general idea, see `librustc/middle/svh.rs`.
+
+use syntax::attr::AttributeMethods;
+use std::hash::{Hash, SipHasher, Hasher};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::map::{NodeItem, NodeForeignItem};
+use rustc::hir::svh::Svh;
+use rustc::ty::TyCtxt;
+use rustc::hir::intravisit::{self, Visitor};
+
+use self::svh_visitor::StrictVersionHashVisitor;
+
+mod svh_visitor;
+
+pub trait SvhCalculate {
+    /// Calculate the SVH for an entire krate.
+    fn calculate_krate_hash(self) -> Svh;
+
+    /// Calculate the SVH for a particular item.
+    fn calculate_item_hash(self, def_id: DefId) -> u64;
+}
+
+impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
+    fn calculate_krate_hash(self) -> Svh {
+        // FIXME (#14132): This is better than it used to be, but it still not
+        // ideal. We now attempt to hash only the relevant portions of the
+        // Crate AST as well as the top-level crate attributes. (However,
+        // the hashing of the crate attributes should be double-checked
+        // to ensure it is not incorporating implementation artifacts into
+        // the hash that are not otherwise visible.)
+
+        let crate_disambiguator = self.sess.local_crate_disambiguator();
+        let krate = self.map.krate();
+
+        // FIXME: this should use SHA1, not SipHash. SipHash is not built to
+        //        avoid collisions.
+        let mut state = SipHasher::new();
+        debug!("state: {:?}", state);
+
+        // FIXME(#32753) -- at (*) we `to_le` for endianness, but is
+        // this enough, and does it matter anyway?
+        "crate_disambiguator".hash(&mut state);
+        crate_disambiguator.len().to_le().hash(&mut state); // (*)
+        crate_disambiguator.hash(&mut state);
+
+        debug!("crate_disambiguator: {:?}", crate_disambiguator);
+        debug!("state: {:?}", state);
+
+        {
+            let mut visit = StrictVersionHashVisitor::new(&mut state, self);
+            krate.visit_all_items(&mut visit);
+        }
+
+        // FIXME (#14132): This hash is still sensitive to e.g. the
+        // spans of the crate Attributes and their underlying
+        // MetaItems; we should make ContentHashable impl for those
+        // types and then use hash_content.  But, since all crate
+        // attributes should appear near beginning of the file, it is
+        // not such a big deal to be sensitive to their spans for now.
+        //
+        // We hash only the MetaItems instead of the entire Attribute
+        // to avoid hashing the AttrId
+        for attr in &krate.attrs {
+            debug!("krate attr {:?}", attr);
+            attr.meta().hash(&mut state);
+        }
+
+        Svh::new(state.finish())
+    }
+
+    fn calculate_item_hash(self, def_id: DefId) -> u64 {
+        assert!(def_id.is_local());
+
+        debug!("calculate_item_hash(def_id={:?})", def_id);
+
+        let mut state = SipHasher::new();
+
+        {
+            let mut visit = StrictVersionHashVisitor::new(&mut state, self);
+            if def_id.index == CRATE_DEF_INDEX {
+                // the crate root itself is not registered in the map
+                // as an item, so we have to fetch it this way
+                let krate = self.map.krate();
+                intravisit::walk_crate(&mut visit, krate);
+            } else {
+                let node_id = self.map.as_local_node_id(def_id).unwrap();
+                match self.map.find(node_id) {
+                    Some(NodeItem(item)) => visit.visit_item(item),
+                    Some(NodeForeignItem(item)) => visit.visit_foreign_item(item),
+                    r => bug!("calculate_item_hash: expected an item for node {} not {:?}",
+                              node_id, r),
+                }
+            }
+        }
+
+        let hash = state.finish();
+
+        debug!("calculate_item_hash: def_id={:?} hash={:?}", def_id, hash);
+
+        hash
+    }
+}
diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs
new file mode 100644 (file)
index 0000000..42e7abe
--- /dev/null
@@ -0,0 +1,439 @@
+// Copyright 2012-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.
+
+// FIXME (#14132): Even this SVH computation still has implementation
+// artifacts: namely, the order of item declaration will affect the
+// hash computation, but for many kinds of items the order of
+// declaration should be irrelevant to the ABI.
+
+pub use self::SawExprComponent::*;
+pub use self::SawStmtComponent::*;
+use self::SawAbiComponent::*;
+use syntax::ast::{self, Name, NodeId};
+use syntax::parse::token;
+use syntax_pos::Span;
+use rustc::hir;
+use rustc::hir::*;
+use rustc::hir::def::{Def, PathResolution};
+use rustc::hir::def_id::DefId;
+use rustc::hir::intravisit as visit;
+use rustc::hir::intravisit::{Visitor, FnKind};
+use rustc::hir::map::DefPath;
+use rustc::ty::TyCtxt;
+
+use std::hash::{Hash, SipHasher};
+
+pub struct StrictVersionHashVisitor<'a, 'tcx: 'a> {
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    pub st: &'a mut SipHasher,
+}
+
+impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
+    pub fn new(st: &'a mut SipHasher,
+               tcx: TyCtxt<'a, 'tcx, 'tcx>)
+               -> Self {
+        StrictVersionHashVisitor { st: st, tcx: tcx }
+    }
+
+    fn hash_def_path(&mut self, path: &DefPath) {
+        path.deterministic_hash_to(self.tcx, self.st);
+    }
+}
+
+// To off-load the bulk of the hash-computation on #[derive(Hash)],
+// we define a set of enums corresponding to the content that our
+// crate visitor will encounter as it traverses the ast.
+//
+// The important invariant is that all of the Saw*Component enums
+// do not carry any Spans, Names, or Idents.
+//
+// Not carrying any Names/Idents is the important fix for problem
+// noted on PR #13948: using the ident.name as the basis for a
+// hash leads to unstable SVH, because ident.name is just an index
+// into intern table (i.e. essentially a random address), not
+// computed from the name content.
+//
+// With the below enums, the SVH computation is not sensitive to
+// artifacts of how rustc was invoked nor of how the source code
+// was laid out.  (Or at least it is *less* sensitive.)
+
+// This enum represents the different potential bits of code the
+// visitor could encounter that could affect the ABI for the crate,
+// and assigns each a distinct tag to feed into the hash computation.
+#[derive(Hash)]
+enum SawAbiComponent<'a> {
+
+    // FIXME (#14132): should we include (some function of)
+    // ident.ctxt as well?
+    SawIdent(token::InternedString),
+    SawStructDef(token::InternedString),
+
+    SawLifetime(token::InternedString),
+    SawLifetimeDef(token::InternedString),
+
+    SawMod,
+    SawForeignItem,
+    SawItem,
+    SawTy,
+    SawGenerics,
+    SawFn,
+    SawTraitItem,
+    SawImplItem,
+    SawStructField,
+    SawVariant,
+    SawPath,
+    SawBlock,
+    SawPat,
+    SawLocal,
+    SawArm,
+    SawExpr(SawExprComponent<'a>),
+    SawStmt(SawStmtComponent),
+}
+
+/// SawExprComponent carries all of the information that we want
+/// to include in the hash that *won't* be covered by the
+/// subsequent recursive traversal of the expression's
+/// substructure by the visitor.
+///
+/// We know every Expr_ variant is covered by a variant because
+/// `fn saw_expr` maps each to some case below.  Ensuring that
+/// each variant carries an appropriate payload has to be verified
+/// by hand.
+///
+/// (However, getting that *exactly* right is not so important
+/// because the SVH is just a developer convenience; there is no
+/// guarantee of collision-freedom, hash collisions are just
+/// (hopefully) unlikely.)
+#[derive(Hash)]
+pub enum SawExprComponent<'a> {
+
+    SawExprLoop(Option<token::InternedString>),
+    SawExprField(token::InternedString),
+    SawExprTupField(usize),
+    SawExprBreak(Option<token::InternedString>),
+    SawExprAgain(Option<token::InternedString>),
+
+    SawExprBox,
+    SawExprVec,
+    SawExprCall,
+    SawExprMethodCall,
+    SawExprTup,
+    SawExprBinary(hir::BinOp_),
+    SawExprUnary(hir::UnOp),
+    SawExprLit(ast::LitKind),
+    SawExprCast,
+    SawExprType,
+    SawExprIf,
+    SawExprWhile,
+    SawExprMatch,
+    SawExprClosure,
+    SawExprBlock,
+    SawExprAssign,
+    SawExprAssignOp(hir::BinOp_),
+    SawExprIndex,
+    SawExprPath(Option<usize>),
+    SawExprAddrOf(hir::Mutability),
+    SawExprRet,
+    SawExprInlineAsm(&'a hir::InlineAsm),
+    SawExprStruct,
+    SawExprRepeat,
+}
+
+fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
+    match *node {
+        ExprBox(..)              => SawExprBox,
+        ExprVec(..)              => SawExprVec,
+        ExprCall(..)             => SawExprCall,
+        ExprMethodCall(..)       => SawExprMethodCall,
+        ExprTup(..)              => SawExprTup,
+        ExprBinary(op, _, _)     => SawExprBinary(op.node),
+        ExprUnary(op, _)         => SawExprUnary(op),
+        ExprLit(ref lit)         => SawExprLit(lit.node.clone()),
+        ExprCast(..)             => SawExprCast,
+        ExprType(..)             => SawExprType,
+        ExprIf(..)               => SawExprIf,
+        ExprWhile(..)            => SawExprWhile,
+        ExprLoop(_, id)          => SawExprLoop(id.map(|id| id.node.as_str())),
+        ExprMatch(..)            => SawExprMatch,
+        ExprClosure(..)          => SawExprClosure,
+        ExprBlock(..)            => SawExprBlock,
+        ExprAssign(..)           => SawExprAssign,
+        ExprAssignOp(op, _, _)   => SawExprAssignOp(op.node),
+        ExprField(_, name)       => SawExprField(name.node.as_str()),
+        ExprTupField(_, id)      => SawExprTupField(id.node),
+        ExprIndex(..)            => SawExprIndex,
+        ExprPath(ref qself, _)   => SawExprPath(qself.as_ref().map(|q| q.position)),
+        ExprAddrOf(m, _)         => SawExprAddrOf(m),
+        ExprBreak(id)            => SawExprBreak(id.map(|id| id.node.as_str())),
+        ExprAgain(id)            => SawExprAgain(id.map(|id| id.node.as_str())),
+        ExprRet(..)              => SawExprRet,
+        ExprInlineAsm(ref a,_,_) => SawExprInlineAsm(a),
+        ExprStruct(..)           => SawExprStruct,
+        ExprRepeat(..)           => SawExprRepeat,
+    }
+}
+
+/// SawStmtComponent is analogous to SawExprComponent, but for statements.
+#[derive(Hash)]
+pub enum SawStmtComponent {
+    SawStmtExpr,
+    SawStmtSemi,
+}
+
+impl<'a, 'tcx> Visitor<'a> for StrictVersionHashVisitor<'a, 'tcx> {
+    fn visit_nested_item(&mut self, _: ItemId) {
+        // Each item is hashed independently; ignore nested items.
+    }
+
+    fn visit_variant_data(&mut self, s: &'a VariantData, name: Name,
+                          g: &'a Generics, _: NodeId, _: Span) {
+        debug!("visit_variant_data: st={:?}", self.st);
+        SawStructDef(name.as_str()).hash(self.st);
+        visit::walk_generics(self, g);
+        visit::walk_struct_def(self, s)
+    }
+
+    fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
+        debug!("visit_variant: st={:?}", self.st);
+        SawVariant.hash(self.st);
+        // walk_variant does not call walk_generics, so do it here.
+        visit::walk_generics(self, g);
+        visit::walk_variant(self, v, g, item_id)
+    }
+
+    // All of the remaining methods just record (in the hash
+    // SipHasher) that the visitor saw that particular variant
+    // (with its payload), and continue walking as the default
+    // visitor would.
+    //
+    // Some of the implementations have some notes as to how one
+    // might try to make their SVH computation less discerning
+    // (e.g. by incorporating reachability analysis).  But
+    // currently all of their implementations are uniform and
+    // uninteresting.
+    //
+    // (If you edit a method such that it deviates from the
+    // pattern, please move that method up above this comment.)
+
+    fn visit_name(&mut self, _: Span, name: Name) {
+        debug!("visit_name: st={:?}", self.st);
+        SawIdent(name.as_str()).hash(self.st);
+    }
+
+    fn visit_lifetime(&mut self, l: &'a Lifetime) {
+        debug!("visit_lifetime: st={:?}", self.st);
+        SawLifetime(l.name.as_str()).hash(self.st);
+    }
+
+    fn visit_lifetime_def(&mut self, l: &'a LifetimeDef) {
+        debug!("visit_lifetime_def: st={:?}", self.st);
+        SawLifetimeDef(l.lifetime.name.as_str()).hash(self.st);
+    }
+
+    // We do recursively walk the bodies of functions/methods
+    // (rather than omitting their bodies from the hash) since
+    // monomorphization and cross-crate inlining generally implies
+    // that a change to a crate body will require downstream
+    // crates to be recompiled.
+    fn visit_expr(&mut self, ex: &'a Expr) {
+        debug!("visit_expr: st={:?}", self.st);
+        SawExpr(saw_expr(&ex.node)).hash(self.st); visit::walk_expr(self, ex)
+    }
+
+    fn visit_stmt(&mut self, s: &'a Stmt) {
+        debug!("visit_stmt: st={:?}", self.st);
+
+        // We don't want to modify the hash for decls, because
+        // they might be item decls (if they are local decls,
+        // we'll hash that fact in visit_local); but we do want to
+        // remember if this was a StmtExpr or StmtSemi (the later
+        // had an explicit semi-colon; this affects the typing
+        // rules).
+        match s.node {
+            StmtDecl(..) => (),
+            StmtExpr(..) => SawStmt(SawStmtExpr).hash(self.st),
+            StmtSemi(..) => SawStmt(SawStmtSemi).hash(self.st),
+        }
+
+        visit::walk_stmt(self, s)
+    }
+
+    fn visit_foreign_item(&mut self, i: &'a ForeignItem) {
+        debug!("visit_foreign_item: st={:?}", self.st);
+
+        // FIXME (#14132) ideally we would incorporate privacy (or
+        // perhaps reachability) somewhere here, so foreign items
+        // that do not leak into downstream crates would not be
+        // part of the ABI.
+        SawForeignItem.hash(self.st); visit::walk_foreign_item(self, i)
+    }
+
+    fn visit_item(&mut self, i: &'a Item) {
+        debug!("visit_item: {:?} st={:?}", i, self.st);
+
+        // FIXME (#14132) ideally would incorporate reachability
+        // analysis somewhere here, so items that never leak into
+        // downstream crates (e.g. via monomorphisation or
+        // inlining) would not be part of the ABI.
+        SawItem.hash(self.st); visit::walk_item(self, i)
+    }
+
+    fn visit_mod(&mut self, m: &'a Mod, _s: Span, n: NodeId) {
+        debug!("visit_mod: st={:?}", self.st);
+        SawMod.hash(self.st); visit::walk_mod(self, m, n)
+    }
+
+    fn visit_ty(&mut self, t: &'a Ty) {
+        debug!("visit_ty: st={:?}", self.st);
+        SawTy.hash(self.st); visit::walk_ty(self, t)
+    }
+
+    fn visit_generics(&mut self, g: &'a Generics) {
+        debug!("visit_generics: st={:?}", self.st);
+        SawGenerics.hash(self.st); visit::walk_generics(self, g)
+    }
+
+    fn visit_fn(&mut self, fk: FnKind<'a>, fd: &'a FnDecl,
+                b: &'a Block, s: Span, n: NodeId) {
+        debug!("visit_fn: st={:?}", self.st);
+        SawFn.hash(self.st); visit::walk_fn(self, fk, fd, b, s, n)
+    }
+
+    fn visit_trait_item(&mut self, ti: &'a TraitItem) {
+        debug!("visit_trait_item: st={:?}", self.st);
+        SawTraitItem.hash(self.st); visit::walk_trait_item(self, ti)
+    }
+
+    fn visit_impl_item(&mut self, ii: &'a ImplItem) {
+        debug!("visit_impl_item: st={:?}", self.st);
+        SawImplItem.hash(self.st); visit::walk_impl_item(self, ii)
+    }
+
+    fn visit_struct_field(&mut self, s: &'a StructField) {
+        debug!("visit_struct_field: st={:?}", self.st);
+        SawStructField.hash(self.st); visit::walk_struct_field(self, s)
+    }
+
+    fn visit_path(&mut self, path: &'a Path, _: ast::NodeId) {
+        debug!("visit_path: st={:?}", self.st);
+        SawPath.hash(self.st); visit::walk_path(self, path)
+    }
+
+    fn visit_block(&mut self, b: &'a Block) {
+        debug!("visit_block: st={:?}", self.st);
+        SawBlock.hash(self.st); visit::walk_block(self, b)
+    }
+
+    fn visit_pat(&mut self, p: &'a Pat) {
+        debug!("visit_pat: st={:?}", self.st);
+        SawPat.hash(self.st); visit::walk_pat(self, p)
+    }
+
+    fn visit_local(&mut self, l: &'a Local) {
+        debug!("visit_local: st={:?}", self.st);
+        SawLocal.hash(self.st); visit::walk_local(self, l)
+    }
+
+    fn visit_arm(&mut self, a: &'a Arm) {
+        debug!("visit_arm: st={:?}", self.st);
+        SawArm.hash(self.st); visit::walk_arm(self, a)
+    }
+
+    fn visit_id(&mut self, id: NodeId) {
+        debug!("visit_id: id={} st={:?}", id, self.st);
+        self.hash_resolve(id);
+    }
+}
+
+#[derive(Hash)]
+pub enum DefHash {
+    SawDefId,
+    SawLabel,
+    SawPrimTy,
+    SawSelfTy,
+    SawErr,
+}
+
+impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
+    fn hash_resolve(&mut self, id: ast::NodeId) {
+        // Because whether or not a given id has an entry is dependent
+        // solely on expr variant etc, we don't need to hash whether
+        // or not an entry was present (we are already hashing what
+        // variant it is above when we visit the HIR).
+
+        if let Some(def) = self.tcx.def_map.borrow().get(&id) {
+            self.hash_partial_def(def);
+        }
+
+        if let Some(traits) = self.tcx.trait_map.get(&id) {
+            traits.len().hash(self.st);
+            for candidate in traits {
+                self.hash_def_id(candidate.def_id);
+            }
+        }
+    }
+
+    fn hash_def_id(&mut self, def_id: DefId) {
+        let def_path = self.tcx.def_path(def_id);
+        self.hash_def_path(&def_path);
+    }
+
+    fn hash_partial_def(&mut self, def: &PathResolution) {
+        self.hash_def(def.base_def);
+        def.depth.hash(self.st);
+    }
+
+    fn hash_def(&mut self, def: Def) {
+        match def {
+            // Crucial point: for all of these variants, the variant +
+            // add'l data that is added is always the same if the
+            // def-id is the same, so it suffices to hash the def-id
+            Def::Fn(..) |
+            Def::Mod(..) |
+            Def::ForeignMod(..) |
+            Def::Static(..) |
+            Def::Variant(..) |
+            Def::Enum(..) |
+            Def::TyAlias(..) |
+            Def::AssociatedTy(..) |
+            Def::TyParam(..) |
+            Def::Struct(..) |
+            Def::Trait(..) |
+            Def::Method(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Upvar(..) => {
+                DefHash::SawDefId.hash(self.st);
+                self.hash_def_id(def.def_id());
+            }
+
+            Def::Label(..) => {
+                DefHash::SawLabel.hash(self.st);
+                // we don't encode the `id` because it always refers to something
+                // within this item, so if it changed, there would have to be other
+                // changes too
+            }
+            Def::PrimTy(ref prim_ty) => {
+                DefHash::SawPrimTy.hash(self.st);
+                prim_ty.hash(self.st);
+            }
+            Def::SelfTy(..) => {
+                DefHash::SawSelfTy.hash(self.st);
+                // the meaning of Self is always the same within a
+                // given context, so we don't need to hash the other
+                // fields
+            }
+            Def::Err => {
+                DefHash::SawErr.hash(self.st);
+            }
+        }
+    }
+}
index 95e9a16f29bbe927db40164283e00576231eb789..12f3ed8ae2bd4caefa6e1e32c3695ebd093e890d 100644 (file)
@@ -19,7 +19,6 @@
 /// Data for use when recompiling the **current crate**.
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedDepGraph {
-    pub nodes: Vec<DepNode<DefPathIndex>>,
     pub edges: Vec<SerializedEdge>,
 
     /// These are hashes of two things:
@@ -44,15 +43,22 @@ pub struct SerializedDepGraph {
     pub hashes: Vec<SerializedHash>,
 }
 
+/// Represents a "reduced" dependency edge. Unlike the full dep-graph,
+/// the dep-graph we serialize contains only edges `S -> T` where the
+/// source `S` is something hashable (a HIR node or foreign metadata)
+/// and the target `T` is something significant, like a work-product.
+/// Normally, significant nodes are only those that have saved data on
+/// disk, but in unit-testing the set of significant nodes can be
+/// increased.
 pub type SerializedEdge = (DepNode<DefPathIndex>, DepNode<DefPathIndex>);
 
 #[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct SerializedHash {
-    /// node being hashed; either a Hir or MetaData variant, in
-    /// practice
-    pub node: DepNode<DefPathIndex>,
+    /// def-id of thing being hashed
+    pub dep_node: DepNode<DefPathIndex>,
 
-    /// the hash itself, computed by `calculate_item_hash`
+    /// the hash as of previous compilation, computed by code in
+    /// `hash` module
     pub hash: u64,
 }
 
index 2fd6973909a8ec59c33a146658b60913049be8a2..084b6714b67b95544ff0e98fd5b4b70bef1f74f3 100644 (file)
 use rustc::dep_graph::DepNode;
 use rustc::hir::map::DefPath;
 use rustc::hir::def_id::DefId;
+use rustc::middle::cstore::LOCAL_CRATE;
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::DefIdMap;
 use std::fmt::{self, Debug};
+use std::iter::once;
+use syntax::ast;
 
 /// Index into the DefIdDirectory
 #[derive(Copy, Clone, Debug, PartialOrd, Ord, Hash, PartialEq, Eq,
@@ -31,17 +34,79 @@ pub struct DefPathIndex {
 pub struct DefIdDirectory {
     // N.B. don't use Removable here because these def-ids are loaded
     // directly without remapping, so loading them should not fail.
-    paths: Vec<DefPath>
+    paths: Vec<DefPath>,
+
+    // For each crate, saves the crate-name/disambiguator so that
+    // later we can match crate-numbers up again.
+    krates: Vec<CrateInfo>,
+}
+
+#[derive(Debug, RustcEncodable, RustcDecodable)]
+pub struct CrateInfo {
+    krate: ast::CrateNum,
+    name: String,
+    disambiguator: String,
 }
 
 impl DefIdDirectory {
-    pub fn new() -> DefIdDirectory {
-        DefIdDirectory { paths: vec![] }
+    pub fn new(krates: Vec<CrateInfo>) -> DefIdDirectory {
+        DefIdDirectory { paths: vec![], krates: krates }
+    }
+
+    fn max_current_crate(&self, tcx: TyCtxt) -> ast::CrateNum {
+        tcx.sess.cstore.crates()
+                       .into_iter()
+                       .max()
+                       .unwrap_or(LOCAL_CRATE)
+    }
+
+    /// Returns a string form for `index`; useful for debugging
+    pub fn def_path_string(&self, tcx: TyCtxt, index: DefPathIndex) -> String {
+        let path = &self.paths[index.index as usize];
+        if self.krate_still_valid(tcx, self.max_current_crate(tcx), path.krate) {
+            path.to_string(tcx)
+        } else {
+            format!("<crate {} changed>", path.krate)
+        }
+    }
+
+    pub fn krate_still_valid(&self,
+                             tcx: TyCtxt,
+                             max_current_crate: ast::CrateNum,
+                             krate: ast::CrateNum) -> bool {
+        // Check that the crate-number still matches. For now, if it
+        // doesn't, just return None. We could do better, such as
+        // finding the new number.
+
+        if krate > max_current_crate {
+            false
+        } else {
+            let old_info = &self.krates[krate as usize];
+            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);
+            old_name == new_name && old_disambiguator == new_disambiguator
+        }
     }
 
     pub fn retrace(&self, tcx: TyCtxt) -> RetracedDefIdDirectory {
+        let max_current_crate = self.max_current_crate(tcx);
+
         let ids = self.paths.iter()
-                            .map(|path| tcx.retrace_path(path))
+                            .map(|path| {
+                                if self.krate_still_valid(tcx, max_current_crate, path.krate) {
+                                    tcx.retrace_path(path)
+                                } else {
+                                    debug!("crate {} changed from {:?} to {:?}/{:?}",
+                                           path.krate,
+                                           self.krates[path.krate as usize],
+                                           tcx.crate_name(path.krate),
+                                           tcx.crate_disambiguator(path.krate));
+                                    None
+                                }
+                            })
                             .collect();
         RetracedDefIdDirectory { ids: ids }
     }
@@ -70,10 +135,26 @@ pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
 
 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
+        let mut krates: Vec<_> =
+            once(LOCAL_CRATE)
+            .chain(tcx.sess.cstore.crates())
+            .map(|krate| {
+                CrateInfo {
+                    krate: krate,
+                    name: tcx.crate_name(krate).to_string(),
+                    disambiguator: tcx.crate_disambiguator(krate).to_string()
+                }
+            })
+            .collect();
+
+        // the result of crates() is not in order, so sort list of
+        // crates so that we can just index it later
+        krates.sort_by_key(|k| k.krate);
+
         DefIdDirectoryBuilder {
             tcx: tcx,
             hash: DefIdMap(),
-            directory: DefIdDirectory::new()
+            directory: DefIdDirectory::new(krates),
         }
     }
 
@@ -91,12 +172,17 @@ pub fn add(&mut self, def_id: DefId) -> DefPathIndex {
                  .clone()
     }
 
+    pub fn lookup_def_path(&self, id: DefPathIndex) -> &DefPath {
+        &self.directory.paths[id.index as usize]
+    }
+
+
     pub fn map(&mut self, node: &DepNode<DefId>) -> DepNode<DefPathIndex> {
         node.map_def(|&def_id| Some(self.add(def_id))).unwrap()
     }
 
-    pub fn into_directory(self) -> DefIdDirectory {
-        self.directory
+    pub fn directory(&self) -> &DefIdDirectory {
+        &self.directory
     }
 }
 
index dee4d667b8d95c6b1a23b740455cda4e2d58d2b8..3c77cc07d3d89283b37a1feda18444e8309618c7 100644 (file)
 //! Errors are reported if we are in the suitable configuration but
 //! the required condition is not met.
 
+use super::directory::RetracedDefIdDirectory;
+use super::load::DirtyNodes;
 use rustc::dep_graph::{DepGraphQuery, DepNode};
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::Visitor;
+use rustc_data_structures::fnv::FnvHashSet;
 use syntax::ast::{self, Attribute, MetaItem};
 use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::InternedString;
 const LABEL: &'static str = "label";
 const CFG: &'static str = "cfg";
 
-pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                               dirty_inputs: &DirtyNodes,
+                                               retraced: &RetracedDefIdDirectory) {
+    // can't add `#[rustc_dirty]` etc without opting in to this feature
+    if !tcx.sess.features.borrow().rustc_attrs {
+        return;
+    }
+
     let _ignore = tcx.dep_graph.in_ignore();
+    let dirty_inputs: FnvHashSet<DepNode<DefId>> =
+        dirty_inputs.iter()
+                   .filter_map(|d| retraced.map(d))
+                   .collect();
     let query = tcx.dep_graph.query();
+    debug!("query-nodes: {:?}", query.nodes());
     let krate = tcx.map.krate();
     krate.visit_all_items(&mut DirtyCleanVisitor {
         tcx: tcx,
         query: &query,
+        dirty_inputs: dirty_inputs,
     });
 }
 
 pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     query: &'a DepGraphQuery<DefId>,
+    dirty_inputs: FnvHashSet<DepNode<DefId>>,
 }
 
 impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
@@ -81,10 +98,13 @@ fn check_config(&self, attr: &ast::Attribute) -> bool {
                         return true;
                     }
                 }
+                return false;
             }
         }
-        debug!("check_config: no match found");
-        return false;
+
+        self.tcx.sess.span_fatal(
+            attr.span,
+            &format!("no cfg attribute"));
     }
 
     fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
@@ -105,29 +125,62 @@ fn dep_node(&self, attr: &Attribute, def_id: DefId) -> DepNode<DefId> {
         self.tcx.sess.span_fatal(attr.span, "no `label` found");
     }
 
-    fn dep_node_str(&self, dep_node: DepNode<DefId>) -> DepNode<String> {
+    fn dep_node_str(&self, dep_node: &DepNode<DefId>) -> DepNode<String> {
         dep_node.map_def(|&def_id| Some(self.tcx.item_path_str(def_id))).unwrap()
     }
 
     fn assert_dirty(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
         debug!("assert_dirty({:?})", dep_node);
 
-        if self.query.contains_node(&dep_node) {
-            let dep_node_str = self.dep_node_str(dep_node);
-            self.tcx.sess.span_err(
-                item.span,
-                &format!("`{:?}` found in dep graph, but should be dirty", dep_node_str));
+        match dep_node {
+            DepNode::Hir(_) => {
+                // HIR nodes are inputs, so if we are asserting that the HIR node is
+                // dirty, we check the dirty input set.
+                if !self.dirty_inputs.contains(&dep_node) {
+                    let dep_node_str = self.dep_node_str(&dep_node);
+                    self.tcx.sess.span_err(
+                        item.span,
+                        &format!("`{:?}` not found in dirty set, but should be dirty",
+                                 dep_node_str));
+                }
+            }
+            _ => {
+                // Other kinds of nodes would be targets, so check if
+                // the dep-graph contains the node.
+                if self.query.contains_node(&dep_node) {
+                    let dep_node_str = self.dep_node_str(&dep_node);
+                    self.tcx.sess.span_err(
+                        item.span,
+                        &format!("`{:?}` found in dep graph, but should be dirty", dep_node_str));
+                }
+            }
         }
     }
 
     fn assert_clean(&self, item: &hir::Item, dep_node: DepNode<DefId>) {
         debug!("assert_clean({:?})", dep_node);
 
-        if !self.query.contains_node(&dep_node) {
-            let dep_node_str = self.dep_node_str(dep_node);
-            self.tcx.sess.span_err(
-                item.span,
-                &format!("`{:?}` not found in dep graph, but should be clean", dep_node_str));
+        match dep_node {
+            DepNode::Hir(_) => {
+                // For HIR nodes, check the inputs.
+                if self.dirty_inputs.contains(&dep_node) {
+                    let dep_node_str = self.dep_node_str(&dep_node);
+                    self.tcx.sess.span_err(
+                        item.span,
+                        &format!("`{:?}` found in dirty-node set, but should be clean",
+                                 dep_node_str));
+                }
+            }
+            _ => {
+                // Otherwise, check if the dep-node exists.
+                if !self.query.contains_node(&dep_node) {
+                    let dep_node_str = self.dep_node_str(&dep_node);
+                    self.tcx.sess.span_err(
+                        item.span,
+                        &format!("`{:?}` not found in dep graph, but should be clean",
+                                 dep_node_str));
+                }
+            }
         }
     }
 }
index 99119dd184c8b3929045d5e75afa08134e3a776a..344b05f095457ec4d5e2c6eccce7bf0b31afab94 100644 (file)
@@ -39,12 +39,19 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         }
     }
 
-    pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> {
+    pub fn is_hashable(dep_node: &DepNode<DefId>) -> bool {
+        match *dep_node {
+            DepNode::Hir(_) => true,
+            DepNode::MetaData(def_id) => !def_id.is_local(),
+            _ => false,
+        }
+    }
+
+    pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<(DefId, u64)> {
         match *dep_node {
             // HIR nodes (which always come from our crate) are an input:
             DepNode::Hir(def_id) => {
-                assert!(def_id.is_local());
-                Some(self.hir_hash(def_id))
+                Some((def_id, self.hir_hash(def_id)))
             }
 
             // MetaData from other crates is an *input* to us.
@@ -52,7 +59,7 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> {
             // don't hash them, but we do compute a hash for them and
             // save it for others to use.
             DepNode::MetaData(def_id) if !def_id.is_local() => {
-                Some(self.metadata_hash(def_id))
+                Some((def_id, self.metadata_hash(def_id)))
             }
 
             _ => {
@@ -66,7 +73,16 @@ pub fn hash(&mut self, dep_node: &DepNode<DefId>) -> Option<u64> {
     }
 
     fn hir_hash(&mut self, def_id: DefId) -> u64 {
-        assert!(def_id.is_local());
+        assert!(def_id.is_local(),
+                "cannot hash HIR for non-local def-id {:?} => {:?}",
+                def_id,
+                self.tcx.item_path_str(def_id));
+
+        assert!(!self.tcx.map.is_inlined_def_id(def_id),
+                "cannot hash HIR for inlined def-id {:?} => {:?}",
+                def_id,
+                self.tcx.item_path_str(def_id));
+
         // FIXME(#32753) -- should we use a distinct hash here
         self.tcx.calculate_item_hash(def_id)
     }
index 36b6c79c40f5dc9379fac023bb43b567d0334198..79b90b63dc608d8b238eea13d3b84ac3f890c9d8 100644 (file)
@@ -28,7 +28,7 @@
 use super::hash::*;
 use super::util::*;
 
-type DirtyNodes = FnvHashSet<DepNode<DefId>>;
+pub type DirtyNodes = FnvHashSet<DepNode<DefPathIndex>>;
 
 type CleanEdges = Vec<(DepNode<DefId>, DepNode<DefId>)>;
 
@@ -45,7 +45,6 @@ pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let _ignore = tcx.dep_graph.in_ignore();
     load_dep_graph_if_exists(tcx);
-    dirty_clean::check_dirty_clean_annotations(tcx);
 }
 
 fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -62,7 +61,7 @@ fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     };
 
     match decode_dep_graph(tcx, &dep_graph_data, &work_products_data) {
-        Ok(()) => return,
+        Ok(dirty_nodes) => dirty_nodes,
         Err(err) => {
             tcx.sess.warn(
                 &format!("decoding error in dep-graph from `{}` and `{}`: {}",
@@ -93,7 +92,6 @@ fn load_data(sess: &Session, path: &Path) -> Option<Vec<u8>> {
             None
         }
     }
-
 }
 
 /// Decode the dep graph and load the edges/nodes that are still clean
@@ -108,143 +106,116 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let directory = try!(DefIdDirectory::decode(&mut dep_graph_decoder));
     let serialized_dep_graph = try!(SerializedDepGraph::decode(&mut dep_graph_decoder));
 
-    debug!("decode_dep_graph: directory = {:#?}", directory);
-    debug!("decode_dep_graph: serialized_dep_graph = {:#?}", serialized_dep_graph);
-
     // Retrace the paths in the directory to find their current location (if any).
     let retraced = directory.retrace(tcx);
 
-    debug!("decode_dep_graph: retraced = {:#?}", retraced);
-
-    // Compute the set of Hir nodes whose data has changed.
-    let mut dirty_nodes =
-        initial_dirty_nodes(tcx, &serialized_dep_graph.hashes, &retraced);
-
-    debug!("decode_dep_graph: initial dirty_nodes = {:#?}", dirty_nodes);
+    // Compute the set of Hir nodes whose data has changed or which
+    // have been removed.  These are "raw" source nodes, which means
+    // that they still use the original `DefPathIndex` values from the
+    // encoding, rather than having been retraced to a `DefId`. The
+    // reason for this is that this way we can include nodes that have
+    // been removed (which no longer have a `DefId` in the current
+    // compilation).
+    let dirty_raw_source_nodes = dirty_nodes(tcx, &serialized_dep_graph.hashes, &retraced);
+
+    // Create a list of (raw-source-node ->
+    // retracted-target-node) edges. In the process of retracing the
+    // target nodes, we may discover some of them def-paths no longer exist,
+    // in which case there is no need to mark the corresopnding nodes as dirty
+    // (they are just not present). So this list may be smaller than the original.
+    //
+    // Note though that in the common case the target nodes are
+    // `DepNode::WorkProduct` instances, and those don't have a
+    // def-id, so they will never be considered to not exist. Instead,
+    // we do a secondary hashing step (later, in trans) when we know
+    // the set of symbols that go into a work-product: if any symbols
+    // have been removed (or added) the hash will be different and
+    // we'll ignore the work-product then.
+    let retraced_edges: Vec<_> =
+        serialized_dep_graph.edges.iter()
+                                  .filter_map(|&(ref raw_source_node, ref raw_target_node)| {
+                                      retraced.map(raw_target_node)
+                                              .map(|target_node| (raw_source_node, target_node))
+                                  })
+                                  .collect();
+
+    // Compute which work-products have an input that has changed or
+    // been removed. Put the dirty ones into a set.
+    let mut dirty_target_nodes = FnvHashSet();
+    for &(raw_source_node, ref target_node) in &retraced_edges {
+        if dirty_raw_source_nodes.contains(raw_source_node) {
+            if !dirty_target_nodes.contains(target_node) {
+                dirty_target_nodes.insert(target_node.clone());
+
+                if tcx.sess.opts.debugging_opts.incremental_info {
+                    // It'd be nice to pretty-print these paths better than just
+                    // using the `Debug` impls, but wev.
+                    println!("module {:?} is dirty because {:?} changed or was removed",
+                             target_node,
+                             raw_source_node.map_def(|&index| {
+                                 Some(directory.def_path_string(tcx, index))
+                             }).unwrap());
+                }
+            }
+        }
+    }
 
-    // Find all DepNodes reachable from that core set. This loop
-    // iterates repeatedly over the list of edges whose source is not
-    // known to be dirty (`clean_edges`). If it finds an edge whose
-    // source is dirty, it removes it from that list and adds the
-    // target to `dirty_nodes`. It stops when it reaches a fixed
-    // point.
-    let clean_edges = compute_clean_edges(&serialized_dep_graph.edges,
-                                          &retraced,
-                                          &mut dirty_nodes);
+    // For work-products that are still clean, add their deps into the
+    // graph. This is needed because later we will have to save this
+    // back out again!
+    let dep_graph = tcx.dep_graph.clone();
+    for (raw_source_node, target_node) in retraced_edges {
+        if dirty_target_nodes.contains(&target_node) {
+            continue;
+        }
 
-    // Add synthetic `foo->foo` edges for each clean node `foo` that
-    // we had before. This is sort of a hack to create clean nodes in
-    // the graph, since the existence of a node is a signal that the
-    // work it represents need not be repeated.
-    let clean_nodes =
-        serialized_dep_graph.nodes
-                            .iter()
-                            .filter_map(|node| retraced.map(node))
-                            .filter(|node| !dirty_nodes.contains(node))
-                            .map(|node| (node.clone(), node));
+        let source_node = retraced.map(raw_source_node).unwrap();
 
-    // Add nodes and edges that are not dirty into our main graph.
-    let dep_graph = tcx.dep_graph.clone();
-    for (source, target) in clean_edges.into_iter().chain(clean_nodes) {
-        debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source, target);
+        debug!("decode_dep_graph: clean edge: {:?} -> {:?}", source_node, target_node);
 
-        let _task = dep_graph.in_task(target);
-        dep_graph.read(source);
+        let _task = dep_graph.in_task(target_node);
+        dep_graph.read(source_node);
     }
 
     // Add in work-products that are still clean, and delete those that are
     // dirty.
     let mut work_product_decoder = Decoder::new(work_products_data, 0);
     let work_products = try!(<Vec<SerializedWorkProduct>>::decode(&mut work_product_decoder));
-    reconcile_work_products(tcx, work_products, &dirty_nodes);
+    reconcile_work_products(tcx, work_products, &dirty_target_nodes);
+
+    dirty_clean::check_dirty_clean_annotations(tcx, &dirty_raw_source_nodes, &retraced);
 
     Ok(())
 }
 
-fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 hashes: &[SerializedHash],
-                                 retraced: &RetracedDefIdDirectory)
-                                 -> DirtyNodes {
+/// Computes which of the original set of def-ids are dirty. Stored in
+/// a bit vector where the index is the DefPathIndex.
+fn dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         hashes: &[SerializedHash],
+                         retraced: &RetracedDefIdDirectory)
+                         -> DirtyNodes {
     let mut hcx = HashContext::new(tcx);
-    let mut items_removed = false;
     let mut dirty_nodes = FnvHashSet();
-    for hash in hashes {
-        match hash.node.map_def(|&i| retraced.def_id(i)) {
-            Some(dep_node) => {
-                let current_hash = hcx.hash(&dep_node).unwrap();
-                if current_hash != hash.hash {
-                    debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
-                           dep_node, current_hash, hash.hash);
-                    dirty_nodes.insert(dep_node);
-                }
-            }
-            None => {
-                items_removed = true;
-            }
-        }
-    }
-
-    // If any of the items in the krate have changed, then we consider
-    // the meta-node `Krate` to be dirty, since that means something
-    // which (potentially) read the contents of every single item.
-    if items_removed || !dirty_nodes.is_empty() {
-        dirty_nodes.insert(DepNode::Krate);
-    }
 
-    dirty_nodes
-}
-
-fn compute_clean_edges(serialized_edges: &[(SerializedEdge)],
-                       retraced: &RetracedDefIdDirectory,
-                       dirty_nodes: &mut DirtyNodes)
-                       -> CleanEdges {
-    // Build up an initial list of edges. Include an edge (source,
-    // target) if neither node has been removed. If the source has
-    // been removed, add target to the list of dirty nodes.
-    let mut clean_edges = Vec::with_capacity(serialized_edges.len());
-    for &(ref serialized_source, ref serialized_target) in serialized_edges {
-        if let Some(target) = retraced.map(serialized_target) {
-            if let Some(source) = retraced.map(serialized_source) {
-                clean_edges.push((source, target))
-            } else {
-                // source removed, target must be dirty
-                debug!("compute_clean_edges: {:?} dirty because {:?} no longer exists",
-                       target, serialized_source);
-                dirty_nodes.insert(target);
+    for hash in hashes {
+        if let Some(dep_node) = retraced.map(&hash.dep_node) {
+            let (_, current_hash) = hcx.hash(&dep_node).unwrap();
+            if current_hash == hash.hash {
+                continue;
             }
+            debug!("initial_dirty_nodes: {:?} is dirty as hash is {:?}, was {:?}",
+                   dep_node.map_def(|&def_id| Some(tcx.def_path(def_id))).unwrap(),
+                   current_hash,
+                   hash.hash);
         } else {
-            // target removed, ignore the edge
+            debug!("initial_dirty_nodes: {:?} is dirty as it was removed",
+                   hash.dep_node);
         }
-    }
 
-    debug!("compute_clean_edges: dirty_nodes={:#?}", dirty_nodes);
-
-    // Propagate dirty marks by iterating repeatedly over
-    // `clean_edges`. If we find an edge `(source, target)` where
-    // `source` is dirty, add `target` to the list of dirty nodes and
-    // remove it. Keep doing this until we find no more dirty nodes.
-    let mut previous_size = 0;
-    while dirty_nodes.len() > previous_size {
-        debug!("compute_clean_edges: previous_size={}", previous_size);
-        previous_size = dirty_nodes.len();
-        let mut i = 0;
-        while i < clean_edges.len() {
-            if dirty_nodes.contains(&clean_edges[i].0) {
-                let (source, target) = clean_edges.swap_remove(i);
-                debug!("compute_clean_edges: dirty source {:?} -> {:?}",
-                       source, target);
-                dirty_nodes.insert(target);
-            } else if dirty_nodes.contains(&clean_edges[i].1) {
-                let (source, target) = clean_edges.swap_remove(i);
-                debug!("compute_clean_edges: dirty target {:?} -> {:?}",
-                       source, target);
-            } else {
-                i += 1;
-            }
-        }
+        dirty_nodes.insert(hash.dep_node.clone());
     }
 
-    clean_edges
+    dirty_nodes
 }
 
 /// Go through the list of work-products produced in the previous run.
@@ -252,11 +223,10 @@ fn compute_clean_edges(serialized_edges: &[(SerializedEdge)],
 /// otherwise no longer applicable.
 fn reconcile_work_products<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      work_products: Vec<SerializedWorkProduct>,
-                                     dirty_nodes: &DirtyNodes) {
+                                     dirty_target_nodes: &FnvHashSet<DepNode<DefId>>) {
     debug!("reconcile_work_products({:?})", work_products);
     for swp in work_products {
-        let dep_node = DepNode::WorkProduct(swp.id.clone());
-        if dirty_nodes.contains(&dep_node) {
+        if dirty_target_nodes.contains(&DepNode::WorkProduct(swp.id.clone())) {
             debug!("reconcile_work_products: dep-node for {:?} is dirty", swp);
             delete_dirty_work_product(tcx, swp);
         } else {
index 1157f494ce604e32c2d9fdd5512416f1c8c967fe..4a042497e044114c3d3421ff777cfa906826f548 100644 (file)
@@ -17,6 +17,7 @@
 mod dirty_clean;
 mod hash;
 mod load;
+mod preds;
 mod save;
 mod util;
 mod work_product;
diff --git a/src/librustc_incremental/persist/preds.rs b/src/librustc_incremental/persist/preds.rs
new file mode 100644 (file)
index 0000000..a82951a
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2012-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.
+
+use rustc::dep_graph::{DepGraphQuery, DepNode};
+use rustc::hir::def_id::DefId;
+use rustc_data_structures::fnv::FnvHashMap;
+use rustc_data_structures::graph::{DepthFirstTraversal, INCOMING, NodeIndex};
+
+use super::hash::*;
+
+/// A data-structure that makes it easy to enumerate the hashable
+/// predecessors of any given dep-node.
+pub struct Predecessors<'query> {
+    // - Keys: dep-nodes that may have work-products, output meta-data
+    //   nodes.
+    // - Values: transitive predecessors of the key that are hashable
+    //   (e.g., HIR nodes, input meta-data nodes)
+    pub inputs: FnvHashMap<&'query DepNode<DefId>, Vec<&'query DepNode<DefId>>>,
+
+    // - Keys: some hashable node
+    // - Values: the hash thereof
+    pub hashes: FnvHashMap<&'query DepNode<DefId>, u64>,
+}
+
+impl<'q> Predecessors<'q> {
+    pub fn new(query: &'q DepGraphQuery<DefId>, hcx: &mut HashContext) -> Self {
+        // Find nodes for which we want to know the full set of preds
+        let mut dfs = DepthFirstTraversal::new(&query.graph, INCOMING);
+        let all_nodes = query.graph.all_nodes();
+        let tcx = hcx.tcx;
+
+        let inputs: FnvHashMap<_, _> = all_nodes.iter()
+            .enumerate()
+            .filter(|&(_, node)| match node.data {
+                DepNode::WorkProduct(_) => true,
+                DepNode::MetaData(ref def_id) => def_id.is_local(),
+
+                // if -Z query-dep-graph is passed, save more extended data
+                // to enable better unit testing
+                DepNode::TypeckItemBody(_) |
+                DepNode::TransCrateItem(_) => tcx.sess.opts.debugging_opts.query_dep_graph,
+
+                _ => false,
+            })
+            .map(|(node_index, node)| {
+                dfs.reset(NodeIndex(node_index));
+                let inputs: Vec<_> = dfs.by_ref()
+                    .map(|i| &all_nodes[i.node_id()].data)
+                    .filter(|d| HashContext::is_hashable(d))
+                    .collect();
+                (&node.data, inputs)
+            })
+            .collect();
+
+        let mut hashes = FnvHashMap();
+        for input in inputs.values().flat_map(|v| v.iter().cloned()) {
+            hashes.entry(input)
+                  .or_insert_with(|| hcx.hash(input).unwrap().1);
+        }
+
+        Predecessors {
+            inputs: inputs,
+            hashes: hashes,
+        }
+    }
+}
index 305250d59623c50d644da6ad3cb3e7de2f538e19..f296cd3172fb0262ea82d7a877a423d012c9260a 100644 (file)
 
 use rbml::opaque::Encoder;
 use rustc::dep_graph::DepNode;
+use rustc::hir::def_id::DefId;
 use rustc::middle::cstore::LOCAL_CRATE;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
-use rustc_serialize::{Encodable as RustcEncodable};
-use std::hash::{Hasher, SipHasher};
+use rustc_data_structures::fnv::FnvHashMap;
+use rustc_serialize::Encodable as RustcEncodable;
+use std::hash::{Hash, Hasher, SipHasher};
 use std::io::{self, Cursor, Write};
 use std::fs::{self, File};
 use std::path::PathBuf;
 use super::data::*;
 use super::directory::*;
 use super::hash::*;
+use super::preds::*;
 use super::util::*;
 
 pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     debug!("save_dep_graph()");
     let _ignore = tcx.dep_graph.in_ignore();
     let sess = tcx.sess;
+    if sess.opts.incremental.is_none() {
+        return;
+    }
     let mut hcx = HashContext::new(tcx);
-    save_in(sess, dep_graph_path(tcx), |e| encode_dep_graph(&mut hcx, e));
-    save_in(sess, metadata_hash_path(tcx, LOCAL_CRATE), |e| encode_metadata_hashes(&mut hcx, e));
+    let mut builder = DefIdDirectoryBuilder::new(tcx);
+    let query = tcx.dep_graph.query();
+    let preds = Predecessors::new(&query, &mut hcx);
+    save_in(sess,
+            dep_graph_path(tcx),
+            |e| encode_dep_graph(&preds, &mut builder, e));
+    save_in(sess,
+            metadata_hash_path(tcx, LOCAL_CRATE),
+            |e| encode_metadata_hashes(tcx, &preds, &mut builder, e));
 }
 
 pub fn save_work_products(sess: &Session, local_crate_name: &str) {
@@ -40,14 +53,12 @@ pub fn save_work_products(sess: &Session, local_crate_name: &str) {
     save_in(sess, path, |e| encode_work_products(sess, e));
 }
 
-fn save_in<F>(sess: &Session,
-              opt_path_buf: Option<PathBuf>,
-              encode: F)
+fn save_in<F>(sess: &Session, opt_path_buf: Option<PathBuf>, encode: F)
     where F: FnOnce(&mut Encoder) -> io::Result<()>
 {
     let path_buf = match opt_path_buf {
         Some(p) => p,
-        None => return
+        None => return,
     };
 
     // FIXME(#32754) lock file?
@@ -55,11 +66,11 @@ fn save_in<F>(sess: &Session,
     // delete the old dep-graph, if any
     if path_buf.exists() {
         match fs::remove_file(&path_buf) {
-            Ok(()) => { }
+            Ok(()) => {}
             Err(err) => {
-                sess.err(
-                    &format!("unable to delete old dep-graph at `{}`: {}",
-                             path_buf.display(), err));
+                sess.err(&format!("unable to delete old dep-graph at `{}`: {}",
+                                  path_buf.display(),
+                                  err));
                 return;
             }
         }
@@ -68,97 +79,106 @@ fn save_in<F>(sess: &Session,
     // generate the data in a memory buffer
     let mut wr = Cursor::new(Vec::new());
     match encode(&mut Encoder::new(&mut wr)) {
-        Ok(()) => { }
+        Ok(()) => {}
         Err(err) => {
-            sess.err(
-                &format!("could not encode dep-graph to `{}`: {}",
-                         path_buf.display(), err));
+            sess.err(&format!("could not encode dep-graph to `{}`: {}",
+                              path_buf.display(),
+                              err));
             return;
         }
     }
 
     // write the data out
     let data = wr.into_inner();
-    match
-        File::create(&path_buf)
-        .and_then(|mut file| file.write_all(&data))
-    {
-        Ok(_) => { }
+    match File::create(&path_buf).and_then(|mut file| file.write_all(&data)) {
+        Ok(_) => {}
         Err(err) => {
-            sess.err(
-                &format!("failed to write dep-graph to `{}`: {}",
-                         path_buf.display(), err));
+            sess.err(&format!("failed to write dep-graph to `{}`: {}",
+                              path_buf.display(),
+                              err));
             return;
         }
     }
 }
 
-pub fn encode_dep_graph<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
-                                  encoder: &mut Encoder)
-                                  -> io::Result<()>
-{
-    let tcx = hcx.tcx;
-    let query = tcx.dep_graph.query();
-
-    let mut builder = DefIdDirectoryBuilder::new(tcx);
-
-    // Create hashes for inputs.
-    let hashes =
-        query.nodes()
-             .into_iter()
-             .filter_map(|dep_node| {
-                 hcx.hash(&dep_node)
-                    .map(|hash| {
-                        let node = builder.map(dep_node);
-                        SerializedHash { node: node, hash: hash }
-                    })
-             })
-             .collect();
+pub fn encode_dep_graph(preds: &Predecessors,
+                        builder: &mut DefIdDirectoryBuilder,
+                        encoder: &mut Encoder)
+                        -> io::Result<()> {
+    // Create a flat list of (Input, WorkProduct) edges for
+    // serialization.
+    let mut edges = vec![];
+    for (&target, sources) in &preds.inputs {
+        match *target {
+            DepNode::MetaData(ref def_id) => {
+                // Metadata *targets* are always local metadata nodes. We handle
+                // those in `encode_metadata_hashes`, which comes later.
+                assert!(def_id.is_local());
+                continue;
+            }
+            _ => (),
+        }
+        let target = builder.map(target);
+        for &source in sources {
+            let source = builder.map(source);
+            edges.push((source, target.clone()));
+        }
+    }
 
     // Create the serialized dep-graph.
     let graph = SerializedDepGraph {
-        nodes: query.nodes().into_iter()
-                            .map(|node| builder.map(node))
-                            .collect(),
-        edges: query.edges().into_iter()
-                            .map(|(source_node, target_node)| {
-                                let source = builder.map(source_node);
-                                let target = builder.map(target_node);
-                                (source, target)
-                            })
-                            .collect(),
-        hashes: hashes,
+        edges: edges,
+        hashes: preds.hashes
+            .iter()
+            .map(|(&dep_node, &hash)| {
+                SerializedHash {
+                    dep_node: builder.map(dep_node),
+                    hash: hash,
+                }
+            })
+            .collect(),
     };
 
     debug!("graph = {:#?}", graph);
 
     // Encode the directory and then the graph data.
-    let directory = builder.into_directory();
-    try!(directory.encode(encoder));
+    try!(builder.directory().encode(encoder));
     try!(graph.encode(encoder));
 
     Ok(())
 }
 
-pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
-                                        encoder: &mut Encoder)
-                                        -> io::Result<()>
-{
-    let tcx = hcx.tcx;
-    let query = tcx.dep_graph.query();
+pub fn encode_metadata_hashes(tcx: TyCtxt,
+                              preds: &Predecessors,
+                              builder: &mut DefIdDirectoryBuilder,
+                              encoder: &mut Encoder)
+                              -> io::Result<()> {
+    let mut def_id_hashes = FnvHashMap();
+    let mut def_id_hash = |def_id: DefId| -> u64 {
+        *def_id_hashes.entry(def_id)
+            .or_insert_with(|| {
+                let index = builder.add(def_id);
+                let path = builder.lookup_def_path(index);
+                path.deterministic_hash(tcx)
+            })
+    };
 
-    let serialized_hashes = {
-        // Identify the `MetaData(X)` nodes where `X` is local. These are
-        // the metadata items we export. Downstream crates will want to
-        // see a hash that tells them whether we might have changed the
-        // metadata for a given item since they last compiled.
-        let meta_data_def_ids =
-            query.nodes()
-                 .into_iter()
-                 .filter_map(|dep_node| match *dep_node {
-                     DepNode::MetaData(def_id) if def_id.is_local() => Some(def_id),
-                     _ => None,
-                 });
+    // For each `MetaData(X)` node where `X` is local, accumulate a
+    // hash.  These are the metadata items we export. Downstream
+    // crates will want to see a hash that tells them whether we might
+    // have changed the metadata for a given item since they last
+    // compiled.
+    //
+    // (I initially wrote this with an iterator, but it seemed harder to read.)
+    let mut serialized_hashes = SerializedMetadataHashes { hashes: vec![] };
+    for (&target, sources) in &preds.inputs {
+        let def_id = match *target {
+            DepNode::MetaData(def_id) => {
+                assert!(def_id.is_local());
+                def_id
+            }
+            _ => continue,
+        };
 
         // To create the hash for each item `X`, we don't hash the raw
         // bytes of the metadata (though in principle we
@@ -166,34 +186,32 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
         // from the dep-graph. This corresponds to all the inputs that
         // were read to construct the metadata. To create the hash for
         // the metadata, we hash (the hash of) all of those inputs.
-        let hashes =
-            meta_data_def_ids
-            .map(|def_id| {
-                assert!(def_id.is_local());
-                let dep_node = DepNode::MetaData(def_id);
-                let mut state = SipHasher::new();
-                debug!("save: computing metadata hash for {:?}", dep_node);
-                for node in query.transitive_predecessors(&dep_node) {
-                    if let Some(hash) = hcx.hash(&node) {
-                        debug!("save: predecessor {:?} has hash {}", node, hash);
-                        state.write_u64(hash.to_le());
-                    } else {
-                        debug!("save: predecessor {:?} cannot be hashed", node);
-                    }
-                }
-                let hash = state.finish();
-                debug!("save: metadata hash for {:?} is {}", dep_node, hash);
-                SerializedMetadataHash {
-                    def_index: def_id.index,
-                    hash: hash,
-                }
-            });
-
-        // Collect these up into a vector.
-        SerializedMetadataHashes {
-            hashes: hashes.collect()
-        }
-    };
+        debug!("save: computing metadata hash for {:?}", def_id);
+
+        // Create a vector containing a pair of (source-id, hash).
+        // The source-id is stored as a `DepNode<u64>`, where the u64
+        // is the det. hash of the def-path. This is convenient
+        // because we can sort this to get a stable ordering across
+        // compilations, even if the def-ids themselves have changed.
+        let mut hashes: Vec<(DepNode<u64>, u64)> = sources.iter()
+            .map(|dep_node| {
+                let hash_dep_node = dep_node.map_def(|&def_id| Some(def_id_hash(def_id))).unwrap();
+                let hash = preds.hashes[dep_node];
+                (hash_dep_node, hash)
+            })
+            .collect();
+
+        hashes.sort();
+        let mut state = SipHasher::new();
+        hashes.hash(&mut state);
+        let hash = state.finish();
+
+        debug!("save: metadata hash for {:?} is {}", def_id, hash);
+        serialized_hashes.hashes.push(SerializedMetadataHash {
+            def_index: def_id.index,
+            hash: hash,
+        });
+    }
 
     // Encode everything.
     try!(serialized_hashes.encode(encoder));
@@ -201,21 +219,17 @@ pub fn encode_metadata_hashes<'a, 'tcx>(hcx: &mut HashContext<'a, 'tcx>,
     Ok(())
 }
 
-pub fn encode_work_products(sess: &Session,
-                            encoder: &mut Encoder)
-                            -> io::Result<()>
-{
-    let work_products: Vec<_> =
-        sess.dep_graph.work_products()
-                     .iter()
-                     .map(|(id, work_product)| {
-                         SerializedWorkProduct {
-                             id: id.clone(),
-                             work_product: work_product.clone(),
-                         }
-                     })
-                     .collect();
+pub fn encode_work_products(sess: &Session, encoder: &mut Encoder) -> io::Result<()> {
+    let work_products: Vec<_> = sess.dep_graph
+        .work_products()
+        .iter()
+        .map(|(id, work_product)| {
+            SerializedWorkProduct {
+                id: id.clone(),
+                work_product: work_product.clone(),
+            }
+        })
+        .collect();
 
     work_products.encode(encoder)
 }
-
index 49dad2d0f6d924653de235ab358a5540f163c512..d8ec79fb0609680de5be956ab554eadc2335d468 100644 (file)
@@ -35,7 +35,7 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::adjustment;
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::hir::map as hir_map;
 use util::nodemap::{NodeSet};
 use lint::{Level, LateContext, LintContext, LintArray, Lint};
@@ -911,7 +911,7 @@ fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let node_id = tcx.map.as_local_node_id(method.def_id).unwrap();
 
                     let param_env = Some(ty::ParameterEnvironment::for_item(tcx, node_id));
-                    tcx.infer_ctxt(None, param_env, ProjectionMode::AnyFinal).enter(|infcx| {
+                    tcx.infer_ctxt(None, param_env, Reveal::NotSpecializable).enter(|infcx| {
                         let mut selcx = traits::SelectionContext::new(&infcx);
                         match selcx.select(&obligation) {
                             // The method comes from a `T: Trait` bound.
index 43376dfd8c2a0ec6dac298f4ba802f5d4caa84d8..cb0036eb5b034fdefb5593defa8762ad31259cf5 100644 (file)
@@ -157,7 +157,7 @@ macro_rules! add_lint_group {
     store.register_future_incompatible(sess, vec![
         FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
-            reference: "the explanation for E0446 (`--explain E0446`)",
+            reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
         },
         FutureIncompatibleInfo {
             id: LintId::of(INACCESSIBLE_EXTERN_CRATE),
index f688bd80ee9dabe95701d425a5a851f09ad65cb8..b9861c309dbec985d3e467eb9c9032219ecbf336 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{Layout, Primitive};
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use middle::const_val::ConstVal;
 use rustc_const_eval::eval_const_expr_partial;
 use rustc_const_eval::EvalHint::ExprTypeChecked;
@@ -596,7 +596,7 @@ fn check_type_for_ffi(&self,
             }
 
             ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
-            ty::TyClosure(..) | ty::TyProjection(..) |
+            ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) |
             ty::TyFnDef(..) => {
                 bug!("Unexpected type in foreign function")
             }
@@ -697,7 +697,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
             if gens.ty_params.is_empty() {  // sizes only make sense for non-generic types
                 let t = cx.tcx.node_id_to_type(it.id);
-                let layout = cx.tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+                let layout = cx.tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
                     let ty = cx.tcx.erase_regions(&t);
                     ty.layout(&infcx).unwrap_or_else(|e| {
                         bug!("failed to get layout for `{}`: {}", t, e)
index b8548aaec5bd74d023d99016d3042f1c220913aa..5f7a0f788ca1289e8da69b9e001289622041af8b 100644 (file)
@@ -112,6 +112,10 @@ fn main() {
         cfg.flag(&flag);
     }
 
+    if env::var_os("LLVM_RUSTLLVM").is_some() {
+        cfg.flag("-DLLVM_RUSTLLVM");
+    }
+
     cfg.file("../rustllvm/PassWrapper.cpp")
        .file("../rustllvm/RustWrapper.cpp")
        .file("../rustllvm/ArchiveWrapper.cpp")
index 6301c57c55540ebe7fe260db96eb82055f33114e..b2ffcac365bad34760351052003f8411d7265fb0 100644 (file)
@@ -1940,6 +1940,9 @@ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef,
     pub fn LLVMRustHasFeature(T: TargetMachineRef,
                               s: *const c_char) -> bool;
 
+    pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef);
+    pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef);
+
     pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
                                        CPU: *const c_char,
                                        Features: *const c_char,
index c39ad414492ed637fd0faa29134e7e504ccea3d7..f03c432c0917791c4a9ca8531517090785b32787 100644 (file)
@@ -78,8 +78,8 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
                            rbml_w: &mut Encoder,
                            ii: InlinedItemRef) {
     let id = match ii {
-        InlinedItemRef::Item(i) => i.id,
-        InlinedItemRef::Foreign(i) => i.id,
+        InlinedItemRef::Item(_, i) => i.id,
+        InlinedItemRef::Foreign(_, i) => i.id,
         InlinedItemRef::TraitItem(_, ti) => ti.id,
         InlinedItemRef::ImplItem(_, ii) => ii.id,
     };
@@ -146,8 +146,8 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata,
                                        decode_ast(ast_doc),
                                        dcx);
     let name = match *ii {
-        InlinedItem::Item(ref i) => i.name,
-        InlinedItem::Foreign(ref i) => i.name,
+        InlinedItem::Item(_, ref i) => i.name,
+        InlinedItem::Foreign(_, ref i) => i.name,
         InlinedItem::TraitItem(_, ref ti) => ti.name,
         InlinedItem::ImplItem(_, ref ii) => ii.name
     };
@@ -158,7 +158,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata,
     region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
     decode_side_tables(dcx, ast_doc);
     copy_item_types(dcx, ii, orig_did);
-    if let InlinedItem::Item(ref i) = *ii {
+    if let InlinedItem::Item(_, ref i) = *ii {
         debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
                ::rustc::hir::print::item_to_string(&i));
     }
@@ -348,8 +348,8 @@ fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) {
 
     let ii = match ii {
         // HACK we're not dropping items.
-        InlinedItemRef::Item(i) => {
-            InlinedItem::Item(P(fold::noop_fold_item(i.clone(), &mut fld)))
+        InlinedItemRef::Item(d, i) => {
+            InlinedItem::Item(d, P(fold::noop_fold_item(i.clone(), &mut fld)))
         }
         InlinedItemRef::TraitItem(d, ti) => {
             InlinedItem::TraitItem(d, P(fold::noop_fold_trait_item(ti.clone(), &mut fld)))
@@ -357,8 +357,8 @@ fn simplify_ast(ii: InlinedItemRef) -> (InlinedItem, IdRange) {
         InlinedItemRef::ImplItem(d, ii) => {
             InlinedItem::ImplItem(d, P(fold::noop_fold_impl_item(ii.clone(), &mut fld)))
         }
-        InlinedItemRef::Foreign(i) => {
-            InlinedItem::Foreign(P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
+        InlinedItemRef::Foreign(d, i) => {
+            InlinedItem::Foreign(d, P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
         }
     };
 
@@ -1241,15 +1241,15 @@ fn copy_item_type(dcx: &DecodeContext,
     }
     // copy the entry for the item itself
     let item_node_id = match ii {
-        &InlinedItem::Item(ref i) => i.id,
+        &InlinedItem::Item(_, ref i) => i.id,
         &InlinedItem::TraitItem(_, ref ti) => ti.id,
         &InlinedItem::ImplItem(_, ref ii) => ii.id,
-        &InlinedItem::Foreign(ref fi) => fi.id
+        &InlinedItem::Foreign(_, ref fi) => fi.id
     };
     copy_item_type(dcx, item_node_id, orig_did);
 
     // copy the entries of inner items
-    if let &InlinedItem::Item(ref item) = ii {
+    if let &InlinedItem::Item(_, ref item) = ii {
         match item.node {
             hir::ItemEnum(ref def, _) => {
                 let orig_def = dcx.tcx.lookup_adt_def(orig_did);
@@ -1383,6 +1383,9 @@ fn foo(x: usize, y: usize) -> usize {
 
 #[test]
 fn test_simplification() {
+    use middle::cstore::LOCAL_CRATE;
+    use rustc::hir::def_id::CRATE_DEF_INDEX;
+
     let cx = mk_ctxt();
     let item = quote_item!(&cx,
         fn new_int_alist<B>() -> alist<isize, B> {
@@ -1393,15 +1396,16 @@ fn eq_int(a: isize, b: isize) -> bool { a == b }
     let cx = mk_ctxt();
     with_testing_context(|lcx| {
         let hir_item = lcx.lower_item(&item);
-        let item_in = InlinedItemRef::Item(&hir_item);
+        let def_id = DefId { krate: LOCAL_CRATE, index: CRATE_DEF_INDEX }; // dummy
+        let item_in = InlinedItemRef::Item(def_id, &hir_item);
         let (item_out, _) = simplify_ast(item_in);
-        let item_exp = InlinedItem::Item(P(lcx.lower_item(&quote_item!(&cx,
+        let item_exp = InlinedItem::Item(def_id, P(lcx.lower_item(&quote_item!(&cx,
             fn new_int_alist<B>() -> alist<isize, B> {
                 return alist {eq_fn: eq_int, data: Vec::new()};
             }
         ).unwrap())));
         match (item_out, item_exp) {
-            (InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
+            (InlinedItem::Item(_, item_out), InlinedItem::Item(_, item_exp)) => {
                  assert!(pprust::item_to_string(&item_out) ==
                          pprust::item_to_string(&item_exp));
             }
index 862245b9b78694bcb22cba1271a98ced9ba0c0e2..7ee6e54a666d6d524520ee745440e422a50a56c3 100644 (file)
@@ -546,11 +546,13 @@ fn maybe_get_item_ast<'a>(&'tcx self,
                     .borrow_mut()
                     .insert(def_id, None);
             }
-            decoder::FoundAst::Found(&InlinedItem::Item(ref item)) => {
+            decoder::FoundAst::Found(&InlinedItem::Item(d, ref item)) => {
+                assert_eq!(d, def_id);
                 let inlined_root_node_id = find_inlined_item_root(item.id);
                 cache_inlined_item(def_id, item.id, inlined_root_node_id);
             }
-            decoder::FoundAst::Found(&InlinedItem::Foreign(ref item)) => {
+            decoder::FoundAst::Found(&InlinedItem::Foreign(d, ref item)) => {
+                assert_eq!(d, def_id);
                 let inlined_root_node_id = find_inlined_item_root(item.id);
                 cache_inlined_item(def_id, item.id, inlined_root_node_id);
             }
index d8fd25d62774af11721a3db8b604a6ff6c0f4400..64b614b56e12fdffe444b86545fb03c77226adaa 100644 (file)
@@ -797,7 +797,7 @@ pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id:
                                          grandparent_def_id,
                                          ast_doc,
                                          parent_did);
-            if let &InlinedItem::Item(ref i) = ii {
+            if let &InlinedItem::Item(_, ref i) = ii {
                 return FoundAst::FoundParent(parent_did, i);
             }
         }
@@ -1690,7 +1690,7 @@ fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
             let mut decoder = reader::Decoder::new(def_key_doc);
             let simple_key = def_key::DefKey::decode(&mut decoder).unwrap();
             let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| {
-                token::intern(name.as_str_slice())
+                token::intern(name.as_str_slice()).as_str()
             });
             def_key::recover_def_key(simple_key, name)
         }
index 05ad333ed3adcf9513e9340cfcc4820920325a7b..285ca2e4d4d4de2367259410dd9f09a3e291e73c 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::hir::def_id::DefIndex;
 use rustc::hir::map as hir_map;
-use syntax::ast::Name;
+use syntax::parse::token::InternedString;
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct DefKey {
@@ -41,6 +41,7 @@ pub enum DefPathData {
     StructCtor,
     Initializer,
     Binding,
+    ImplTrait,
 }
 
 pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey {
@@ -72,10 +73,11 @@ fn simplify_def_path_data(data: hir_map::DefPathData) -> DefPathData {
         hir_map::DefPathData::StructCtor => DefPathData::StructCtor,
         hir_map::DefPathData::Initializer => DefPathData::Initializer,
         hir_map::DefPathData::Binding(_) => DefPathData::Binding,
+        hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait,
     }
 }
 
-pub fn recover_def_key(key: DefKey, name: Option<Name>) -> hir_map::DefKey {
+pub fn recover_def_key(key: DefKey, name: Option<InternedString>) -> hir_map::DefKey {
     let data = hir_map::DisambiguatedDefPathData {
         data: recover_def_path_data(key.disambiguated_data.data, name),
         disambiguator: key.disambiguated_data.disambiguator,
@@ -86,7 +88,7 @@ pub fn recover_def_key(key: DefKey, name: Option<Name>) -> hir_map::DefKey {
     }
 }
 
-fn recover_def_path_data(data: DefPathData, name: Option<Name>) -> hir_map::DefPathData {
+fn recover_def_path_data(data: DefPathData, name: Option<InternedString>) -> hir_map::DefPathData {
     match data {
         DefPathData::CrateRoot => hir_map::DefPathData::CrateRoot,
         DefPathData::Misc => hir_map::DefPathData::Misc,
@@ -103,5 +105,6 @@ fn recover_def_path_data(data: DefPathData, name: Option<Name>) -> hir_map::DefP
         DefPathData::StructCtor => hir_map::DefPathData::StructCtor,
         DefPathData::Initializer => hir_map::DefPathData::Initializer,
         DefPathData::Binding => hir_map::DefPathData::Binding(name.unwrap()),
+        DefPathData::ImplTrait => hir_map::DefPathData::ImplTrait,
     }
 }
index 732c256a1910f18ca8e8b629d158d5476512f286..cc1d07b33c7e830b6840e2d4b79045210db44f99 100644 (file)
@@ -743,7 +743,8 @@ fn encode_repr_attrs(rbml_w: &mut Encoder,
 }
 
 fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, node_id: NodeId) {
-    if let Some(mir) = ecx.mir_map.map.get(&node_id) {
+    let def_id = ecx.tcx.map.local_def_id(node_id);
+    if let Some(mir) = ecx.mir_map.map.get(&def_id) {
         rbml_w.start_tag(tag_mir as usize);
         rbml_w.emit_opaque(|opaque_encoder| {
             tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| {
@@ -861,7 +862,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
         encode_name(rbml_w, item.name);
         encode_attributes(rbml_w, &item.attrs);
-        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(def_id, item));
         encode_mir(ecx, rbml_w, item.id);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
@@ -879,7 +880,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_attributes(rbml_w, &item.attrs);
         let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
         if needs_inline || constness == hir::Constness::Const {
-            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
+            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(def_id, item));
             encode_mir(ecx, rbml_w, item.id);
         }
         encode_constness(rbml_w, constness);
@@ -942,7 +943,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         for v in &enum_definition.variants {
             encode_variant_id(rbml_w, ecx.tcx.map.local_def_id(v.node.data.id()));
         }
-        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(def_id, item));
         encode_mir(ecx, rbml_w, item.id);
 
         // Encode inherent implementations for this enumeration.
@@ -989,7 +990,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         needs to know*/
         encode_struct_fields(rbml_w, variant);
 
-        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
+        encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(def_id, item));
         encode_mir(ecx, rbml_w, item.id);
 
         // Encode inherent implementations for this structure.
@@ -1311,7 +1312,7 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
         encode_name(rbml_w, nitem.name);
         if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
+            encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(def_id, nitem));
             encode_mir(ecx, rbml_w, nitem.id);
         }
         encode_attributes(rbml_w, &nitem.attrs);
@@ -1361,7 +1362,7 @@ fn my_visit_expr(expr: &hir::Expr,
             ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap();
             rbml_w.end_tag();
 
-            assert!(ecx.mir_map.map.contains_key(&expr.id));
+            assert!(ecx.mir_map.map.contains_key(&def_id));
             encode_mir(ecx, rbml_w, expr.id);
 
             rbml_w.end_tag();
@@ -1389,6 +1390,20 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
         encode_info_for_foreign_item(self.ecx, self.rbml_w_for_visit_item, ni, self.index);
     }
+    fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
+        intravisit::walk_ty(self, ty);
+
+        if let hir::TyImplTrait(_) = ty.node {
+            let rbml_w = &mut *self.rbml_w_for_visit_item;
+            let def_id = self.ecx.tcx.map.local_def_id(ty.id);
+            let _task = self.index.record(def_id, rbml_w);
+            rbml_w.start_tag(tag_items_data_item);
+            encode_def_id_and_key(self.ecx, rbml_w, def_id);
+            encode_family(rbml_w, 'y');
+            encode_bounds_and_type_for_item(rbml_w, self.ecx, self.index, ty.id);
+            rbml_w.end_tag();
+        }
+    }
 }
 
 fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
index 119640af463aa8bf768dddfc23ede46bd996df88..1dcec35adb285554642a41712abcc6265d736166 100644 (file)
@@ -445,6 +445,13 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
                 let name = token::intern(&self.parse_str(']'));
                 return tcx.mk_projection(trait_ref, name);
             }
+            'A' => {
+                assert_eq!(self.next(), '[');
+                let def_id = self.parse_def();
+                let substs = self.parse_substs();
+                assert_eq!(self.next(), ']');
+                return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs));
+            }
             'e' => {
                 return tcx.types.err;
             }
index 3484a8b75dded7105c12e44d98d5e3b11ad7ccd2..c2e91eba0d2523a600d322ccf35f1d548375958a 100644 (file)
@@ -170,6 +170,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
             enc_trait_ref(w, cx, data.trait_ref);
             write!(w, "{}]", data.item_name);
         }
+        ty::TyAnon(def_id, substs) => {
+            write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id));
+            enc_substs(w, cx, substs);
+            write!(w, "]");
+        }
         ty::TyError => {
             write!(w, "e");
         }
index fdfa872b0b698805f140863294837893e86a70e7..d986d88dafc94c8b7c507457e3d74ce6d51fe953 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 
 use dot;
+use rustc::hir::def_id::DefId;
 use rustc::mir::repr::*;
+use rustc::mir::mir_map::MirMap;
 use rustc::ty::{self, TyCtxt};
 use std::fmt::Debug;
 use std::io::{self, Write};
 
 /// Write a graphviz DOT graph of a list of MIRs.
 pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-                                              iter: I, w: &mut W)
+                                              iter: I,
+                                              mir_map: &MirMap<'tcx>,
+                                              w: &mut W)
                                               -> io::Result<()>
-where W: Write, I: Iterator<Item=(&'a NodeId, &'a Mir<'a>)> {
-    for (&nodeid, mir) in iter {
+    where W: Write, I: Iterator<Item=DefId>
+{
+    for def_id in iter {
+        let nodeid = tcx.map.as_local_node_id(def_id).unwrap();
+        let mir = &mir_map.map[&def_id];
+
         writeln!(w, "digraph Mir_{} {{", nodeid)?;
 
         // Global graph properties
index 2438f43d24e0a42f8e87854af51e0ffe35c90ddb..df1fec75939b5097e8d62ec45e6d481007e92253 100644 (file)
@@ -22,6 +22,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc_const_eval as const_eval;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc::dep_graph::DepNode;
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
@@ -61,7 +62,17 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
             MirSource::Promoted(..) => bug!()
         };
 
-        let attrs = infcx.tcx.map.attrs(src.item_id());
+        let src_node_id = src.item_id();
+
+        // We are going to be accessing various tables
+        // generated by TypeckItemBody; we also assume
+        // that the body passes type check. These tables
+        // are not individually tracked, so just register
+        // a read here.
+        let src_def_id = infcx.tcx.map.local_def_id(src_node_id);
+        infcx.tcx.dep_graph.read(DepNode::TypeckItemBody(src_def_id));
+
+        let attrs = infcx.tcx.map.attrs(src_node_id);
 
         // Some functions always have overflow checks enabled,
         // however, they may not get codegen'd, depending on
index 11d6b0779275ee40f6f6a56ae6728fdb9d0c687f..5e92a057da38280a46c8ca1ef21353e1bad1ef64 100644 (file)
@@ -18,6 +18,7 @@
 
 use build;
 use rustc::dep_graph::DepNode;
+use rustc::hir::def_id::DefId;
 use rustc::mir::repr::Mir;
 use rustc::mir::transform::MirSource;
 use rustc::mir::visit::MutVisitor;
 
 use rustc::mir::mir_map::MirMap;
 use rustc::infer::InferCtxtBuilder;
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
-use rustc::util::nodemap::NodeMap;
 use rustc::hir;
 use rustc::hir::intravisit::{self, FnKind, Visitor};
 use syntax::ast;
 use std::mem;
 
 pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx> {
-    let mut map = MirMap {
-        map: NodeMap(),
-    };
+    let mut map = MirMap::new(tcx.dep_graph.clone());
     {
         let mut dump = BuildMir {
             tcx: tcx,
             map: &mut map,
         };
-        tcx.visit_all_items_in_krate(DepNode::MirMapConstruction, &mut dump);
+        tcx.visit_all_items_in_krate(DepNode::Mir, &mut dump);
     }
     map
 }
@@ -94,6 +92,7 @@ struct BuildMir<'a, 'tcx: 'a> {
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Cx<'b, 'gcx, 'tcx>).
 struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     src: MirSource,
+    def_id: DefId,
     infcx: InferCtxtBuilder<'a, 'gcx, 'tcx>,
     map: &'a mut MirMap<'gcx>,
 }
@@ -101,9 +100,11 @@ struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> {
     fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> {
         let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id());
+        let def_id = self.tcx.map.local_def_id(src.item_id());
         CxBuilder {
             src: src,
-            infcx: self.tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal),
+            infcx: self.tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable),
+            def_id: def_id,
             map: self.map
         }
     }
@@ -133,7 +134,7 @@ fn build<F>(&'tcx mut self, f: F)
             mir
         });
 
-        assert!(self.map.map.insert(src.item_id(), mir).is_none())
+        assert!(self.map.map.insert(self.def_id, mir).is_none())
     }
 }
 
index d1b88ddda0c674987bb3e605b315b9cc20330b36..55e7408b0fd5d4ec881c2387fa94023abc2e938b 100644 (file)
@@ -10,7 +10,9 @@
 
 use build::{Location, ScopeAuxiliaryVec, ScopeId};
 use rustc::hir;
+use rustc::hir::def_id::DefId;
 use rustc::mir::repr::*;
+use rustc::mir::mir_map::MirMap;
 use rustc::mir::transform::MirSource;
 use rustc::ty::{self, TyCtxt};
 use rustc_data_structures::fnv::FnvHashMap;
@@ -18,7 +20,6 @@
 use std::fmt::Display;
 use std::fs;
 use std::io::{self, Write};
-use syntax::ast::NodeId;
 use std::path::{PathBuf, Path};
 
 const INDENT: &'static str = "    ";
@@ -89,12 +90,15 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// Write out a human-readable textual representation for the given MIR.
 pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                          iter: I,
+                                         mir_map: &MirMap<'tcx>,
                                          w: &mut Write)
                                          -> io::Result<()>
-    where I: Iterator<Item=(&'a NodeId, &'a Mir<'tcx>)>, 'tcx: 'a
+    where I: Iterator<Item=DefId>, 'tcx: 'a
 {
     let mut first = true;
-    for (&id, mir) in iter {
+    for def_id in iter {
+        let mir = &mir_map.map[&def_id];
+
         if first {
             first = false;
         } else {
@@ -102,6 +106,7 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
             writeln!(w, "")?;
         }
 
+        let id = tcx.map.as_local_node_id(def_id).unwrap();
         let src = MirSource::from_node(tcx, id);
         write_mir_fn(tcx, src, mir, w, None)?;
 
index fccd4a607fdcf1cd2e9a520b7ee0efe7b2d5cecb..cd6f0ed9cbac68a81313211464ccc802eb75c1c1 100644 (file)
@@ -39,7 +39,7 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         let mut curr: usize = 0;
         for bb in mir.basic_blocks_mut() {
-            let idx = match get_aggregate_statement(curr, &bb.statements) {
+            let idx = match get_aggregate_statement_index(curr, &bb.statements) {
                 Some(idx) => idx,
                 None => continue,
             };
@@ -48,7 +48,11 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let src_info = bb.statements[idx].source_info;
             let suffix_stmts = bb.statements.split_off(idx+1);
             let orig_stmt = bb.statements.pop().unwrap();
-            let StatementKind::Assign(ref lhs, ref rhs) = orig_stmt.kind;
+            let (lhs, rhs) = match orig_stmt.kind {
+                StatementKind::Assign(ref lhs, ref rhs) => (lhs, rhs),
+                StatementKind::SetDiscriminant{ .. } =>
+                    span_bug!(src_info.span, "expected aggregate, not {:?}", orig_stmt.kind),
+            };
             let (agg_kind, operands) = match rhs {
                 &Rvalue::Aggregate(ref agg_kind, ref operands) => (agg_kind, operands),
                 _ => span_bug!(src_info.span, "expected aggregate, not {:?}", rhs),
@@ -64,10 +68,14 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 let ty = variant_def.fields[i].ty(tcx, substs);
                 let rhs = Rvalue::Use(op.clone());
 
-                // since we don't handle enums, we don't need a cast
-                let lhs_cast = lhs.clone();
-
-                // FIXME we cannot deaggregate enums issue: #35186
+                let lhs_cast = if adt_def.variants.len() > 1 {
+                    Lvalue::Projection(Box::new(LvalueProjection {
+                        base: lhs.clone(),
+                        elem: ProjectionElem::Downcast(adt_def, variant),
+                    }))
+                } else {
+                    lhs.clone()
+                };
 
                 let lhs_proj = Lvalue::Projection(Box::new(LvalueProjection {
                     base: lhs_cast,
@@ -80,18 +88,34 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 debug!("inserting: {:?} @ {:?}", new_statement, idx + i);
                 bb.statements.push(new_statement);
             }
+
+            // if the aggregate was an enum, we need to set the discriminant
+            if adt_def.variants.len() > 1 {
+                let set_discriminant = Statement {
+                    kind: StatementKind::SetDiscriminant {
+                        lvalue: lhs.clone(),
+                        variant_index: variant,
+                    },
+                    source_info: src_info,
+                };
+                bb.statements.push(set_discriminant);
+            };
+
             curr = bb.statements.len();
             bb.statements.extend(suffix_stmts);
         }
     }
 }
 
-fn get_aggregate_statement<'a, 'tcx, 'b>(curr: usize,
+fn get_aggregate_statement_index<'a, 'tcx, 'b>(start: usize,
                                          statements: &Vec<Statement<'tcx>>)
                                          -> Option<usize> {
-    for i in curr..statements.len() {
+    for i in start..statements.len() {
         let ref statement = statements[i];
-        let StatementKind::Assign(_, ref rhs) = statement.kind;
+        let rhs = match statement.kind {
+            StatementKind::Assign(_, ref rhs) => rhs,
+            StatementKind::SetDiscriminant{ .. } => continue,
+        };
         let (kind, operands) = match rhs {
             &Rvalue::Aggregate(ref kind, ref operands) => (kind, operands),
             _ => continue,
@@ -100,9 +124,8 @@ fn get_aggregate_statement<'a, 'tcx, 'b>(curr: usize,
             &AggregateKind::Adt(adt_def, variant, _) => (adt_def, variant),
             _ => continue,
         };
-        if operands.len() == 0 || adt_def.variants.len() > 1 {
+        if operands.len() == 0 {
             // don't deaggregate ()
-            // don't deaggregate enums ... for now
             continue;
         }
         debug!("getting variant {:?}", variant);
index 4b551d6bb083cfa85eeb1af32293f67e1b6f21c8..eb0d8697f15d4c88e028a3d5b9cd3a68c71bc9e2 100644 (file)
@@ -219,7 +219,13 @@ fn promote_temp(&mut self, temp: Temp) -> Temp {
         let (mut rvalue, mut call) = (None, None);
         let source_info = if stmt_idx < no_stmts {
             let statement = &mut self.source[bb].statements[stmt_idx];
-            let StatementKind::Assign(_, ref mut rhs) = statement.kind;
+            let mut rhs = match statement.kind {
+                StatementKind::Assign(_, ref mut rhs) => rhs,
+                StatementKind::SetDiscriminant{ .. } =>
+                    span_bug!(statement.source_info.span,
+                              "cannot promote SetDiscriminant {:?}",
+                              statement),
+            };
             if self.keep_original {
                 rvalue = Some(rhs.clone());
             } else {
@@ -300,10 +306,16 @@ fn promote_candidate(mut self, candidate: Candidate) {
         });
         let mut rvalue = match candidate {
             Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
-                match self.source[bb].statements[stmt_idx].kind {
+                let ref mut statement = self.source[bb].statements[stmt_idx];
+                match statement.kind {
                     StatementKind::Assign(_, ref mut rvalue) => {
                         mem::replace(rvalue, Rvalue::Use(new_operand))
                     }
+                    StatementKind::SetDiscriminant{ .. } => {
+                        span_bug!(statement.source_info.span,
+                                  "cannot promote SetDiscriminant {:?}",
+                                  statement);
+                    }
                 }
             }
             Candidate::ShuffleIndices(bb) => {
@@ -340,20 +352,24 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
         let (span, ty) = match candidate {
             Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
                 let statement = &mir[bb].statements[stmt_idx];
-                let StatementKind::Assign(ref dest, _) = statement.kind;
+                let dest = match statement.kind {
+                    StatementKind::Assign(ref dest, _) => dest,
+                    StatementKind::SetDiscriminant{ .. } =>
+                        panic!("cannot promote SetDiscriminant"),
+                };
                 if let Lvalue::Temp(index) = *dest {
                     if temps[index] == TempState::PromotedOut {
                         // Already promoted.
                         continue;
                     }
                 }
-                (statement.source_info.span, mir.lvalue_ty(tcx, dest).to_ty(tcx))
+                (statement.source_info.span, dest.ty(mir, tcx).to_ty(tcx))
             }
             Candidate::ShuffleIndices(bb) => {
                 let terminator = mir[bb].terminator();
                 let ty = match terminator.kind {
                     TerminatorKind::Call { ref args, .. } => {
-                        mir.operand_ty(tcx, &args[2])
+                        args[2].ty(mir, tcx)
                     }
                     _ => {
                         span_bug!(terminator.source_info.span,
index 5455ca62ea46e6eb3a426af70db3a8b5946881a0..7ebc72bcc5fca36875d7dc631774151219194300 100644 (file)
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::ty::cast::CastTy;
 use rustc::mir::repr::*;
@@ -485,8 +486,7 @@ fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
                                 this.add(Qualif::STATIC);
                             }
 
-                            let base_ty = this.mir.lvalue_ty(this.tcx, &proj.base)
-                                              .to_ty(this.tcx);
+                            let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
                             if let ty::TyRawPtr(_) = base_ty.sty {
                                 this.add(Qualif::NOT_CONST);
                                 if this.mode != Mode::Fn {
@@ -505,8 +505,7 @@ fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
                                           "cannot refer to the interior of another \
                                            static, use a constant instead");
                             }
-                            let ty = this.mir.lvalue_ty(this.tcx, lvalue)
-                                         .to_ty(this.tcx);
+                            let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
                             this.qualif.restrict(ty, this.tcx, &this.param_env);
                         }
 
@@ -591,7 +590,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
                     self.add(Qualif::STATIC_REF);
                 }
 
-                let ty = self.mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
+                let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx);
                 if kind == BorrowKind::Mut {
                     // In theory, any zero-sized value could be borrowed
                     // mutably without consequences. However, only &mut []
@@ -616,9 +615,12 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
                     if !allow {
                         self.add(Qualif::NOT_CONST);
                         if self.mode != Mode::Fn {
-                            span_err!(self.tcx.sess, self.span, E0017,
-                                      "references in {}s may only refer \
-                                       to immutable values", self.mode);
+                            struct_span_err!(self.tcx.sess,  self.span, E0017,
+                                             "references in {}s may only refer \
+                                              to immutable values", self.mode)
+                                .span_label(self.span, &format!("{}s require immutable values",
+                                                                self.mode))
+                                .emit();
                         }
                     }
                 } else {
@@ -651,7 +653,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
             }
 
             Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => {
-                let operand_ty = self.mir.operand_ty(self.tcx, operand);
+                let operand_ty = operand.ty(self.mir, self.tcx);
                 let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
                 let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
                 match (cast_in, cast_out) {
@@ -669,7 +671,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
             }
 
             Rvalue::BinaryOp(op, ref lhs, _) => {
-                if let ty::TyRawPtr(_) = self.mir.operand_ty(self.tcx, lhs).sty {
+                if let ty::TyRawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
                     assert!(op == BinOp::Eq || op == BinOp::Ne ||
                             op == BinOp::Le || op == BinOp::Lt ||
                             op == BinOp::Ge || op == BinOp::Gt);
@@ -701,7 +703,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
                     }
 
                     if Some(def.did) == self.tcx.lang_items.unsafe_cell_type() {
-                        let ty = self.mir.rvalue_ty(self.tcx, rvalue).unwrap();
+                        let ty = rvalue.ty(self.mir, self.tcx).unwrap();
                         self.add_type(ty);
                         assert!(self.qualif.intersects(Qualif::MUTABLE_INTERIOR));
                         // Even if the value inside may not need dropping,
@@ -723,7 +725,7 @@ fn visit_terminator_kind(&mut self, bb: BasicBlock, kind: &TerminatorKind<'tcx>)
         if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind {
             self.visit_operand(func);
 
-            let fn_ty = self.mir.operand_ty(self.tcx, func);
+            let fn_ty = func.ty(self.mir, self.tcx);
             let (is_shuffle, is_const_fn) = match fn_ty.sty {
                 ty::TyFnDef(def_id, _, f) => {
                     (f.abi == Abi::PlatformIntrinsic &&
@@ -803,7 +805,7 @@ struct and enum constructors",
                 } else {
                     // Be conservative about the returned value of a const fn.
                     let tcx = self.tcx;
-                    let ty = self.mir.lvalue_ty(tcx, dest).to_ty(tcx);
+                    let ty = dest.ty(self.mir, tcx).to_ty(tcx);
                     self.qualif = Qualif::empty();
                     self.add_type(ty);
 
@@ -883,8 +885,8 @@ fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let extern_mir;
     let param_env_and_mir = if def_id.is_local() {
-        let node_id = tcx.map.as_local_node_id(def_id).unwrap();
-        mir_map.and_then(|map| map.map.get(&node_id)).map(|mir| {
+        mir_map.and_then(|map| map.map.get(&def_id)).map(|mir| {
+            let node_id = tcx.map.as_local_node_id(def_id).unwrap();
             (ty::ParameterEnvironment::for_item(tcx, node_id), mir)
         })
     } else if let Some(mir) = tcx.sess.cstore.maybe_get_item_mir(tcx, def_id) {
@@ -919,9 +921,10 @@ fn run_pass<'a>(&mut self,
 
         // First, visit `const` items, potentially recursing, to get
         // accurate MUTABLE_INTERIOR and NEEDS_DROP qualifications.
-        for &id in map.map.keys() {
-            let def_id = tcx.map.local_def_id(id);
-            let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
+        let keys = map.map.keys();
+        for &def_id in &keys {
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let id = tcx.map.as_local_node_id(def_id).unwrap();
             let src = MirSource::from_node(tcx, id);
             if let MirSource::Const(_) = src {
                 qualify_const_item_cached(tcx, &mut qualif_map, Some(map), def_id);
@@ -931,9 +934,9 @@ fn run_pass<'a>(&mut self,
         // Then, handle everything else, without recursing,
         // as the MIR map is not shared, since promotion
         // in functions (including `const fn`) mutates it.
-        for (&id, mir) in &mut map.map {
-            let def_id = tcx.map.local_def_id(id);
-            let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
+        for &def_id in &keys {
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let id = tcx.map.as_local_node_id(def_id).unwrap();
             let src = MirSource::from_node(tcx, id);
             let mode = match src {
                 MirSource::Fn(_) => {
@@ -950,6 +953,7 @@ fn run_pass<'a>(&mut self,
             };
             let param_env = ty::ParameterEnvironment::for_item(tcx, id);
 
+            let mir = map.map.get_mut(&def_id).unwrap();
             for hook in &mut *hooks {
                 hook.on_mir_pass(tcx, src, mir, self, false);
             }
@@ -988,7 +992,7 @@ fn run_pass<'a>(&mut self,
             // Statics must be Sync.
             if mode == Mode::Static {
                 let ty = mir.return_ty.unwrap();
-                tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
+                tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
                     let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic);
                     let mut fulfillment_cx = traits::FulfillmentContext::new();
                     fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
index db49e1e040791803103f66e7e34742e5d4b60248..934357c9e1da2f4deb3d6019e30ae50bcdb3b972 100644 (file)
 //! This pass type-checks the MIR to ensure it is not broken.
 #![allow(unreachable_code)]
 
-use rustc::dep_graph::DepNode;
-use rustc::hir::def_id::DefId;
 use rustc::infer::{self, InferCtxt, InferOk};
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
 use rustc::mir::repr::*;
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir::transform::{MirPass, MirSource, Pass};
@@ -81,7 +79,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>) {
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
         self.super_rvalue(rvalue);
-        if let Some(ty) = self.mir.rvalue_ty(self.tcx(), rvalue) {
+        if let Some(ty) = rvalue.ty(self.mir, self.tcx()) {
             self.sanitize_type(rvalue, ty);
         }
     }
@@ -180,7 +178,7 @@ fn sanitize_projection(&mut self,
             }
             ProjectionElem::Index(ref i) => {
                 self.visit_operand(i);
-                let index_ty = self.mir.operand_ty(tcx, i);
+                let index_ty = i.ty(self.mir, tcx);
                 if index_ty != tcx.types.usize {
                     LvalueTy::Ty {
                         ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i)
@@ -355,17 +353,34 @@ fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>) {
         let tcx = self.tcx();
         match stmt.kind {
             StatementKind::Assign(ref lv, ref rv) => {
-                let lv_ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
-                let rv_ty = mir.rvalue_ty(tcx, rv);
+                let lv_ty = lv.ty(mir, tcx).to_ty(tcx);
+                let rv_ty = rv.ty(mir, tcx);
                 if let Some(rv_ty) = rv_ty {
                     if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
                         span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}",
                                      lv_ty, rv_ty, terr);
                     }
-                }
-
                 // FIXME: rvalue with undeterminable type - e.g. inline
                 // asm.
+                }
+            }
+            StatementKind::SetDiscriminant{ ref lvalue, variant_index } => {
+                let lvalue_type = lvalue.ty(mir, tcx).to_ty(tcx);
+                let adt = match lvalue_type.sty {
+                    TypeVariants::TyEnum(adt, _) => adt,
+                    _ => {
+                        span_bug!(stmt.source_info.span,
+                                  "bad set discriminant ({:?} = {:?}): lhs is not an enum",
+                                  lvalue,
+                                  variant_index);
+                    }
+                };
+                if variant_index >= adt.variants.len() {
+                     span_bug!(stmt.source_info.span,
+                               "bad set discriminant ({:?} = {:?}): value of of range",
+                               lvalue,
+                               variant_index);
+                };
             }
         }
     }
@@ -390,8 +405,8 @@ fn check_terminator(&mut self,
                 ref value,
                 ..
             } => {
-                let lv_ty = mir.lvalue_ty(tcx, location).to_ty(tcx);
-                let rv_ty = mir.operand_ty(tcx, value);
+                let lv_ty = location.ty(mir, tcx).to_ty(tcx);
+                let rv_ty = value.ty(mir, tcx);
                 if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
                     span_mirbug!(self, term, "bad DropAndReplace ({:?} = {:?}): {:?}",
                                  lv_ty, rv_ty, terr);
@@ -399,7 +414,7 @@ fn check_terminator(&mut self,
             }
 
             TerminatorKind::If { ref cond, .. } => {
-                let cond_ty = mir.operand_ty(tcx, cond);
+                let cond_ty = cond.ty(mir, tcx);
                 match cond_ty.sty {
                     ty::TyBool => {}
                     _ => {
@@ -408,7 +423,7 @@ fn check_terminator(&mut self,
                 }
             }
             TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
-                let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+                let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
                 if let Err(terr) = self.sub_types(self.last_span, discr_ty, switch_ty) {
                     span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
                                  switch_ty, discr_ty, terr);
@@ -421,7 +436,7 @@ fn check_terminator(&mut self,
                 // FIXME: check the values
             }
             TerminatorKind::Switch { ref discr, adt_def, ref targets } => {
-                let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+                let discr_ty = discr.ty(mir, tcx).to_ty(tcx);
                 match discr_ty.sty {
                     ty::TyEnum(def, _)
                         if def == adt_def && adt_def.variants.len() == targets.len()
@@ -433,7 +448,7 @@ fn check_terminator(&mut self,
                 }
             }
             TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
-                let func_ty = mir.operand_ty(tcx, func);
+                let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let func_ty = match func_ty.sty {
                     ty::TyFnDef(_, _, func_ty) | ty::TyFnPtr(func_ty) => func_ty,
@@ -453,16 +468,16 @@ fn check_terminator(&mut self,
                 }
             }
             TerminatorKind::Assert { ref cond, ref msg, .. } => {
-                let cond_ty = mir.operand_ty(tcx, cond);
+                let cond_ty = cond.ty(mir, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
                 if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
-                    if mir.operand_ty(tcx, len) != tcx.types.usize {
+                    if len.ty(mir, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
-                    if mir.operand_ty(tcx, index) != tcx.types.usize {
+                    if index.ty(mir, tcx) != tcx.types.usize {
                         span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
                     }
                 }
@@ -481,7 +496,7 @@ fn check_call_dest(&self,
                 span_mirbug!(self, term, "call to diverging function {:?} with dest", sig);
             }
             (&Some((ref dest, _)), ty::FnConverging(ty)) => {
-                let dest_ty = mir.lvalue_ty(tcx, dest).to_ty(tcx);
+                let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
                 if let Err(terr) = self.sub_types(self.last_span, ty, dest_ty) {
                     span_mirbug!(self, term,
                                  "call dest mismatch ({:?} <- {:?}): {:?}",
@@ -507,7 +522,7 @@ fn check_call_inputs(&self,
             span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
         }
         for (n, (fn_arg, op_arg)) in sig.inputs.iter().zip(args).enumerate() {
-            let op_arg_ty = mir.operand_ty(self.tcx(), op_arg);
+            let op_arg_ty = op_arg.ty(mir, self.tcx());
             if let Err(terr) = self.sub_types(self.last_span, op_arg_ty, fn_arg) {
                 span_mirbug!(self, term, "bad arg #{:?} ({:?} <- {:?}): {:?}",
                              n, fn_arg, op_arg_ty, terr);
@@ -554,7 +569,7 @@ fn check_box_free_inputs(&self,
             return;
         }
 
-        let arg_ty = match mir.operand_ty(self.tcx(), &args[0]).sty {
+        let arg_ty = match args[0].ty(mir, self.tcx()).sty {
             ty::TyRawPtr(mt) => mt.ty,
             ty::TyBox(ty) => ty,
             _ => {
@@ -697,7 +712,7 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
             return;
         }
         let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id());
-        tcx.infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal).enter(|infcx| {
+        tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable).enter(|infcx| {
             let mut checker = TypeChecker::new(&infcx);
             {
                 let mut verifier = TypeVerifier::new(&mut checker, mir);
@@ -714,7 +729,4 @@ fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl Pass for TypeckMir {
-    fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
-        DepNode::MirTypeck(def_id)
-    }
 }
index 91d2500564fd3b7d246f406fcb8d117fb0fede0b..1e8da29ee74002bbd5f37b5ead3935d08c62382c 100644 (file)
@@ -183,6 +183,7 @@ fn visit_foreign_item(&mut self, fi: &ForeignItem) {
                                                    E0130,
                                                    "patterns aren't allowed in foreign function \
                                                     declarations");
+                    err.span_label(span, &format!("pattern not allowed in foreign function"));
                     if is_recent {
                         err.span_note(span,
                                       "this is a recent error, see issue #35203 for more details");
@@ -196,27 +197,6 @@ fn visit_foreign_item(&mut self, fi: &ForeignItem) {
         visit::walk_foreign_item(self, fi)
     }
 
-    fn visit_variant_data(&mut self,
-                          vdata: &VariantData,
-                          _: Ident,
-                          _: &Generics,
-                          _: NodeId,
-                          span: Span) {
-        if vdata.fields().is_empty() {
-            if vdata.is_tuple() {
-                self.err_handler()
-                    .struct_span_err(span,
-                                     "empty tuple structs and enum variants are not allowed, use \
-                                      unit structs and enum variants instead")
-                    .span_help(span,
-                               "remove trailing `()` to make a unit struct or unit enum variant")
-                    .emit();
-            }
-        }
-
-        visit::walk_struct_def(self, vdata)
-    }
-
     fn visit_vis(&mut self, vis: &Visibility) {
         match *vis {
             Visibility::Restricted { ref path, .. } => {
index fc55118c9f4c518ed0fa989067cf40f95f580f9e..37e42cdea1bf84b6f6b690efeb9bd92b28a4afa4 100644 (file)
@@ -39,7 +39,7 @@
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::middle::const_qualif::ConstQualif;
@@ -96,7 +96,7 @@ fn with_euv<F, R>(&mut self, item_id: Option<ast::NodeId>, f: F) -> R
         };
 
         self.tcx
-            .infer_ctxt(None, Some(param_env), ProjectionMode::AnyFinal)
+            .infer_ctxt(None, Some(param_env), Reveal::NotSpecializable)
             .enter(|infcx| f(&mut euv::ExprUseVisitor::new(self, &infcx)))
     }
 
index 2a5dc50cae92f4682044ffae57dc069e04ce409c..782ee34edd4f98ec90c45b2716b332bd2e19b79f 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::ty::{self, TyCtxt, ParameterEnvironment};
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 
 use rustc::hir;
 use rustc::hir::intravisit;
@@ -41,7 +41,7 @@ fn visit_fn(&mut self,
         // FIXME (@jroesch) change this to be an inference context
         let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
         self.tcx.infer_ctxt(None, Some(param_env.clone()),
-                            ProjectionMode::AnyFinal).enter(|infcx| {
+                            Reveal::NotSpecializable).enter(|infcx| {
             let mut delegate = RvalueContextDelegate {
                 tcx: infcx.tcx,
                 param_env: &param_env
index 66afe5835bf6fc6f3549dfc788e7feaab720f948..891b6adea789386a3ac8da271d6d1f25a9de26f5 100644 (file)
@@ -17,8 +17,6 @@
 examples:
 
 ```compile_fail,E0445
-#![deny(private_in_public)]
-
 trait Foo {
     fn dummy(&self) { }
 }
@@ -47,8 +45,6 @@ pub fn foo<T: Foo> (t: T) {} // ok!
 A private type was used in a public type signature. Erroneous code example:
 
 ```compile_fail,E0446
-#![deny(private_in_public)]
-
 mod Foo {
     struct Bar(u32);
 
index 793e52d37920354be1a9373fbdd672920c0eaba5..d8f39358411a19ef181adb25129038766bc1183a 100644 (file)
@@ -873,19 +873,12 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     // Return the visibility of the type alias's least visible component type when substituted
     fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
                                     -> Option<ty::Visibility> {
-        // We substitute type aliases only when determining impl publicity
-        // FIXME: This will probably change and all type aliases will be substituted,
-        // requires an amendment to RFC 136.
-        if self.required_visibility != ty::Visibility::PrivateExternal {
-            return None;
-        }
         // Type alias is considered public if the aliased type is
         // public, even if the type alias itself is private. So, something
         // like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
         if let hir::ItemTy(ref ty, ref generics) = item.node {
-            let mut check = SearchInterfaceForPrivateItemsVisitor {
-                min_visibility: ty::Visibility::Public, ..*self
-            };
+            let mut check = SearchInterfaceForPrivateItemsVisitor::new(self.tcx,
+                                                                       self.old_error_set);
             check.visit_ty(ty);
             // If a private type alias with default type parameters is used in public
             // interface we must ensure, that the defaults are public if they are actually used.
@@ -945,7 +938,8 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                                 self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
                                                        node_id,
                                                        ty.span,
-                                                       format!("private type in public interface"));
+                                                       format!("private type in public \
+                                                                interface (error E0446)"));
                             }
                         }
                     }
index 9f1f07004f4aecc9978fefb658e20a85a3b3fbbf..bdbdb294954883977837b68f3a3a91efacbd2374 100644 (file)
@@ -412,7 +412,10 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
             struct_span_err!(resolver.session, span, E0432, "{}", msg)
         }
         ResolutionError::FailedToResolve(msg) => {
-            struct_span_err!(resolver.session, span, E0433, "failed to resolve. {}", msg)
+            let mut err = struct_span_err!(resolver.session, span, E0433,
+                                           "failed to resolve. {}", msg);
+            err.span_label(span, &msg);
+            err
         }
         ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
             struct_span_err!(resolver.session,
@@ -1005,7 +1008,7 @@ pub struct Resolver<'a> {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    pub module_map: NodeMap<Module<'a>>,
+    module_map: NodeMap<Module<'a>>,
 
     // Whether or not to print error messages. Can be set to true
     // when getting additional info for error message suggestions,
@@ -1744,6 +1747,7 @@ fn with_type_parameter_rib<'b, F>(&'b mut self, type_parameters: TypeParameters<
                     let def_id = self.definitions.local_def_id(type_parameter.id);
                     let def = Def::TyParam(space, index as u32, def_id, name);
                     function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def);
+                    self.record_def(type_parameter.id, PathResolution::new(def));
                 }
                 self.type_ribs.push(function_type_rib);
             }
index f7fd970f37f2f89e1a4686f541ef9ea5984343bc..29b3f6ce52fb2b8368f17d2fcbea1193273aac20 100644 (file)
 use Disr;
 use value::Value;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use session::config::NoDebugInfo;
 use util::common::indenter;
 use util::nodemap::FnvHashMap;
@@ -1471,7 +1471,7 @@ fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool
         field: field,
         reassigned: false
     };
-    bcx.tcx().normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+    bcx.tcx().normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
         let mut visitor = euv::ExprUseVisitor::new(&mut rc, &infcx);
         visitor.walk_expr(body);
     });
index ebb6e0baf20a00e8c837a18249c5e9853e706caf..5e2c0805c2ea3a6c4bda553e9d773ffbdd58ff91 100644 (file)
 use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
 use rustc::hir::map::definitions::{DefPath, DefPathData};
 
-use std::fmt::Write;
 use syntax::attr;
 use syntax::parse::token::{self, InternedString};
 use serialize::hex::ToHex;
 
 pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> String {
     let def_path = tcx.def_path(def_id);
-    def_path_to_string(tcx, &def_path)
-}
-
-fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String {
-    let mut s = String::with_capacity(def_path.data.len() * 16);
-
-    if def_path.krate == cstore::LOCAL_CRATE {
-        s.push_str(&tcx.crate_name(def_path.krate));
-    } else {
-        s.push_str(&tcx.sess.cstore.original_crate_name(def_path.krate));
-    }
-    s.push_str("/");
-    s.push_str(&tcx.crate_disambiguator(def_path.krate));
-
-    for component in &def_path.data {
-        write!(s,
-               "::{}[{}]",
-               component.data.as_interned_str(),
-               component.disambiguator)
-            .unwrap();
-    }
-
-    s
+    def_path.to_string(tcx)
 }
 
 fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
@@ -167,7 +144,7 @@ fn get_symbol_hash<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     // the main symbol name is not necessarily unique; hash in the
     // compiler's internal def-path, guaranteeing each symbol has a
     // truly unique path
-    hash_state.input_str(&def_path_to_string(tcx, def_path));
+    hash_state.input_str(&def_path.to_string(tcx));
 
     // Include the main item-type. Note that, in this case, the
     // assertions about `needs_subst` may not hold, but this item-type
index 8ce2fa762f9e2606103399f371c6db5afd9a2329..b5c993b86ecb2e0c09d015f9d93117ec02534b60 100644 (file)
 use std::thread;
 use libc::{c_uint, c_void};
 
+pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 4] = [
+    ("pic", llvm::RelocMode::PIC),
+    ("static", llvm::RelocMode::Static),
+    ("default", llvm::RelocMode::Default),
+    ("dynamic-no-pic", llvm::RelocMode::DynamicNoPic),
+];
+
+pub const CODE_GEN_MODEL_ARGS : [(&'static str, llvm::CodeModel); 5] = [
+    ("default", llvm::CodeModel::Default),
+    ("small", llvm::CodeModel::Small),
+    ("kernel", llvm::CodeModel::Kernel),
+    ("medium", llvm::CodeModel::Medium),
+    ("large", llvm::CodeModel::Large),
+];
+
 pub fn llvm_err(handler: &errors::Handler, msg: String) -> ! {
     match llvm::last_error() {
         Some(err) => panic!(handler.fatal(&format!("{}: {}", msg, err))),
@@ -168,12 +183,9 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
         None => &sess.target.target.options.code_model[..],
     };
 
-    let code_model = match code_model_arg {
-        "default" => llvm::CodeModel::Default,
-        "small" => llvm::CodeModel::Small,
-        "kernel" => llvm::CodeModel::Kernel,
-        "medium" => llvm::CodeModel::Medium,
-        "large" => llvm::CodeModel::Large,
+    let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
+        |&&arg| arg.0 == code_model_arg) {
+        Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid code model",
                              sess.opts
@@ -725,6 +737,10 @@ pub fn run_passes(sess: &Session,
         work_items.push(work);
     }
 
+    if sess.opts.debugging_opts.incremental_info {
+        dump_incremental_data(&trans);
+    }
+
     // Process the work items, optionally using worker threads.
     // NOTE: This code is not really adapted to incremental compilation where
     //       the compiler decides the number of codegen units (and will
@@ -902,6 +918,17 @@ pub fn run_passes(sess: &Session,
     }
 }
 
+fn dump_incremental_data(trans: &CrateTranslation) {
+    let mut reuse = 0;
+    for mtrans in trans.modules.iter() {
+        match mtrans.source {
+            ModuleSource::Preexisting(..) => reuse += 1,
+            ModuleSource::Translated(..) => (),
+        }
+    }
+    println!("incremental: re-using {} out of {} modules", reuse, trans.modules.len());
+}
+
 struct WorkItem {
     mtrans: ModuleTranslation,
     config: ModuleConfig,
index ba2cd2ba699926ca40e274f5e015f590b2c04f19..794da0d1473bd12b900d0aad7d842074f52c2dc8 100644 (file)
 use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
+use rustc_const_eval as const_eval;
+
 use syntax::abi::Abi;
 use errors;
 use syntax_pos::DUMMY_SP;
-use syntax::ast::NodeId;
 use base::custom_coerce_unsize_info;
 use context::SharedCrateContext;
 use common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized};
@@ -478,7 +479,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>) {
                 let target_ty = monomorphize::apply_param_substs(self.scx.tcx(),
                                                                  self.param_substs,
                                                                  &target_ty);
-                let source_ty = self.mir.operand_ty(self.scx.tcx(), operand);
+                let source_ty = operand.ty(self.mir, self.scx.tcx());
                 let source_ty = monomorphize::apply_param_substs(self.scx.tcx(),
                                                                  self.param_substs,
                                                                  &source_ty);
@@ -525,8 +526,8 @@ fn visit_lvalue(&mut self,
         debug!("visiting lvalue {:?}", *lvalue);
 
         if let mir_visit::LvalueContext::Drop = context {
-            let ty = self.mir.lvalue_ty(self.scx.tcx(), lvalue)
-                             .to_ty(self.scx.tcx());
+            let ty = lvalue.ty(self.mir, self.scx.tcx())
+                           .to_ty(self.scx.tcx());
 
             let ty = monomorphize::apply_param_substs(self.scx.tcx(),
                                                       self.param_substs,
@@ -543,9 +544,46 @@ fn visit_operand(&mut self, operand: &mir::Operand<'tcx>) {
         debug!("visiting operand {:?}", *operand);
 
         let callee = match *operand {
-            mir::Operand::Constant(mir::Constant { ty: &ty::TyS {
-                sty: ty::TyFnDef(def_id, substs, _), ..
-            }, .. }) => Some((def_id, substs)),
+            mir::Operand::Constant(ref constant) => {
+                if let ty::TyFnDef(def_id, substs, _) = constant.ty.sty {
+                    // This is something that can act as a callee, proceed
+                    Some((def_id, substs))
+                } else {
+                    // This is not a callee, but we still have to look for
+                    // references to `const` items
+                    if let mir::Literal::Item { def_id, substs } = constant.literal {
+                        let tcx = self.scx.tcx();
+                        let substs = monomorphize::apply_param_substs(tcx,
+                                                                      self.param_substs,
+                                                                      &substs);
+
+                        // If the constant referred to here is an associated
+                        // item of a trait, we need to resolve it to the actual
+                        // constant in the corresponding impl. Luckily
+                        // const_eval::lookup_const_by_id() does that for us.
+                        if let Some((expr, _)) = const_eval::lookup_const_by_id(tcx,
+                                                                                def_id,
+                                                                                Some(substs)) {
+                            // The hir::Expr we get here is the initializer of
+                            // the constant, what we really want is the item
+                            // DefId.
+                            let const_node_id = tcx.map.get_parent(expr.id);
+                            let def_id = if tcx.map.is_inlined_node_id(const_node_id) {
+                                tcx.sess.cstore.defid_for_inlined_node(const_node_id).unwrap()
+                            } else {
+                                tcx.map.local_def_id(const_node_id)
+                            };
+
+                            collect_const_item_neighbours(self.scx,
+                                                          def_id,
+                                                          substs,
+                                                          self.output);
+                        }
+                    }
+
+                    None
+                }
+            }
             _ => None
         };
 
@@ -627,7 +665,7 @@ fn visit_terminator_kind(&mut self,
                 match constant.ty.sty {
                     ty::TyFnDef(def_id, _, bare_fn_ty)
                         if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
-                        let operand_ty = self.mir.operand_ty(tcx, &args[0]);
+                        let operand_ty = args[0].ty(self.mir, tcx);
                         if let ty::TyRawPtr(mt) = operand_ty.sty {
                             let operand_ty = monomorphize::apply_param_substs(tcx,
                                                                               self.param_substs,
@@ -796,6 +834,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         ty::TyProjection(_) |
         ty::TyParam(_)      |
         ty::TyInfer(_)      |
+        ty::TyAnon(..)      |
         ty::TyError         => {
             bug!("encountered unexpected type");
         }
@@ -1116,10 +1155,8 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                 self.output.push(TransItem::Static(item.id));
             }
             hir::ItemConst(..) => {
-                debug!("RootCollector: ItemConst({})",
-                       def_id_to_string(self.scx.tcx(),
-                                        self.scx.tcx().map.local_def_id(item.id)));
-                add_roots_for_const_item(self.scx, item.id, self.output);
+                // const items only generate translation items if they are
+                // actually used somewhere. Just declaring them is insufficient.
             }
             hir::ItemFn(_, _, _, _, ref generics, _) => {
                 if !generics.is_type_parameterized() {
@@ -1243,23 +1280,21 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 // There are no translation items for constants themselves but their
 // initializers might still contain something that produces translation items,
 // such as cast that introduce a new vtable.
-fn add_roots_for_const_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                      const_item_node_id: NodeId,
-                                      output: &mut Vec<TransItem<'tcx>>)
+fn collect_const_item_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
+                                           def_id: DefId,
+                                           substs: &'tcx Substs<'tcx>,
+                                           output: &mut Vec<TransItem<'tcx>>)
 {
-    let def_id = scx.tcx().map.local_def_id(const_item_node_id);
-
     // Scan the MIR in order to find function calls, closures, and
     // drop-glue
     let mir = errors::expect(scx.sess().diagnostic(), scx.get_mir(def_id),
         || format!("Could not find MIR for const: {:?}", def_id));
 
-    let empty_substs = scx.empty_substs_for_def_id(def_id);
     let visitor = MirNeighborCollector {
         scx: scx,
         mir: &mir,
         output: output,
-        param_substs: empty_substs
+        param_substs: substs
     };
 
     visit_mir_and_promoted(visitor, &mir);
index a1783e9c0a3829960035925d7f39d6183b28f4cb..dea5a1560e15b0564f94aaf8b29bb16a5cdc80fc 100644 (file)
@@ -40,7 +40,7 @@
 use value::Value;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::Layout;
-use rustc::traits::{self, SelectionContext, ProjectionMode};
+use rustc::traits::{self, SelectionContext, Reveal};
 use rustc::ty::fold::TypeFoldable;
 use rustc::hir;
 use util::nodemap::NodeMap;
@@ -128,7 +128,7 @@ pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
 pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
                                   -> bool {
     let tcx = ccx.tcx();
-    let layout = tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+    let layout = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
         match ty.layout(&infcx) {
             Ok(layout) => layout,
             Err(err) => {
@@ -1136,7 +1136,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 
         // Do the initial selection for the obligation. This yields the
         // shallow result we are looking for -- that is, what specific impl.
-        tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+        tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
             let mut selcx = SelectionContext::new(&infcx);
 
             let obligation_cause = traits::ObligationCause::misc(span,
@@ -1195,7 +1195,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("normalize_and_test_predicates(predicates={:?})",
            predicates);
 
-    tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+    tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
         let mut selcx = SelectionContext::new(&infcx);
         let mut fulfill_cx = traits::FulfillmentContext::new();
         let cause = traits::ObligationCause::dummy();
@@ -1244,7 +1244,7 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }), ..}) => ty,
         _ => ctor_ty
     }.ty_adt_def().unwrap();
-    let variant_def_id = if ccx.tcx().map.is_inlined(inlined_vid) {
+    let variant_def_id = if ccx.tcx().map.is_inlined_node_id(inlined_vid) {
         ccx.defid_for_inlined_node(inlined_vid).unwrap()
     } else {
         ccx.tcx().map.local_def_id(inlined_vid)
index 7afb5257258ec38f5c5b26100e7ececad4bbff9f..769dd008af8f495c3602737f04e7b99e2187f7ed 100644 (file)
@@ -1026,7 +1026,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
                              .get(TransItem::Static(id))
                              .expect("Local statics should always be in the SymbolMap");
                 // Make sure that this is never executed for something inlined.
-                assert!(!ccx.tcx().map.is_inlined(id));
+                assert!(!ccx.tcx().map.is_inlined_node_id(id));
 
                 let defined_in_current_codegen_unit = ccx.codegen_unit()
                                                          .items()
index 166ce990fddfa72303618ca5d0aea7cad9c20dee..65eea1bbb6337cba32e1737be9da86b04a3f6d19 100644 (file)
@@ -81,7 +81,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     check_overflow: bool,
     check_drop_flag_for_sanity: bool,
     mir_map: &'a MirMap<'tcx>,
-    mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
+    mir_cache: RefCell<DepTrackingMap<MirCache<'tcx>>>,
 
     use_dll_storage_attrs: bool,
 
@@ -186,6 +186,19 @@ fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
     }
 }
 
+// Cache for mir loaded from metadata
+struct MirCache<'tcx> {
+    data: PhantomData<&'tcx ()>
+}
+
+impl<'tcx> DepTrackingMapConfig for MirCache<'tcx> {
+    type Key = DefId;
+    type Value = Rc<mir::Mir<'tcx>>;
+    fn to_dep_node(key: &DefId) -> DepNode<DefId> {
+        DepNode::Mir(*key)
+    }
+}
+
 /// This list owns a number of LocalCrateContexts and binds them to their common
 /// SharedCrateContext. This type just exists as a convenience, something to
 /// pass around all LocalCrateContexts with and get an iterator over them.
@@ -324,16 +337,14 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
         None => &sess.target.target.options.relocation_model[..],
     };
 
-    match reloc_model_arg {
-        "pic" => llvm::RelocMode::PIC,
-        "static" => llvm::RelocMode::Static,
-        "default" => llvm::RelocMode::Default,
-        "dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
+    match ::back::write::RELOC_MODEL_ARGS.iter().find(
+        |&&arg| arg.0 == reloc_model_arg) {
+        Some(x) => x.1,
         _ => {
             sess.err(&format!("{:?} is not a valid relocation mode",
                              sess.opts
                                  .cg
-                                 .relocation_model));
+                                 .code_model));
             sess.abort_if_errors();
             bug!();
         }
@@ -474,7 +485,7 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
             symbol_hasher: RefCell::new(symbol_hasher),
             tcx: tcx,
             mir_map: mir_map,
-            mir_cache: RefCell::new(DefIdMap()),
+            mir_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
             stats: Stats {
                 n_glues_created: Cell::new(0),
                 n_null_glues: Cell::new(0),
@@ -538,8 +549,7 @@ pub fn use_dll_storage_attrs(&self) -> bool {
 
     pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
         if def_id.is_local() {
-            let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
-            self.mir_map.map.get(&node_id).map(CachedMir::Ref)
+            self.mir_map.map.get(&def_id).map(CachedMir::Ref)
         } else {
             if let Some(mir) = self.mir_cache.borrow().get(&def_id).cloned() {
                 return Some(CachedMir::Owned(mir));
index 8011347d3eb12c76770dd9c447b03147653d5214..ee13af80b2ba0aeff7741bb4a5a687305b0bbb50 100644 (file)
@@ -326,7 +326,7 @@ fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
             // First, find out the 'real' def_id of the type. Items inlined from
             // other crates have to be mapped back to their source.
             let def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
-                if cx.tcx().map.is_inlined(node_id) {
+                if cx.tcx().map.is_inlined_node_id(node_id) {
                     // The given def_id identifies the inlined copy of a
                     // type definition, let's take the source of the copy.
                     cx.defid_for_inlined_node(node_id).unwrap()
@@ -1846,7 +1846,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
     // crate should already contain debuginfo for it. More importantly, the
     // global might not even exist in un-inlined form anywhere which would lead
     // to a linker errors.
-    if cx.tcx().map.is_inlined(node_id) {
+    if cx.tcx().map.is_inlined_node_id(node_id) {
         return;
     }
 
index 63f460e4693d56be227fb0daf7a09d20018d4afa..bee2667c71f9db974660ff39bde162776e9379b3 100644 (file)
@@ -150,6 +150,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyError |
         ty::TyInfer(_) |
         ty::TyProjection(..) |
+        ty::TyAnon(..) |
         ty::TyParam(_) => {
             bug!("debuginfo: Trying to create type name for \
                 unexpected type: {:?}", t);
index 6bc48546dfa8c7c9b7b9f4454d0218d7618c8137..93e5f4ba1e205cec5dfd64577a54ea7564065a8f 100644 (file)
@@ -115,7 +115,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match t.sty {
         ty::TyBox(typ) if !type_needs_drop(tcx, typ)
                          && type_is_sized(tcx, typ) => {
-            tcx.normalizing_infer_ctxt(traits::ProjectionMode::Any).enter(|infcx| {
+            tcx.normalizing_infer_ctxt(traits::Reveal::All).enter(|infcx| {
                 let layout = t.layout(&infcx).unwrap();
                 if layout.size(&tcx.data_layout).bytes() == 0 {
                     // `Box<ZeroSizeType>` does not allocate.
index ac6af8d66e19ff55b24c84ce9e099147071c4506..3d6093d4d6960f16aeeab3e697a71564414bc823 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::ty::subst::{FnSpace, Subst, Substs};
 use rustc::ty::subst;
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use abi::FnType;
 use base::*;
 use build::*;
@@ -321,7 +321,7 @@ pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() {
         Some(node_item) => {
-            let substs = tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+            let substs = tcx.normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
                 let substs = traits::translate_substs(&infcx, impl_def_id,
                                                       substs, node_item.node);
                 tcx.lift(&substs).unwrap_or_else(|| {
index dac7afab6e38b4d85de41d18f1c2fae4b837c9d4..d6dbefec0346752254731824e160fbe80a4e9db5 100644 (file)
@@ -143,7 +143,8 @@ fn visit_lvalue(&mut self,
         // Allow uses of projections of immediate pair fields.
         if let mir::Lvalue::Projection(ref proj) = *lvalue {
             if self.mir.local_index(&proj.base).is_some() {
-                let ty = self.mir.lvalue_ty(self.bcx.tcx(), &proj.base);
+                let ty = proj.base.ty(self.mir, self.bcx.tcx());
+
                 let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
                 if common::type_is_imm_pair(self.bcx.ccx(), ty) {
                     if let mir::ProjectionElem::Field(..) = proj.elem {
@@ -170,7 +171,7 @@ fn visit_lvalue(&mut self,
                     self.mark_as_lvalue(index);
                 }
                 LvalueContext::Drop => {
-                    let ty = self.mir.lvalue_ty(self.bcx.tcx(), lvalue);
+                    let ty = lvalue.ty(self.mir, self.bcx.tcx());
                     let ty = self.bcx.monomorphize(&ty.to_ty(self.bcx.tcx()));
 
                     // Only need the lvalue if we're actually dropping it.
index 9bfdb511c623c97f34974b9711b443978ffcea3b..b1fd3e88d75f00c8d579f8e0feb9fa45773b7adf 100644 (file)
@@ -230,7 +230,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
             }
 
             mir::TerminatorKind::Drop { ref location, target, unwind } => {
-                let ty = mir.lvalue_ty(bcx.tcx(), location).to_ty(bcx.tcx());
+                let ty = location.ty(&mir, bcx.tcx()).to_ty(bcx.tcx());
                 let ty = bcx.monomorphize(&ty);
 
                 // Double check for necessity to drop
@@ -433,7 +433,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
 
                 let extra_args = &args[sig.inputs.len()..];
                 let extra_args = extra_args.iter().map(|op_arg| {
-                    let op_ty = self.mir.operand_ty(bcx.tcx(), op_arg);
+                    let op_ty = op_arg.ty(&self.mir, bcx.tcx());
                     bcx.monomorphize(&op_ty)
                 }).collect::<Vec<_>>();
                 let fn_ty = callee.direct_fn_type(bcx.ccx(), &extra_args);
@@ -828,7 +828,7 @@ fn make_return_dest(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
             return ReturnDest::Nothing;
         }
         let dest = if let Some(index) = self.mir.local_index(dest) {
-            let ret_ty = self.lvalue_ty(dest);
+            let ret_ty = self.monomorphized_lvalue_ty(dest);
             match self.locals[index] {
                 LocalRef::Lvalue(dest) => dest,
                 LocalRef::Operand(None) => {
index 00db19d2739c3953d95615af8801e6169acb13ae..7ca94b6356e40185f5ce73b31ec5693b9d6c45b1 100644 (file)
@@ -278,13 +278,16 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalFailure> {
                 let span = statement.source_info.span;
                 match statement.kind {
                     mir::StatementKind::Assign(ref dest, ref rvalue) => {
-                        let ty = self.mir.lvalue_ty(tcx, dest);
+                        let ty = dest.ty(self.mir, tcx);
                         let ty = self.monomorphize(&ty).to_ty(tcx);
                         match self.const_rvalue(rvalue, ty, span) {
                             Ok(value) => self.store(dest, value, span),
                             Err(err) => if failure.is_ok() { failure = Err(err); }
                         }
                     }
+                    mir::StatementKind::SetDiscriminant{ .. } => {
+                        span_bug!(span, "SetDiscriminant should not appear in constants?");
+                    }
                 }
             }
 
@@ -327,7 +330,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalFailure> {
                 }
 
                 mir::TerminatorKind::Call { ref func, ref args, ref destination, .. } => {
-                    let fn_ty = self.mir.operand_ty(tcx, func);
+                    let fn_ty = func.ty(self.mir, tcx);
                     let fn_ty = self.monomorphize(&fn_ty);
                     let instance = match fn_ty.sty {
                         ty::TyFnDef(def_id, substs, _) => {
@@ -386,7 +389,7 @@ fn const_lvalue(&self, lvalue: &mir::Lvalue<'tcx>, span: Span)
                 ConstLvalue {
                     base: Base::Static(consts::get_static(self.ccx, def_id).val),
                     llextra: ptr::null_mut(),
-                    ty: self.mir.lvalue_ty(tcx, lvalue).to_ty(tcx)
+                    ty: lvalue.ty(self.mir, tcx).to_ty(tcx)
                 }
             }
             mir::Lvalue::Projection(ref projection) => {
@@ -723,7 +726,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                 let lhs = self.const_operand(lhs, span)?;
                 let rhs = self.const_operand(rhs, span)?;
                 let ty = lhs.ty;
-                let binop_ty = self.mir.binop_ty(tcx, op, lhs.ty, rhs.ty);
+                let binop_ty = op.ty(tcx, lhs.ty, rhs.ty);
                 let (lhs, rhs) = (lhs.llval, rhs.llval);
                 Const::new(const_scalar_binop(op, lhs, rhs, ty), binop_ty)
             }
@@ -732,7 +735,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                 let lhs = self.const_operand(lhs, span)?;
                 let rhs = self.const_operand(rhs, span)?;
                 let ty = lhs.ty;
-                let val_ty = self.mir.binop_ty(tcx, op, lhs.ty, rhs.ty);
+                let val_ty = op.ty(tcx, lhs.ty, rhs.ty);
                 let binop_ty = tcx.mk_tup(vec![val_ty, tcx.types.bool]);
                 let (lhs, rhs) = (lhs.llval, rhs.llval);
                 assert!(!ty.is_fp());
index ceaba2a40ca55f77c7773194d179c0a838e53550..94db2e3c23cef29a965a16c4bb7feec768e9f3b7 100644 (file)
@@ -108,7 +108,7 @@ pub fn trans_lvalue(&mut self,
             mir::Lvalue::Arg(_) |
             mir::Lvalue::ReturnPointer => bug!(), // handled above
             mir::Lvalue::Static(def_id) => {
-                let const_ty = self.lvalue_ty(lvalue);
+                let const_ty = self.monomorphized_lvalue_ty(lvalue);
                 LvalueRef::new_sized(consts::get_static(ccx, def_id).val,
                                      LvalueTy::from_ty(const_ty))
             },
@@ -200,7 +200,7 @@ pub fn trans_lvalue(&mut self,
                             ty::TyArray(..) => {
                                 // must cast the lvalue pointer type to the new
                                 // array type (*[%_; new_len]).
-                                let base_ty = self.lvalue_ty(lvalue);
+                                let base_ty = self.monomorphized_lvalue_ty(lvalue);
                                 let llbasety = type_of::type_of(bcx.ccx(), base_ty).ptr_to();
                                 let llbase = bcx.pointercast(llbase, llbasety);
                                 (llbase, ptr::null_mut())
@@ -240,7 +240,7 @@ pub fn with_lvalue_ref<F, U>(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
             match self.locals[index] {
                 LocalRef::Lvalue(lvalue) => f(self, lvalue),
                 LocalRef::Operand(None) => {
-                    let lvalue_ty = self.lvalue_ty(lvalue);
+                    let lvalue_ty = self.monomorphized_lvalue_ty(lvalue);
                     let lvalue = LvalueRef::alloca(bcx,
                                                    lvalue_ty,
                                                    "lvalue_temp");
@@ -252,7 +252,7 @@ pub fn with_lvalue_ref<F, U>(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
                 LocalRef::Operand(Some(_)) => {
                     // See comments in LocalRef::new_operand as to why
                     // we always have Some in a ZST LocalRef::Operand.
-                    let ty = self.lvalue_ty(lvalue);
+                    let ty = self.monomorphized_lvalue_ty(lvalue);
                     if common::type_is_zero_size(bcx.ccx(), ty) {
                         // Pass an undef pointer as no stores can actually occur.
                         let llptr = C_undef(type_of(bcx.ccx(), ty).ptr_to());
@@ -289,9 +289,9 @@ fn prepare_index(&mut self,
         }
     }
 
-    pub fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
+    pub fn monomorphized_lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> Ty<'tcx> {
         let tcx = self.fcx.ccx.tcx();
-        let lvalue_ty = self.mir.lvalue_ty(tcx, lvalue);
+        let lvalue_ty = lvalue.ty(&self.mir, tcx);
         self.fcx.monomorphize(&lvalue_ty.to_ty(tcx))
     }
 }
index 97d65ce9c53614bf1a2600fd48e6c0fb1f15f3cc..9f7c2ee219eb5abafed3bc90684a3ffc6a159fbb 100644 (file)
@@ -400,7 +400,7 @@ pub fn trans_rvalue_operand(&mut self,
                 };
                 let operand = OperandRef {
                     val: OperandValue::Immediate(llresult),
-                    ty: self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty),
+                    ty: op.ty(bcx.tcx(), lhs.ty, rhs.ty),
                 };
                 (bcx, operand)
             }
@@ -410,7 +410,7 @@ pub fn trans_rvalue_operand(&mut self,
                 let result = self.trans_scalar_checked_binop(&bcx, op,
                                                              lhs.immediate(), rhs.immediate(),
                                                              lhs.ty);
-                let val_ty = self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty);
+                let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty);
                 let operand_ty = bcx.tcx().mk_tup(vec![val_ty, bcx.tcx().types.bool]);
                 let operand = OperandRef {
                     val: result,
index 55efa75b17336aafdea56e516b496388d19a5a36..7e3074f4cedf0740beed7f444454e9561a76a2e0 100644 (file)
@@ -14,6 +14,8 @@
 
 use super::MirContext;
 use super::LocalRef;
+use super::super::adt;
+use super::super::disr::Disr;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_statement(&mut self,
@@ -39,7 +41,7 @@ pub fn trans_statement(&mut self,
                             bcx
                         }
                         LocalRef::Operand(Some(_)) => {
-                            let ty = self.lvalue_ty(lvalue);
+                            let ty = self.monomorphized_lvalue_ty(lvalue);
 
                             if !common::type_is_zero_size(bcx.ccx(), ty) {
                                 span_bug!(statement.source_info.span,
@@ -57,6 +59,18 @@ pub fn trans_statement(&mut self,
                     self.trans_rvalue(bcx, tr_dest, rvalue, debug_loc)
                 }
             }
+            mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => {
+                let ty = self.monomorphized_lvalue_ty(lvalue);
+                let repr = adt::represent_type(bcx.ccx(), ty);
+                let lvalue_transed = self.trans_lvalue(&bcx, lvalue);
+                bcx.with_block(|bcx|
+                    adt::trans_set_discr(bcx,
+                                         &repr,
+                                        lvalue_transed.llval,
+                                        Disr::from(variant_index))
+                );
+                bcx
+            }
         }
     }
 }
index 35bb0481c8e979e6f82248a111fa18254fb078eb..187ffe353fdcb5f596bd87dbfb0994feaa8e8c79 100644 (file)
@@ -83,8 +83,6 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
         // that the incoming edges to a particular fn are from a
         // particular set.
 
-        self.register_reads(ccx);
-
         match *self {
             TransItem::Static(node_id) => {
                 let def_id = ccx.tcx().map.local_def_id(node_id);
@@ -120,46 +118,6 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
                ccx.codegen_unit().name());
     }
 
-    /// If necessary, creates a subtask for trans'ing a particular item and registers reads on
-    /// `TypeckItemBody` and `Hir`.
-    fn register_reads(&self, ccx: &CrateContext<'a, 'tcx>) {
-        let tcx = ccx.tcx();
-        let def_id = match *self {
-            TransItem::Static(node_id) => {
-                tcx.map.local_def_id(node_id)
-            }
-            TransItem::Fn(instance) => {
-                if let Some(node) = tcx.map.as_local_node_id(instance.def) {
-                    if let hir_map::Node::NodeItem(_) = tcx.map.get(node) {
-                        // This already is a "real" item
-                        instance.def
-                    } else {
-                        // Get the enclosing item and register a read on it
-                        tcx.map.get_parent_did(node)
-                    }
-                } else {
-                    // Translating an inlined item from another crate? Don't track anything.
-                    return;
-                }
-            }
-            TransItem::DropGlue(_) => {
-                // Nothing to track for drop glue
-                return;
-            }
-        };
-
-        tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
-            tcx.dep_graph.read(DepNode::Hir(def_id));
-
-            // We are going to be accessing various tables
-            // generated by TypeckItemBody; we also assume
-            // that the body passes type check. These tables
-            // are not individually tracked, so just register
-            // a read here.
-            tcx.dep_graph.read(DepNode::TypeckItemBody(def_id));
-        });
-    }
-
     pub fn predefine(&self,
                      ccx: &CrateContext<'a, 'tcx>,
                      linkage: llvm::Linkage) {
@@ -578,7 +536,8 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::TyError |
         ty::TyInfer(_) |
         ty::TyProjection(..) |
-        ty::TyParam(_) => {
+        ty::TyParam(_) |
+        ty::TyAnon(..) => {
             bug!("debuginfo: Trying to create type name for \
                   unexpected type: {:?}", t);
         }
index e5acb9b6699bd2ea5bb6ce9924a6c8192f22a89e..cde53f6fa899cb9c89a33977e8e42070764b6f19 100644 (file)
@@ -16,7 +16,7 @@
 use adt;
 use common::*;
 use machine;
-use rustc::traits::ProjectionMode;
+use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TypeFoldable};
 
 use type_::Type;
@@ -112,7 +112,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
+        ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
+        ty::TyAnon(..) | ty::TyError => {
             bug!("fictitious type {:?} in sizing_type_of()", t)
         }
         ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!()
@@ -123,7 +124,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
 
     // FIXME(eddyb) Temporary sanity check for ty::layout.
-    let layout = cx.tcx().normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
+    let layout = cx.tcx().normalizing_infer_ctxt(Reveal::All).enter(|infcx| {
         t.layout(&infcx)
     });
     match layout {
@@ -339,10 +340,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           }
       }
 
-      ty::TyInfer(..) => bug!("type_of with TyInfer"),
-      ty::TyProjection(..) => bug!("type_of with TyProjection"),
-      ty::TyParam(..) => bug!("type_of with ty_param"),
-      ty::TyError => bug!("type_of with TyError"),
+      ty::TyInfer(..) |
+      ty::TyProjection(..) |
+      ty::TyParam(..) |
+      ty::TyAnon(..) |
+      ty::TyError => bug!("type_of with {:?}", t),
     };
 
     debug!("--> mapped t={:?} to llty={:?}", t, llty);
index b4e9fb5c65bb3576417b53469e454c262a249830..ad61b5b0b513eb355d664e7e4695e1c40de36cf2 100644 (file)
@@ -56,6 +56,7 @@
 use middle::resolve_lifetime as rl;
 use rustc::lint;
 use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
+use rustc::ty::subst::VecPerParamSpace;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
@@ -64,6 +65,7 @@
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
              ElisionFailureInfo, ElidedLifetime};
+use rscope::{AnonTypeScope, MaybeWithAnonTypes};
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::{NodeMap, FnvHashSet};
 
@@ -360,8 +362,11 @@ pub fn ast_path_substs_for_ty(&self,
                 self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
             }
             hir::ParenthesizedParameters(..) => {
-                span_err!(tcx.sess, span, E0214,
-                          "parenthesized parameters may only be used with a trait");
+                struct_span_err!(tcx.sess, span, E0214,
+                          "parenthesized parameters may only be used with a trait")
+                    .span_label(span, &format!("only traits may use parentheses"))
+                    .emit();
+
                 let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
                 (Substs::empty(),
                  ty_param_defs.iter().map(|_| tcx.types.err).collect(),
@@ -631,20 +636,21 @@ fn find_implied_output_region(&self,
 
     fn convert_ty_with_lifetime_elision(&self,
                                         elided_lifetime: ElidedLifetime,
-                                        ty: &hir::Ty)
+                                        ty: &hir::Ty,
+                                        anon_scope: Option<AnonTypeScope>)
                                         -> Ty<'tcx>
     {
         match elided_lifetime {
             Ok(implied_output_region) => {
                 let rb = ElidableRscope::new(implied_output_region);
-                self.ast_ty_to_ty(&rb, ty)
+                self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
             }
             Err(param_lifetimes) => {
                 // All regions must be explicitly specified in the output
                 // if the lifetime elision rules do not apply. This saves
                 // the user from potentially-confusing errors.
                 let rb = UnelidableRscope::new(param_lifetimes);
-                self.ast_ty_to_ty(&rb, ty)
+                self.ast_ty_to_ty(&MaybeWithAnonTypes::new(rb, anon_scope), ty)
             }
         }
     }
@@ -661,7 +667,8 @@ fn convert_parenthesized_parameters(&self,
         let region_substs =
             self.create_region_substs(rscope, span, decl_generics, Vec::new());
 
-        let binding_rscope = BindingRscope::new();
+        let anon_scope = rscope.anon_type_scope();
+        let binding_rscope = MaybeWithAnonTypes::new(BindingRscope::new(), anon_scope);
         let inputs =
             data.inputs.iter()
                        .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
@@ -675,7 +682,9 @@ fn convert_parenthesized_parameters(&self,
 
         let (output, output_span) = match data.output {
             Some(ref output_ty) => {
-                (self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
+                (self.convert_ty_with_lifetime_elision(implied_output_region,
+                                                       &output_ty,
+                                                       anon_scope),
                  output_ty.span)
             }
             None => {
@@ -1201,10 +1210,13 @@ fn make_object_type(&self,
         }
 
         for (trait_def_id, name) in associated_types {
-            span_err!(tcx.sess, span, E0191,
+            struct_span_err!(tcx.sess, span, E0191,
                 "the value of the associated type `{}` (from the trait `{}`) must be specified",
                         name,
-                        tcx.item_path_str(trait_def_id));
+                        tcx.item_path_str(trait_def_id))
+                        .span_label(span, &format!(
+                            "missing associated type `{}` value", name))
+                        .emit();
         }
 
         tcx.mk_trait(object.principal, object.bounds)
@@ -1281,10 +1293,12 @@ fn one_bound_for_assoc_type(&self,
         }
 
         if bounds.len() > 1 {
-            let mut err = struct_span_err!(self.tcx().sess, span, E0221,
-                                           "ambiguous associated type `{}` in bounds of `{}`",
-                                           assoc_name,
-                                           ty_param_name);
+            let mut err = struct_span_err!(
+                self.tcx().sess, span, E0221,
+                "ambiguous associated type `{}` in bounds of `{}`",
+                assoc_name,
+                ty_param_name);
+            err.span_label(span, &format!("ambiguous associated type `{}`", assoc_name));
 
             for bound in &bounds {
                 span_note!(&mut err, span,
@@ -1584,9 +1598,11 @@ fn base_def_to_ty(&self,
                 return self.tcx().types.err;
             }
             _ => {
-                span_err!(tcx.sess, span, E0248,
-                          "found value `{}` used as a type",
-                          tcx.item_path_str(def.def_id()));
+                struct_span_err!(tcx.sess, span, E0248,
+                           "found value `{}` used as a type",
+                            tcx.item_path_str(def.def_id()))
+                           .span_label(span, &format!("value used as a type"))
+                           .emit();
                 return self.tcx().types.err;
             }
         }
@@ -1692,7 +1708,14 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
             }
             hir::TyBareFn(ref bf) => {
                 require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-                let bare_fn_ty = self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl);
+                let anon_scope = rscope.anon_type_scope();
+                let (bare_fn_ty, _) =
+                    self.ty_of_method_or_bare_fn(bf.unsafety,
+                                                 bf.abi,
+                                                 None,
+                                                 &bf.decl,
+                                                 anon_scope,
+                                                 anon_scope);
 
                 // Find any late-bound regions declared in return type that do
                 // not appear in the arguments. These are not wellformed.
@@ -1735,6 +1758,34 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyPolyTraitRef(ref bounds) => {
                 self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
             }
+            hir::TyImplTrait(ref bounds) => {
+                use collect::{compute_bounds, SizedByDefault};
+
+                // Create the anonymized type.
+                let def_id = tcx.map.local_def_id(ast_ty.id);
+                if let Some(anon_scope) = rscope.anon_type_scope() {
+                    let substs = anon_scope.fresh_substs(tcx);
+                    let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs);
+
+                    // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
+                    let bounds = compute_bounds(self, ty, bounds,
+                                                SizedByDefault::Yes,
+                                                Some(anon_scope),
+                                                ast_ty.span);
+                    let predicates = bounds.predicates(tcx, ty);
+                    let predicates = tcx.lift_to_global(&predicates).unwrap();
+                    tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates {
+                        predicates: VecPerParamSpace::new(vec![], vec![], predicates)
+                    });
+
+                    ty
+                } else {
+                    span_err!(tcx.sess, ast_ty.span, E0562,
+                              "`impl Trait` not allowed outside of function \
+                               and inherent method return types");
+                    tcx.types.err
+                }
+            }
             hir::TyPath(ref maybe_qself, ref path) => {
                 debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
                 let path_res = tcx.expect_resolution(ast_ty.id);
@@ -1799,36 +1850,40 @@ pub fn ty_of_arg(&self,
 
     pub fn ty_of_method(&self,
                         sig: &hir::MethodSig,
-                        untransformed_self_ty: Ty<'tcx>)
+                        untransformed_self_ty: Ty<'tcx>,
+                        anon_scope: Option<AnonTypeScope>)
                         -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
-        let (bare_fn_ty, optional_explicit_self_category) =
-            self.ty_of_method_or_bare_fn(sig.unsafety,
-                                         sig.abi,
-                                         Some(untransformed_self_ty),
-                                         &sig.decl);
-        (bare_fn_ty, optional_explicit_self_category)
+        self.ty_of_method_or_bare_fn(sig.unsafety,
+                                     sig.abi,
+                                     Some(untransformed_self_ty),
+                                     &sig.decl,
+                                     None,
+                                     anon_scope)
     }
 
     pub fn ty_of_bare_fn(&self,
                          unsafety: hir::Unsafety,
                          abi: abi::Abi,
-                         decl: &hir::FnDecl)
+                         decl: &hir::FnDecl,
+                         anon_scope: Option<AnonTypeScope>)
                          -> &'tcx ty::BareFnTy<'tcx> {
-        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl).0
+        self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0
     }
 
-    fn ty_of_method_or_bare_fn<'a>(&self,
-                                   unsafety: hir::Unsafety,
-                                   abi: abi::Abi,
-                                   opt_untransformed_self_ty: Option<Ty<'tcx>>,
-                                   decl: &hir::FnDecl)
-                                   -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
+    fn ty_of_method_or_bare_fn(&self,
+                               unsafety: hir::Unsafety,
+                               abi: abi::Abi,
+                               opt_untransformed_self_ty: Option<Ty<'tcx>>,
+                               decl: &hir::FnDecl,
+                               arg_anon_scope: Option<AnonTypeScope>,
+                               ret_anon_scope: Option<AnonTypeScope>)
+                               -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory)
     {
         debug!("ty_of_method_or_bare_fn");
 
         // New region names that appear inside of the arguments of the function
         // declaration are bound to that function type.
-        let rb = rscope::BindingRscope::new();
+        let rb = MaybeWithAnonTypes::new(BindingRscope::new(), arg_anon_scope);
 
         // `implied_output_region` is the region that will be assumed for any
         // region parameters in the return type. In accordance with the rules for
@@ -1866,7 +1921,8 @@ fn ty_of_method_or_bare_fn<'a>(&self,
         let output_ty = match decl.output {
             hir::Return(ref output) =>
                 ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
-                                                                       &output)),
+                                                                       &output,
+                                                                       ret_anon_scope)),
             hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
             hir::NoReturn(..) => ty::FnDiverging
         };
index fe68690d4e97447efbc826717314234bbffb86ec..5f255cc1fb730112b1df500d28a65b18fec18dfb 100644 (file)
@@ -633,10 +633,23 @@ fn check_pat_tuple_struct(&self,
                 self.check_pat(&subpat, field_ty);
             }
         } else {
-            span_err!(tcx.sess, pat.span, E0023,
-                      "this pattern has {} field{s}, but the corresponding {} has {} field{s}",
-                      subpats.len(), def.kind_name(), variant.fields.len(),
-                      s = if variant.fields.len() == 1 {""} else {"s"});
+            let subpats_ending = if subpats.len() == 1 {
+                ""
+            } else {
+                "s"
+            };
+            let fields_ending = if variant.fields.len() == 1 {
+                ""
+            } else {
+                "s"
+            };
+            struct_span_err!(tcx.sess, pat.span, E0023,
+                             "this pattern has {} field{}, but the corresponding {} has {} field{}",
+                             subpats.len(), subpats_ending, def.kind_name(),
+                             variant.fields.len(),  fields_ending)
+                .span_label(pat.span, &format!("expected {} field{}, found {}",
+                                               variant.fields.len(), fields_ending, subpats.len()))
+                .emit();
             on_error();
         }
     }
@@ -682,10 +695,16 @@ pub fn check_struct_pat_fields(&self,
                     field_map.get(&field.name)
                         .map(|f| self.field_ty(span, f, substs))
                         .unwrap_or_else(|| {
-                            span_err!(tcx.sess, span, E0026,
-                                "struct `{}` does not have a field named `{}`",
-                                tcx.item_path_str(variant.did),
-                                field.name);
+                            struct_span_err!(tcx.sess, span, E0026,
+                                             "struct `{}` does not have a field named `{}`",
+                                             tcx.item_path_str(variant.did),
+                                             field.name)
+                                .span_label(span,
+                                            &format!("struct `{}` does not have field `{}`",
+                                                     tcx.item_path_str(variant.did),
+                                                     field.name))
+                                .emit();
+
                             tcx.types.err
                         })
                 }
index b971ae02cd0bd27a87905137df7540a80142257b..e6ddc6ad69379922d7f94282c66389683edb8c50 100644 (file)
 use middle::free_region::FreeRegionMap;
 use rustc::infer::{self, InferOk, TypeOrigin};
 use rustc::ty;
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::error::ExpectedFound;
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
+use rustc::hir::map::Node;
+use rustc::hir::{ImplItemKind, TraitItem_};
 
 use syntax::ast;
 use syntax_pos::Span;
@@ -211,7 +213,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         return;
     }
 
-    tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|mut infcx| {
+    tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| {
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
         // Normalize the associated types in the trait_bounds.
@@ -431,7 +433,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
            impl_trait_ref);
 
     let tcx = ccx.tcx;
-    tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
+    tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
         // The below is for the most part highly similar to the procedure
@@ -461,7 +463,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         // Compute skolemized form of impl and trait const tys.
         let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
         let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
-        let origin = TypeOrigin::Misc(impl_c_span);
+        let mut origin = TypeOrigin::Misc(impl_c_span);
 
         let err = infcx.commit_if_ok(|_| {
             // There is no "body" here, so just pass dummy id.
@@ -496,11 +498,31 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
                    impl_ty,
                    trait_ty);
+
+            // Locate the Span containing just the type of the offending impl
+            if let Some(impl_trait_node) = tcx.map.get_if_local(impl_c.def_id) {
+                if let Node::NodeImplItem(impl_trait_item) = impl_trait_node {
+                    if let ImplItemKind::Const(ref ty, _) = impl_trait_item.node {
+                        origin = TypeOrigin::Misc(ty.span);
+                    }
+                }
+            }
+
             let mut diag = struct_span_err!(
                 tcx.sess, origin.span(), E0326,
                 "implemented const `{}` has an incompatible type for trait",
                 trait_c.name
             );
+
+            // Add a label to the Span containing just the type of the item
+            if let Some(orig_trait_node) = tcx.map.get_if_local(trait_c.def_id) {
+                if let Node::NodeTraitItem(orig_trait_item) = orig_trait_node {
+                    if let TraitItem_::ConstTraitItem(ref ty, _) = orig_trait_item.node {
+                        diag.span_label(ty.span, &format!("original trait requirement"));
+                    }
+                }
+            }
+
             infcx.note_type_err(
                 &mut diag, origin,
                 Some(infer::ValuePairs::Types(ExpectedFound {
index 56e4108153e1e669f0a2db85a67657be56cf2801..f65e15430daf75c7de17357c61f1bab01cc2d49a 100644 (file)
@@ -17,7 +17,7 @@
 use middle::region;
 use rustc::ty::subst::{self, Subst};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use util::nodemap::FnvHashSet;
 
 use syntax::ast;
@@ -84,7 +84,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
     // check that the impl type can be made to match the trait type.
 
     let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
-    tcx.infer_ctxt(None, Some(impl_param_env), ProjectionMode::AnyFinal).enter(|infcx| {
+    tcx.infer_ctxt(None, Some(impl_param_env), Reveal::NotSpecializable).enter(|infcx| {
         let tcx = infcx.tcx;
         let mut fulfillment_cx = traits::FulfillmentContext::new();
 
@@ -499,7 +499,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
         }
 
         // these are always dtorck
-        ty::TyTrait(..) | ty::TyProjection(_) => bug!(),
+        ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(),
     }
 }
 
@@ -509,7 +509,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
             def.is_dtorck(tcx)
         }
-        ty::TyTrait(..) | ty::TyProjection(..) => {
+        ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
             debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
             true
         },
index 8a53c59b4c7fad08dafbe1215cb6d8bf52914885..9051b1c8069bde3583af62b07cb215efd70b5f3f 100644 (file)
@@ -97,8 +97,10 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
                 (0, Vec::new(), tcx.mk_nil())
             }
             op => {
-                span_err!(tcx.sess, it.span, E0092,
-                    "unrecognized atomic operation function: `{}`", op);
+                struct_span_err!(tcx.sess, it.span, E0092,
+                      "unrecognized atomic operation function: `{}`", op)
+                  .span_label(it.span, &format!("unrecognized atomic operation"))
+                  .emit();
                 return;
             }
         };
index 6a1baf13b273d4f2bda0c4f4c3d4cf1b688ca38c..99f1b13d4e4ab422a6c218dd0c202da6812b037e 100644 (file)
@@ -580,7 +580,7 @@ fn assemble_extension_candidates_for_traits_in_scope(&mut self,
                                                          -> Result<(), MethodError<'tcx>>
     {
         let mut duplicates = HashSet::new();
-        let opt_applicable_traits = self.ccx.trait_map.get(&expr_id);
+        let opt_applicable_traits = self.tcx.trait_map.get(&expr_id);
         if let Some(applicable_traits) = opt_applicable_traits {
             for trait_candidate in applicable_traits {
                 let trait_did = trait_candidate.def_id;
@@ -786,16 +786,19 @@ fn assemble_projection_candidates(&mut self,
             debug!("assemble_projection_candidates: step={:?}",
                    step);
 
-            let projection_trait_ref = match step.self_ty.sty {
-                ty::TyProjection(ref data) => &data.trait_ref,
+            let (def_id, substs) = match step.self_ty.sty {
+                ty::TyProjection(ref data) => {
+                    (data.trait_ref.def_id, data.trait_ref.substs)
+                }
+                ty::TyAnon(def_id, substs) => (def_id, substs),
                 _ => continue,
             };
 
-            debug!("assemble_projection_candidates: projection_trait_ref={:?}",
-                   projection_trait_ref);
+            debug!("assemble_projection_candidates: def_id={:?} substs={:?}",
+                   def_id, substs);
 
-            let trait_predicates = self.tcx.lookup_predicates(projection_trait_ref.def_id);
-            let bounds = trait_predicates.instantiate(self.tcx, projection_trait_ref.substs);
+            let trait_predicates = self.tcx.lookup_predicates(def_id);
+            let bounds = trait_predicates.instantiate(self.tcx, substs);
             let predicates = bounds.predicates.into_vec();
             debug!("assemble_projection_candidates: predicates={:?}",
                    predicates);
@@ -806,9 +809,8 @@ fn assemble_projection_candidates(&mut self,
             {
                 let bound = self.erase_late_bound_regions(&poly_bound);
 
-                debug!("assemble_projection_candidates: projection_trait_ref={:?} bound={:?}",
-                       projection_trait_ref,
-                       bound);
+                debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}",
+                       def_id, substs, bound);
 
                 if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
                     let xform_self_ty = self.xform_self_ty(&item,
index 4bb36aa639c541b1e0ae46517a27b654b46d4f40..0c8e6d990a64443f08cb6e5c24c64cda5d6dd153 100644 (file)
 use hir::pat_util;
 use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::{GenericPredicates, TypeScheme};
 use rustc::ty::{ParamTy, ParameterEnvironment};
 use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility};
 use rustc::ty::{MethodCall, MethodCallee};
 use rustc::ty::adjustment;
-use rustc::ty::fold::TypeFoldable;
+use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
 use rustc::ty::util::{Representability, IntTypeExt};
 use require_c_abi_if_variadic;
 use rscope::{ElisionFailureInfo, RegionScope};
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{self, Spanned};
+use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax::parse::token::{self, InternedString, keywords};
 use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -172,6 +173,16 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'gcx, 'tcx>>>>,
 
     deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
+
+    // Anonymized types found in explicit return types and their
+    // associated fresh inference variable. Writeback resolves these
+    // variables to get the concrete type, which can be used to
+    // deanonymize TyAnon, after typeck is done with all functions.
+    anon_types: RefCell<DefIdMap<Ty<'tcx>>>,
+
+    // Obligations which will have to be checked at the end of
+    // type-checking, after all functions have been inferred.
+    deferred_obligations: RefCell<Vec<traits::DeferredObligation<'tcx>>>,
 }
 
 impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@@ -384,13 +395,14 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 }
 
 impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> {
-    pub fn inherited(&'a self, param_env: Option<ty::ParameterEnvironment<'gcx>>)
+    pub fn inherited(&'a self, id: ast::NodeId)
                      -> InheritedBuilder<'a, 'gcx, 'tcx> {
+        let param_env = ParameterEnvironment::for_item(self.tcx, id);
         InheritedBuilder {
             ccx: self,
             infcx: self.tcx.infer_ctxt(Some(ty::Tables::empty()),
-                                       param_env,
-                                       ProjectionMode::AnyFinal)
+                                       Some(param_env),
+                                       Reveal::NotSpecializable)
         }
     }
 }
@@ -408,6 +420,8 @@ fn enter<F, R>(&'tcx mut self, f: F) -> R
                 locals: RefCell::new(NodeMap()),
                 deferred_call_resolutions: RefCell::new(DefIdMap()),
                 deferred_cast_checks: RefCell::new(Vec::new()),
+                anon_types: RefCell::new(DefIdMap()),
+                deferred_obligations: RefCell::new(Vec::new()),
             })
         })
     }
@@ -442,7 +456,7 @@ fn visit_item(&mut self, i: &'tcx hir::Item) {
     fn visit_ty(&mut self, t: &'tcx hir::Ty) {
         match t.node {
             hir::TyFixedLengthVec(_, ref expr) => {
-                check_const_in_type(self.ccx, &expr, self.ccx.tcx.types.usize);
+                check_const_with_type(self.ccx, &expr, self.ccx.tcx.types.usize, expr.id);
             }
             _ => {}
         }
@@ -475,6 +489,31 @@ pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult {
     ccx.tcx.sess.track_errors(|| {
         let mut visit = CheckItemBodiesVisitor { ccx: ccx };
         ccx.tcx.visit_all_items_in_krate(DepNode::TypeckItemBody, &mut visit);
+
+        // Process deferred obligations, now that all functions
+        // bodies have been fully inferred.
+        for (&item_id, obligations) in ccx.deferred_obligations.borrow().iter() {
+            // Use the same DepNode as for the body of the original function/item.
+            let def_id = ccx.tcx.map.local_def_id(item_id);
+            let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeckItemBody(def_id));
+
+            let param_env = ParameterEnvironment::for_item(ccx.tcx, item_id);
+            ccx.tcx.infer_ctxt(None, Some(param_env),
+                               Reveal::NotSpecializable).enter(|infcx| {
+                let mut fulfillment_cx = traits::FulfillmentContext::new();
+                for obligation in obligations.iter().map(|o| o.to_obligation()) {
+                    fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+                }
+
+                if let Err(errors) = fulfillment_cx.select_all_or_error(&infcx) {
+                    infcx.report_fulfillment_errors(&errors);
+                }
+
+                if let Err(errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
+                    infcx.report_fulfillment_errors_as_warnings(&errors, item_id);
+                }
+            });
+        }
     })
 }
 
@@ -501,17 +540,14 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            decl: &'tcx hir::FnDecl,
                            body: &'tcx hir::Block,
-                           fn_id: ast::NodeId,
-                           fn_span: Span,
-                           raw_fty: Ty<'tcx>,
-                           param_env: ty::ParameterEnvironment<'tcx>)
-{
+                           fn_id: ast::NodeId) {
+    let raw_fty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(fn_id)).ty;
     let fn_ty = match raw_fty.sty {
         ty::TyFnDef(_, _, f) => f,
         _ => span_bug!(body.span, "check_bare_fn: function type expected")
     };
 
-    ccx.inherited(Some(param_env)).enter(|inh| {
+    ccx.inherited(fn_id).enter(|inh| {
         // Compute the fty from point of view of inside fn.
         let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body.id);
         let fn_sig =
@@ -529,8 +565,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         fcx.check_casts();
         fcx.select_all_obligations_or_error(); // Casts can introduce new obligations.
 
-        fcx.regionck_fn(fn_id, fn_span, decl, body);
-        fcx.resolve_type_vars_in_fn(decl, body);
+        fcx.regionck_fn(fn_id, decl, body);
+        fcx.resolve_type_vars_in_fn(decl, body, fn_id);
     });
 }
 
@@ -631,32 +667,29 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                             body: &'gcx hir::Block)
                             -> FnCtxt<'a, 'gcx, 'tcx>
 {
-    let arg_tys = &fn_sig.inputs;
-    let ret_ty = fn_sig.output;
+    let mut fn_sig = fn_sig.clone();
 
-    debug!("check_fn(arg_tys={:?}, ret_ty={:?}, fn_id={})",
-           arg_tys,
-           ret_ty,
-           fn_id);
+    debug!("check_fn(sig={:?}, fn_id={})", fn_sig, fn_id);
 
     // Create the function context.  This is either derived from scratch or,
     // in the case of function expressions, based on the outer context.
-    let fcx = FnCtxt::new(inherited, ret_ty, body.id);
+    let mut fcx = FnCtxt::new(inherited, fn_sig.output, body.id);
     *fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);
 
-    if let ty::FnConverging(ret_ty) = ret_ty {
-        fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
-    }
-
-    debug!("fn-sig-map: fn_id={} fn_sig={:?}", fn_id, fn_sig);
-
-    inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig.clone());
+    fn_sig.output = match fcx.ret_ty {
+        ty::FnConverging(orig_ret_ty) => {
+            fcx.require_type_is_sized(orig_ret_ty, decl.output.span(), traits::ReturnType);
+            ty::FnConverging(fcx.instantiate_anon_types(&orig_ret_ty))
+        }
+        ty::FnDiverging => ty::FnDiverging
+    };
+    fcx.ret_ty = fn_sig.output;
 
     {
         let mut visit = GatherLocalsVisitor { fcx: &fcx, };
 
         // Add formal parameters.
-        for (arg_ty, input) in arg_tys.iter().zip(&decl.inputs) {
+        for (arg_ty, input) in fn_sig.inputs.iter().zip(&decl.inputs) {
             // The type of the argument must be well-formed.
             //
             // NB -- this is now checked in wfcheck, but that
@@ -672,21 +705,20 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
             });
 
             // Check the pattern.
-            fcx.check_pat(&input.pat, *arg_ty);
+            fcx.check_pat(&input.pat, arg_ty);
+            fcx.write_ty(input.id, arg_ty);
         }
 
         visit.visit_block(body);
     }
 
-    fcx.check_block_with_expected(body, match ret_ty {
+    inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
+
+    fcx.check_block_with_expected(body, match fcx.ret_ty {
         ty::FnConverging(result_type) => ExpectHasType(result_type),
         ty::FnDiverging => NoExpectation
     });
 
-    for (input, arg) in decl.inputs.iter().zip(arg_tys) {
-        fcx.write_ty(input.id, arg);
-    }
-
     fcx
 }
 
@@ -708,7 +740,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
       hir::ItemStatic(_, _, ref e) |
-      hir::ItemConst(_, ref e) => check_const(ccx, it.span, &e, it.id),
+      hir::ItemConst(_, ref e) => check_const(ccx, &e, it.id),
       hir::ItemEnum(ref enum_definition, _) => {
         check_enum_variants(ccx,
                             it.span,
@@ -787,23 +819,18 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
     let _indenter = indenter();
     match it.node {
       hir::ItemFn(ref decl, _, _, _, _, ref body) => {
-        let fn_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
-        let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
-        check_bare_fn(ccx, &decl, &body, it.id, it.span, fn_pty.ty, param_env);
+        check_bare_fn(ccx, &decl, &body, it.id);
       }
       hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", it.name, it.id);
 
-        let impl_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
-
         for impl_item in impl_items {
             match impl_item.node {
                 hir::ImplItemKind::Const(_, ref expr) => {
-                    check_const(ccx, impl_item.span, &expr, impl_item.id)
+                    check_const(ccx, &expr, impl_item.id)
                 }
                 hir::ImplItemKind::Method(ref sig, ref body) => {
-                    check_method_body(ccx, &impl_pty.generics, sig, body,
-                                      impl_item.id, impl_item.span);
+                    check_bare_fn(ccx, &sig.decl, body, impl_item.id);
                 }
                 hir::ImplItemKind::Type(_) => {
                     // Nothing to do here.
@@ -812,17 +839,15 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
         }
       }
       hir::ItemTrait(_, _, _, ref trait_items) => {
-        let trait_def = ccx.tcx.lookup_trait_def(ccx.tcx.map.local_def_id(it.id));
         for trait_item in trait_items {
             match trait_item.node {
                 hir::ConstTraitItem(_, Some(ref expr)) => {
-                    check_const(ccx, trait_item.span, &expr, trait_item.id)
+                    check_const(ccx, &expr, trait_item.id)
                 }
                 hir::MethodTraitItem(ref sig, Some(ref body)) => {
                     check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
 
-                    check_method_body(ccx, &trait_def.generics, sig, body,
-                                      trait_item.id, trait_item.span);
+                    check_bare_fn(ccx, &sig.decl, body, trait_item.id);
                 }
                 hir::MethodTraitItem(ref sig, None) => {
                     check_trait_fn_not_const(ccx, trait_item.span, sig.constness);
@@ -899,29 +924,6 @@ fn check_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-/// Type checks a method body.
-///
-/// # Parameters
-///
-/// * `item_generics`: generics defined on the impl/trait that contains
-///   the method
-/// * `self_bound`: bound for the `Self` type parameter, if any
-/// * `method`: the method definition
-fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                               item_generics: &ty::Generics<'tcx>,
-                               sig: &'tcx hir::MethodSig,
-                               body: &'tcx hir::Block,
-                               id: ast::NodeId, span: Span) {
-    debug!("check_method_body(item_generics={:?}, id={})",
-            item_generics, id);
-    let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
-
-    let fty = ccx.tcx.node_id_to_type(id);
-    debug!("check_method_body: fty={:?}", fty);
-
-    check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
-}
-
 fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              impl_item: &hir::ImplItem,
                                              parent_impl: DefId)
@@ -1160,30 +1162,39 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-/// Checks a constant appearing in a type. At the moment this is just the
-/// length expression in a fixed-length vector, but someday it might be
-/// extended to type-level numeric literals.
-fn check_const_in_type<'a,'tcx>(ccx: &'a CrateCtxt<'a,'tcx>,
-                                expr: &'tcx hir::Expr,
-                                expected_type: Ty<'tcx>) {
-    ccx.inherited(None).enter(|inh| {
+/// Checks a constant with a given type.
+fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
+                                   expr: &'tcx hir::Expr,
+                                   expected_type: Ty<'tcx>,
+                                   id: ast::NodeId) {
+    ccx.inherited(id).enter(|inh| {
         let fcx = FnCtxt::new(&inh, ty::FnConverging(expected_type), expr.id);
-        fcx.check_const_with_ty(expr.span, expr, expected_type);
+        fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized);
+
+        // Gather locals in statics (because of block expressions).
+        // This is technically unnecessary because locals in static items are forbidden,
+        // but prevents type checking from blowing up before const checking can properly
+        // emit an error.
+        GatherLocalsVisitor { fcx: &fcx }.visit_expr(expr);
+
+        fcx.check_expr_coercable_to_type(expr, expected_type);
+
+        fcx.select_all_obligations_and_apply_defaults();
+        fcx.closure_analyze_const(expr);
+        fcx.select_obligations_where_possible();
+        fcx.check_casts();
+        fcx.select_all_obligations_or_error();
+
+        fcx.regionck_expr(expr);
+        fcx.resolve_type_vars_in_expr(expr, id);
     });
 }
 
-fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
-                        sp: Span,
-                        e: &'tcx hir::Expr,
-                        id: ast::NodeId) {
-    let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
-    ccx.inherited(Some(param_env)).enter(|inh| {
-        let rty = ccx.tcx.node_id_to_type(id);
-        let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), e.id);
-        let declty = fcx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
-        fcx.require_type_is_sized(declty, e.span, traits::ConstSized);
-        fcx.check_const_with_ty(sp, e, declty);
-    });
+fn check_const<'a, 'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                         expr: &'tcx hir::Expr,
+                         id: ast::NodeId) {
+    let decl_ty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
+    check_const_with_type(ccx, expr, decl_ty, id);
 }
 
 /// Checks whether a type can be represented in memory. In particular, it
@@ -1252,37 +1263,40 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             "unsupported representation for zero-variant enum");
     }
 
-    ccx.inherited(None).enter(|inh| {
-        let rty = ccx.tcx.node_id_to_type(id);
-        let fcx = FnCtxt::new(&inh, ty::FnConverging(rty), id);
-
-        let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
-        for v in vs {
-            if let Some(ref e) = v.node.disr_expr {
-                fcx.check_const_with_ty(e.span, e, repr_type_ty);
-            }
+    let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
+    for v in vs {
+        if let Some(ref e) = v.node.disr_expr {
+            check_const_with_type(ccx, e, repr_type_ty, e.id);
         }
+    }
 
-        let def_id = ccx.tcx.map.local_def_id(id);
-
-        let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
-        let mut disr_vals: Vec<ty::Disr> = Vec::new();
-        for (v, variant) in vs.iter().zip(variants.iter()) {
-            let current_disr_val = variant.disr_val;
-
-            // Check for duplicate discriminant values
-            if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) {
-                let mut err = struct_span_err!(ccx.tcx.sess, v.span, E0081,
-                    "discriminant value `{}` already exists", disr_vals[i]);
-                let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
-                err.span_label(ccx.tcx.map.span(variant_i_node_id),
-                               &format!("first use of `{}`", disr_vals[i]));
-                err.span_label(v.span , &format!("enum already has `{}`", disr_vals[i]));
-                err.emit();
-            }
-            disr_vals.push(current_disr_val);
+    let def_id = ccx.tcx.map.local_def_id(id);
+
+    let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
+    let mut disr_vals: Vec<ty::Disr> = Vec::new();
+    for (v, variant) in vs.iter().zip(variants.iter()) {
+        let current_disr_val = variant.disr_val;
+
+        // Check for duplicate discriminant values
+        if let Some(i) = disr_vals.iter().position(|&x| x == current_disr_val) {
+            let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
+            let variant_i = ccx.tcx.map.expect_variant(variant_i_node_id);
+            let i_span = match variant_i.node.disr_expr {
+                Some(ref expr) => expr.span,
+                None => ccx.tcx.map.span(variant_i_node_id)
+            };
+            let span = match v.node.disr_expr {
+                Some(ref expr) => expr.span,
+                None => v.span
+            };
+            struct_span_err!(ccx.tcx.sess, span, E0081,
+                             "discriminant value `{}` already exists", disr_vals[i])
+                .span_label(i_span, &format!("first use of `{}`", disr_vals[i]))
+                .span_label(span , &format!("enum already has `{}`", disr_vals[i]))
+                .emit();
         }
-    });
+        disr_vals.push(current_disr_val);
+    }
 
     check_representable(ccx.tcx, sp, id, "enum");
 }
@@ -1615,6 +1629,41 @@ fn instantiate_bounds(&self,
         }
     }
 
+    /// Replace all anonymized types with fresh inference variables
+    /// and record them for writeback.
+    fn instantiate_anon_types<T: TypeFoldable<'tcx>>(&self, value: &T) -> T {
+        value.fold_with(&mut BottomUpFolder { tcx: self.tcx, fldop: |ty| {
+            if let ty::TyAnon(def_id, substs) = ty.sty {
+                // Use the same type variable if the exact same TyAnon appears more
+                // than once in the return type (e.g. if it's pased to a type alias).
+                if let Some(ty_var) = self.anon_types.borrow().get(&def_id) {
+                    return ty_var;
+                }
+                let ty_var = self.next_ty_var();
+                self.anon_types.borrow_mut().insert(def_id, ty_var);
+
+                let item_predicates = self.tcx.lookup_predicates(def_id);
+                let bounds = item_predicates.instantiate(self.tcx, substs);
+
+                let span = self.tcx.map.def_id_span(def_id, codemap::DUMMY_SP);
+                for predicate in bounds.predicates {
+                    // Change the predicate to refer to the type variable,
+                    // which will be the concrete type, instead of the TyAnon.
+                    // This also instantiates nested `impl Trait`.
+                    let predicate = self.instantiate_anon_types(&predicate);
+
+                    // Require that the predicate holds for the concrete type.
+                    let cause = traits::ObligationCause::new(span, self.body_id,
+                                                             traits::ReturnType);
+                    self.register_predicate(traits::Obligation::new(cause, predicate));
+                }
+
+                ty_var
+            } else {
+                ty
+            }
+        }})
+    }
 
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
         where T : TypeFoldable<'tcx>
@@ -1652,7 +1701,12 @@ pub fn instantiate_type_path(&self,
                                  node_id: ast::NodeId)
                                  -> Ty<'tcx> {
         debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
-        let type_scheme = self.tcx.lookup_item_type(did);
+        let mut type_scheme = self.tcx.lookup_item_type(did);
+        if type_scheme.ty.is_fn() {
+            // Tuple variants have fn type even in type namespace, extract true variant type from it
+            let fn_ret = self.tcx.no_late_bound_regions(&type_scheme.ty.fn_ret()).unwrap().unwrap();
+            type_scheme = ty::TypeScheme { ty: fn_ret, generics: type_scheme.generics }
+        }
         let type_predicates = self.tcx.lookup_predicates(did);
         let substs = AstConv::ast_path_substs_for_ty(self, self,
                                                      path.span,
@@ -2182,6 +2236,12 @@ fn select_all_obligations_or_error(&self) {
         self.select_all_obligations_and_apply_defaults();
 
         let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+
+        // Steal the deferred obligations before the fulfillment
+        // context can turn all of them into errors.
+        let obligations = fulfillment_cx.take_deferred_obligations();
+        self.deferred_obligations.borrow_mut().extend(obligations);
+
         match fulfillment_cx.select_all_or_error(self) {
             Ok(()) => { }
             Err(errors) => { self.report_fulfillment_errors(&errors); }
@@ -3190,19 +3250,24 @@ pub fn check_struct_path(&self,
             }
             _ => None
         };
-        if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
-            // Reject tuple structs for now, braced and unit structs are allowed.
+
+        if let Some(variant) = variant {
+            if variant.kind == ty::VariantKind::Tuple &&
+                    !self.tcx.sess.features.borrow().relaxed_adts {
+                emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
+                                 "relaxed_adts", span, GateIssue::Language,
+                                 "tuple structs and variants in struct patterns are unstable");
+            }
+            let ty = self.instantiate_type_path(def.def_id(), path, node_id);
+            Some((variant, ty))
+        } else {
             struct_span_err!(self.tcx.sess, path.span, E0071,
                              "`{}` does not name a struct or a struct variant",
                              pprust::path_to_string(path))
                 .span_label(path.span, &format!("not a struct"))
                 .emit();
-
-            return None;
+            None
         }
-
-        let ty = self.instantiate_type_path(def.def_id(), path, node_id);
-        Some((variant.unwrap(), ty))
     }
 
     fn check_expr_struct(&self,
@@ -3990,29 +4055,6 @@ fn check_block_with_expected(&self,
         *self.ps.borrow_mut() = prev;
     }
 
-
-    fn check_const_with_ty(&self,
-                           _: Span,
-                           e: &'gcx hir::Expr,
-                           declty: Ty<'tcx>) {
-        // Gather locals in statics (because of block expressions).
-        // This is technically unnecessary because locals in static items are forbidden,
-        // but prevents type checking from blowing up before const checking can properly
-        // emit an error.
-        GatherLocalsVisitor { fcx: self }.visit_expr(e);
-
-        self.check_expr_coercable_to_type(e, declty);
-
-        self.select_all_obligations_and_apply_defaults();
-        self.closure_analyze_const(e);
-        self.select_obligations_where_possible();
-        self.check_casts();
-        self.select_all_obligations_or_error();
-
-        self.regionck_expr(e);
-        self.resolve_type_vars_in_expr(e);
-    }
-
     // Returns the type parameter count and the type for the given definition.
     fn type_scheme_and_predicates_for_def(&self,
                                           sp: Span,
@@ -4372,14 +4414,17 @@ fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(&self,
                 if i < type_count {
                     substs.types.push(space, t);
                 } else if i == type_count {
-                    span_err!(self.tcx.sess, typ.span, E0087,
-                        "too many type parameters provided: \
-                         expected at most {} parameter{}, \
-                         found {} parameter{}",
-                         type_count,
-                         if type_count == 1 {""} else {"s"},
-                         data.types.len(),
-                         if data.types.len() == 1 {""} else {"s"});
+                    struct_span_err!(self.tcx.sess, typ.span, E0087,
+                                     "too many type parameters provided: \
+                                      expected at most {} parameter{}, \
+                                      found {} parameter{}",
+                                     type_count,
+                                     if type_count == 1 {""} else {"s"},
+                                     data.types.len(),
+                                     if data.types.len() == 1 {""} else {"s"})
+                        .span_label(typ.span , &format!("expected {} parameter{}",
+                                    type_count,
+                                    if type_count == 1 {""} else {"s"})).emit();
                     substs.types.truncate(space, 0);
                     break;
                 }
@@ -4637,9 +4682,11 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     for (i, b) in tps_used.iter().enumerate() {
         if !*b {
-            span_err!(ccx.tcx.sess, tps[i].span, E0091,
+            struct_span_err!(ccx.tcx.sess, tps[i].span, E0091,
                 "type parameter `{}` is unused",
-                tps[i].name);
+                tps[i].name)
+                .span_label(tps[i].span, &format!("unused type parameter"))
+                .emit();
         }
     }
 }
index 5a7038a056982cc390709acb49a14c1beebd1f75..f3a6442f35d1127721bf424710b864d8e4d26847 100644 (file)
@@ -141,7 +141,6 @@ pub fn regionck_item(&self,
 
     pub fn regionck_fn(&self,
                        fn_id: ast::NodeId,
-                       fn_span: Span,
                        decl: &hir::FnDecl,
                        blk: &hir::Block) {
         debug!("regionck_fn(id={})", fn_id);
@@ -149,7 +148,7 @@ pub fn regionck_fn(&self,
 
         if self.err_count_since_creation() == 0 {
             // regionck assumes typeck succeeded
-            rcx.visit_fn_body(fn_id, decl, blk, fn_span);
+            rcx.visit_fn_body(fn_id, decl, blk, self.tcx.map.span(fn_id));
         }
 
         rcx.free_region_map.relate_free_regions_from_predicates(
index 34a91b22981e15b298c5e8752f7710ecfe011c52..e2080906ca24294c9f029cdbcfbe7a6bf1e08c8a 100644 (file)
@@ -209,9 +209,8 @@ fn for_item<'tcx>(&self, item: &hir::Item)
 
     fn for_id<'tcx>(&self, id: ast::NodeId, span: Span)
                     -> CheckWfFcxBuilder<'ccx, 'gcx, 'tcx> {
-        let param_env = ty::ParameterEnvironment::for_item(self.ccx.tcx, id);
         CheckWfFcxBuilder {
-            inherited: self.ccx.inherited(Some(param_env)),
+            inherited: self.ccx.inherited(id),
             code: self.code.clone(),
             id: id,
             span: span
index 42893e40024e891aa14eb5ec8dd7684f3a93edb8..9026920e7f48abb0936f7e02165516c39bc5e72a 100644 (file)
@@ -18,7 +18,9 @@
 use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
 use rustc::ty::adjustment;
 use rustc::ty::fold::{TypeFolder,TypeFoldable};
+use rustc::ty::subst::ParamSpace;
 use rustc::infer::{InferCtxt, FixupError};
+use rustc::util::nodemap::DefIdMap;
 use write_substs_to_tcx;
 use write_ty_to_tcx;
 
@@ -35,7 +37,7 @@
 // Entry point functions
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
-    pub fn resolve_type_vars_in_expr(&self, e: &hir::Expr) {
+    pub fn resolve_type_vars_in_expr(&self, e: &hir::Expr, item_id: ast::NodeId) {
         assert_eq!(self.writeback_errors.get(), false);
         let mut wbcx = WritebackCx::new(self);
         wbcx.visit_expr(e);
@@ -43,9 +45,13 @@ pub fn resolve_type_vars_in_expr(&self, e: &hir::Expr) {
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
+        wbcx.visit_deferred_obligations(item_id);
     }
 
-    pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
+    pub fn resolve_type_vars_in_fn(&self,
+                                   decl: &hir::FnDecl,
+                                   blk: &hir::Block,
+                                   item_id: ast::NodeId) {
         assert_eq!(self.writeback_errors.get(), false);
         let mut wbcx = WritebackCx::new(self);
         wbcx.visit_block(blk);
@@ -62,6 +68,8 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
+        wbcx.visit_anon_types();
+        wbcx.visit_deferred_obligations(item_id);
     }
 }
 
@@ -75,11 +83,48 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
 
 struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
+
+    // Mapping from free regions of the function to the
+    // early-bound versions of them, visible from the
+    // outside of the function. This is needed by, and
+    // only populated if there are any `impl Trait`.
+    free_to_bound_regions: DefIdMap<ty::Region>
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
-        WritebackCx { fcx: fcx }
+        let mut wbcx = WritebackCx {
+            fcx: fcx,
+            free_to_bound_regions: DefIdMap()
+        };
+
+        // Only build the reverse mapping if `impl Trait` is used.
+        if fcx.anon_types.borrow().is_empty() {
+            return wbcx;
+        }
+
+        let free_substs = fcx.parameter_environment.free_substs;
+        for &space in &ParamSpace::all() {
+            for (i, r) in free_substs.regions.get_slice(space).iter().enumerate() {
+                match *r {
+                    ty::ReFree(ty::FreeRegion {
+                        bound_region: ty::BoundRegion::BrNamed(def_id, name, _), ..
+                    }) => {
+                        let bound_region = ty::ReEarlyBound(ty::EarlyBoundRegion {
+                            space: space,
+                            index: i as u32,
+                            name: name,
+                        });
+                        wbcx.free_to_bound_regions.insert(def_id, bound_region);
+                    }
+                    _ => {
+                        bug!("{:?} is not a free region for an early-bound lifetime", r);
+                    }
+                }
+            }
+        }
+
+        wbcx
     }
 
     fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
@@ -255,6 +300,58 @@ fn visit_closures(&self) {
         }
     }
 
+    fn visit_anon_types(&self) {
+        if self.fcx.writeback_errors.get() {
+            return
+        }
+
+        let gcx = self.tcx().global_tcx();
+        for (&def_id, &concrete_ty) in self.fcx.anon_types.borrow().iter() {
+            let reason = ResolvingAnonTy(def_id);
+            let inside_ty = self.resolve(&concrete_ty, reason);
+
+            // Convert the type from the function into a type valid outside
+            // the function, by replacing free regions with early-bound ones.
+            let outside_ty = gcx.fold_regions(&inside_ty, &mut false, |r, _| {
+                match r {
+                    // 'static is valid everywhere.
+                    ty::ReStatic => ty::ReStatic,
+
+                    // Free regions that come from early-bound regions are valid.
+                    ty::ReFree(ty::FreeRegion {
+                        bound_region: ty::BoundRegion::BrNamed(def_id, _, _), ..
+                    }) if self.free_to_bound_regions.contains_key(&def_id) => {
+                        self.free_to_bound_regions[&def_id]
+                    }
+
+                    ty::ReFree(_) |
+                    ty::ReEarlyBound(_) |
+                    ty::ReLateBound(..) |
+                    ty::ReScope(_) |
+                    ty::ReSkolemized(..) => {
+                        let span = reason.span(self.tcx());
+                        span_err!(self.tcx().sess, span, E0564,
+                                  "only named lifetimes are allowed in `impl Trait`, \
+                                   but `{}` was found in the type `{}`", r, inside_ty);
+                        ty::ReStatic
+                    }
+
+                    ty::ReVar(_) |
+                    ty::ReEmpty |
+                    ty::ReErased => {
+                        let span = reason.span(self.tcx());
+                        span_bug!(span, "invalid region in impl Trait: {:?}", r);
+                    }
+                }
+            });
+
+            gcx.tcache.borrow_mut().insert(def_id, ty::TypeScheme {
+                ty: outside_ty,
+                generics: ty::Generics::empty()
+            });
+        }
+    }
+
     fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
         // Resolve any borrowings for the node with id `id`
         self.visit_adjustments(reason, id);
@@ -353,6 +450,19 @@ fn visit_fru_field_types(&self) {
         }
     }
 
+    fn visit_deferred_obligations(&self, item_id: ast::NodeId) {
+        let deferred_obligations = self.fcx.deferred_obligations.borrow();
+        let obligations: Vec<_> = deferred_obligations.iter().map(|obligation| {
+            let reason = ResolvingDeferredObligation(obligation.cause.span);
+            self.resolve(obligation, reason)
+        }).collect();
+
+        if !obligations.is_empty() {
+            assert!(self.fcx.ccx.deferred_obligations.borrow_mut()
+                                .insert(item_id, obligations).is_none());
+        }
+    }
+
     fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
         where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
     {
@@ -369,7 +479,7 @@ fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
 ///////////////////////////////////////////////////////////////////////////
 // Resolution reason.
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 enum ResolveReason {
     ResolvingExpr(Span),
     ResolvingLocal(Span),
@@ -377,7 +487,9 @@ enum ResolveReason {
     ResolvingUpvar(ty::UpvarId),
     ResolvingClosure(DefId),
     ResolvingFnSig(ast::NodeId),
-    ResolvingFieldTypes(ast::NodeId)
+    ResolvingFieldTypes(ast::NodeId),
+    ResolvingAnonTy(DefId),
+    ResolvingDeferredObligation(Span),
 }
 
 impl<'a, 'gcx, 'tcx> ResolveReason {
@@ -395,13 +507,11 @@ fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
             ResolvingFieldTypes(id) => {
                 tcx.map.span(id)
             }
-            ResolvingClosure(did) => {
-                if let Some(node_id) = tcx.map.as_local_node_id(did) {
-                    tcx.expr_span(node_id)
-                } else {
-                    DUMMY_SP
-                }
+            ResolvingClosure(did) |
+            ResolvingAnonTy(did) => {
+                tcx.map.def_id_span(did, DUMMY_SP)
             }
+            ResolvingDeferredObligation(span) => span
         }
     }
 }
@@ -474,14 +584,23 @@ fn report_error(&self, e: FixupError) {
                               "cannot determine a type for this closure")
                 }
 
-                ResolvingFnSig(id) | ResolvingFieldTypes(id) => {
+                ResolvingFnSig(_) |
+                ResolvingFieldTypes(_) |
+                ResolvingDeferredObligation(_) => {
                     // any failures here should also fail when
                     // resolving the patterns, closure types, or
                     // something else.
                     let span = self.reason.span(self.tcx);
                     self.tcx.sess.delay_span_bug(
                         span,
-                        &format!("cannot resolve some aspect of data for {:?}", id));
+                        &format!("cannot resolve some aspect of data for {:?}: {}",
+                                 self.reason, e));
+                }
+
+                ResolvingAnonTy(_) => {
+                    let span = self.reason.span(self.tcx);
+                    span_err!(self.tcx.sess, span, E0563,
+                              "cannot determine a type for this `impl Trait`: {}", e)
                 }
             }
         }
index cdf2ca14d4c78366a4a8284d9ac63eace14c2b01..13deac57330e3b28e5c44914b07b439d29d905cc 100644 (file)
@@ -19,7 +19,7 @@
 use middle::lang_items::UnsizeTraitLangItem;
 use rustc::ty::subst::{self, Subst};
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId};
 use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
 use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
@@ -27,7 +27,7 @@
 use rustc::ty::{TyRef, TyStruct, TyTrait, TyTuple};
 use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
-use rustc::ty::TyProjection;
+use rustc::ty::{TyProjection, TyAnon};
 use rustc::ty::util::CopyImplementationError;
 use middle::free_region::FreeRegionMap;
 use CrateCtxt;
@@ -89,7 +89,7 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
                 None
             }
 
-            TyInfer(..) | TyClosure(..) => {
+            TyInfer(..) | TyClosure(..) | TyAnon(..) => {
                 // `ty` comes from a user declaration so we should only expect types
                 // that the user can type
                 span_bug!(
@@ -321,13 +321,18 @@ fn check_implementations_of_copy(&self) {
 
                 }
                 Err(CopyImplementationError::InfrigingVariant(name)) => {
-                       struct_span_err!(tcx.sess, span, E0205,
-                                 "the trait `Copy` may not be \
-                                          implemented for this type")
-                           .span_label(span, &format!("variant \
-                                          `{}` does not implement `Copy`",
-                                         name))
-                           .emit()
+                    let item = tcx.map.expect_item(impl_node_id);
+                    let span = if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
+                        tr.path.span
+                    } else {
+                        span
+                    };
+
+                    struct_span_err!(tcx.sess, span, E0205,
+                                     "the trait `Copy` may not be implemented for this type")
+                        .span_label(span, &format!("variant `{}` does not implement `Copy`",
+                                                   name))
+                        .emit()
                 }
                 Err(CopyImplementationError::NotAnAdt) => {
                     let item = tcx.map.expect_item(impl_node_id);
@@ -394,7 +399,7 @@ fn check_implementations_of_coerce_unsized(&self) {
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
                    source, target);
 
-            tcx.infer_ctxt(None, Some(param_env), ProjectionMode::Topmost).enter(|infcx| {
+            tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| {
                 let origin = TypeOrigin::Misc(span);
                 let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>,
                                    mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| {
@@ -531,7 +536,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
 
 pub fn check_coherence(ccx: &CrateCtxt) {
     let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
-    ccx.tcx.infer_ctxt(None, None, ProjectionMode::Topmost).enter(|infcx| {
+    ccx.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| {
         CoherenceChecker {
             crate_context: ccx,
             inference_context: infcx,
index 54bd141304d7816e21966f600a6c7c3878e1096f..46a9ef8d5babb0edcc4fe4de4e44894e41910425 100644 (file)
@@ -13,7 +13,7 @@
 //! constructor provide a method with the same name.
 
 use hir::def_id::DefId;
-use rustc::traits::{self, ProjectionMode};
+use rustc::traits::{self, Reveal};
 use rustc::ty::{self, TyCtxt};
 use syntax::ast;
 use rustc::dep_graph::DepNode;
@@ -84,7 +84,7 @@ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
 
         for (i, &impl1_def_id) in impls.iter().enumerate() {
             for &impl2_def_id in &impls[(i+1)..] {
-                self.tcx.infer_ctxt(None, None, ProjectionMode::Topmost).enter(|infcx| {
+                self.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| {
                     if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
                         self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
                     }
index 9b1a6c78335f189470f69c1d31b59706e37c21b3..75bfad053a32855c9d6f079b67bcf3465429c019 100644 (file)
@@ -564,13 +564,17 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let ty_generic_predicates =
         ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
 
-    let (fty, explicit_self_category) =
+    let (fty, explicit_self_category) = {
+        let anon_scope = match container {
+            ImplContainer(_) => Some(AnonTypeScope::new(&ty_generics)),
+            TraitContainer(_) => None
+        };
         AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
-                              sig,
-                              untransformed_rcvr_ty);
+                              sig, untransformed_rcvr_ty, anon_scope)
+    };
 
     let def_id = ccx.tcx.map.local_def_id(id);
-    let substs = mk_item_substs(ccx, &ty_generics);
+    let substs = mk_item_substs(ccx.tcx, &ty_generics);
 
     let ty_method = ty::Method::new(name,
                                     ty_generics,
@@ -961,7 +965,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 .map(|field| field.unsubst_ty())
                 .collect();
             let def_id = tcx.map.local_def_id(ctor_id);
-            let substs = mk_item_substs(ccx, &scheme.generics);
+            let substs = mk_item_substs(tcx, &scheme.generics);
             tcx.mk_fn_def(def_id, substs, tcx.mk_bare_fn(ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: abi::Abi::Rust,
@@ -1190,10 +1194,11 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
         // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
         let self_param_ty = tcx.mk_self_type();
         let superbounds1 = compute_bounds(&ccx.icx(scope),
-                                    self_param_ty,
-                                    bounds,
-                                    SizedByDefault::No,
-                                    item.span);
+                                          self_param_ty,
+                                          bounds,
+                                          SizedByDefault::No,
+                                          None,
+                                          item.span);
 
         let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
 
@@ -1403,6 +1408,7 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                         assoc_ty,
                                         bounds,
                                         SizedByDefault::Yes,
+                                        None,
                                         trait_item.span);
 
             bounds.predicates(ccx.tcx, assoc_ty).into_iter()
@@ -1442,6 +1448,7 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         // NB. Since the `memoized` function enters a new task, and we
         // are giving this task access to the item `item`, we must
         // register a read.
+        assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id));
         ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
         compute_type_scheme_of_item(ccx, item)
     })
@@ -1459,9 +1466,10 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         }
         hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
-            let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
+            let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
+                                              Some(AnonTypeScope::new(&ty_generics)));
             let def_id = ccx.tcx.map.local_def_id(it.id);
-            let substs = mk_item_substs(ccx, &ty_generics);
+            let substs = mk_item_substs(tcx, &ty_generics);
             let ty = tcx.mk_fn_def(def_id, substs, tofd);
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
@@ -1473,14 +1481,14 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         hir::ItemEnum(ref ei, ref generics) => {
             let def = convert_enum_def(ccx, it, ei);
             let ty_generics = ty_generics_for_type(ccx, generics);
-            let substs = mk_item_substs(ccx, &ty_generics);
+            let substs = mk_item_substs(tcx, &ty_generics);
             let t = tcx.mk_enum(def, substs);
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
         hir::ItemStruct(ref si, ref generics) => {
             let def = convert_struct_def(ccx, it, si);
             let ty_generics = ty_generics_for_type(ccx, generics);
-            let substs = mk_item_substs(ccx, &ty_generics);
+            let substs = mk_item_substs(tcx, &ty_generics);
             let t = tcx.mk_struct(def, substs);
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
@@ -1569,6 +1577,7 @@ fn type_scheme_of_foreign_item<'a, 'tcx>(
         // NB. Since the `memoized` function enters a new task, and we
         // are giving this task access to the item `item`, we must
         // register a read.
+        assert!(!ccx.tcx.map.is_inlined_def_id(item_def_id));
         ccx.tcx.dep_graph.read(DepNode::Hir(item_def_id));
         compute_type_scheme_of_foreign_item(ccx, item, abi)
     })
@@ -1692,10 +1701,10 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                           bounds: &mut ty::BuiltinBounds,
-                           ast_bounds: &[hir::TyParamBound],
-                           span: Span)
+fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                       bounds: &mut ty::BuiltinBounds,
+                                       ast_bounds: &[hir::TyParamBound],
+                                       span: Span)
 {
     let tcx = astconv.tcx();
 
@@ -1773,6 +1782,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                     param_ty,
                                     &param.bounds,
                                     SizedByDefault::Yes,
+                                    None,
                                     param.span);
         let predicates = bounds.predicates(ccx.tcx, param_ty);
         result.predicates.extend(space, predicates.into_iter());
@@ -1901,9 +1911,12 @@ fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     for leaf_ty in ty.walk() {
         if let ty::TyParam(p) = leaf_ty.sty {
             if p.space == space && p.idx >= index {
-                span_err!(ccx.tcx.sess, path.span, E0128,
-                          "type parameters with a default cannot use \
-                           forward declared identifiers");
+                struct_span_err!(ccx.tcx.sess, path.span, E0128,
+                                 "type parameters with a default cannot use \
+                                 forward declared identifiers")
+                    .span_label(path.span, &format!("defaulted type parameters \
+                                                    cannot be forward declared"))
+                    .emit();
 
                 return ccx.tcx.types.err
             }
@@ -2033,34 +2046,52 @@ fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 }
 
-enum SizedByDefault { Yes, No, }
+pub enum SizedByDefault { Yes, No, }
 
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                        param_ty: ty::Ty<'tcx>,
-                        ast_bounds: &[hir::TyParamBound],
-                        sized_by_default: SizedByDefault,
-                        span: Span)
-                        -> Bounds<'tcx>
+pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                        param_ty: ty::Ty<'tcx>,
+                                        ast_bounds: &[hir::TyParamBound],
+                                        sized_by_default: SizedByDefault,
+                                        anon_scope: Option<AnonTypeScope>,
+                                        span: Span)
+                                        -> Bounds<'tcx>
 {
-    let mut bounds =
-        conv_param_bounds(astconv,
-                          span,
-                          param_ty,
-                          ast_bounds);
+    let tcx = astconv.tcx();
+    let PartitionedBounds {
+        mut builtin_bounds,
+        trait_bounds,
+        region_bounds
+    } = partition_bounds(tcx, span, &ast_bounds);
 
     if let SizedByDefault::Yes = sized_by_default {
-        add_unsized_bound(astconv,
-                          &mut bounds.builtin_bounds,
-                          ast_bounds,
-                          span);
+        add_unsized_bound(astconv, &mut builtin_bounds, ast_bounds, span);
     }
 
-    bounds.trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
+    let mut projection_bounds = vec![];
+
+    let rscope = MaybeWithAnonTypes::new(ExplicitRscope, anon_scope);
+    let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
+        astconv.instantiate_poly_trait_ref(&rscope,
+                                           bound,
+                                           Some(param_ty),
+                                           &mut projection_bounds)
+    }).collect();
 
-    bounds
+    let region_bounds = region_bounds.into_iter().map(|r| {
+        ast_region_to_region(tcx, r)
+    }).collect();
+
+    trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
+
+    Bounds {
+        region_bounds: region_bounds,
+        builtin_bounds: builtin_bounds,
+        trait_bounds: trait_bounds,
+        projection_bounds: projection_bounds,
+    }
 }
 
 /// Converts a specific TyParamBound from the AST into a set of
@@ -2093,11 +2124,11 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                             param_ty: Ty<'tcx>,
-                             trait_ref: &hir::PolyTraitRef,
-                             projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-                             -> ty::PolyTraitRef<'tcx>
+fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
+                                         param_ty: Ty<'tcx>,
+                                         trait_ref: &hir::PolyTraitRef,
+                                         projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                                         -> ty::PolyTraitRef<'tcx>
 {
     AstConv::instantiate_poly_trait_ref(astconv,
                                         &ExplicitRscope,
@@ -2106,42 +2137,6 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                                         projections)
 }
 
-fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
-                              span: Span,
-                              param_ty: ty::Ty<'tcx>,
-                              ast_bounds: &[hir::TyParamBound])
-                              -> Bounds<'tcx>
-{
-    let tcx = astconv.tcx();
-    let PartitionedBounds {
-        builtin_bounds,
-        trait_bounds,
-        region_bounds
-    } = partition_bounds(tcx, span, &ast_bounds);
-
-    let mut projection_bounds = Vec::new();
-
-    let trait_bounds: Vec<ty::PolyTraitRef> =
-        trait_bounds.iter()
-                    .map(|bound| conv_poly_trait_ref(astconv,
-                                                     param_ty,
-                                                     *bound,
-                                                     &mut projection_bounds))
-                    .collect();
-
-    let region_bounds: Vec<ty::Region> =
-        region_bounds.into_iter()
-                     .map(|r| ast_region_to_region(tcx, r))
-                     .collect();
-
-    Bounds {
-        region_bounds: region_bounds,
-        builtin_bounds: builtin_bounds,
-        trait_bounds: trait_bounds,
-        projection_bounds: projection_bounds,
-    }
-}
-
 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     ccx: &CrateCtxt<'a, 'tcx>,
     id: DefId,
@@ -2189,7 +2184,7 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
         }
     }
 
-    let substs = mk_item_substs(ccx, &ty_generics);
+    let substs = mk_item_substs(ccx.tcx, &ty_generics);
     let t_fn = ccx.tcx.mk_fn_def(id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
         abi: abi,
         unsafety: hir::Unsafety::Unsafe,
@@ -2204,19 +2199,19 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     }
 }
 
-fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                            ty_generics: &ty::Generics<'tcx>)
-                            -> &'tcx Substs<'tcx>
+pub fn mk_item_substs<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                      ty_generics: &ty::Generics)
+                                      -> &'tcx Substs<'tcx>
 {
     let types =
         ty_generics.types.map(
-            |def| ccx.tcx.mk_param_from_def(def));
+            |def| tcx.mk_param_from_def(def));
 
     let regions =
         ty_generics.regions.map(
             |def| def.to_early_bound_region());
 
-    ccx.tcx.mk_substs(Substs::new(types, regions))
+    tcx.mk_substs(Substs::new(types, regions))
 }
 
 /// Checks that all the type parameters on an impl
index 7909584bfabdf560b4c11ffe97b08f3133a2667d..7d3bd095a3a888c930b813f17654334ae4e92ded 100644 (file)
@@ -45,7 +45,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         match t.sty {
-            ty::TyProjection(..) if !self.include_nonconstraining => {
+            ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return false;
             }
index 64b27857d2c610b50e6cc04850585b46ba4275ca..ac40708e25cdea049bc316f63456b1290df6723a 100644 (file)
@@ -43,7 +43,7 @@ enum Fruit {
 
 Matching with the wrong number of fields has no sensible interpretation:
 
-```compile_fail
+```compile_fail,E0023
 enum Fruit {
     Apple(String, String),
     Pear(u32),
@@ -66,7 +66,7 @@ enum Fruit {
 Each field of a struct can only be bound once in a pattern. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0025
 struct Foo {
     a: u8,
     b: u8,
@@ -123,7 +123,7 @@ struct Thing {
 
 Change this:
 
-```compile_fail
+```compile_fail,E0026
 struct Thing {
     x: u32,
     y: u32
@@ -159,7 +159,7 @@ struct Thing {
 
 For example:
 
-```compile_fail
+```compile_fail,E0027
 struct Dog {
     name: String,
     age: u32,
@@ -201,7 +201,9 @@ struct Dog {
 want to capture values of an orderable type between two end-points, you can use
 a guard.
 
-```compile_fail
+```compile_fail,E0029
+let string = "salutations !";
+
 // The ordering relation for strings can't be evaluated at compile time,
 // so this doesn't work:
 match string {
@@ -245,7 +247,7 @@ struct Dog {
 The compiler doesn't know what method to call because more than one method
 has the same prototype. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0034
 struct Test;
 
 trait Trait1 {
@@ -332,7 +334,7 @@ fn main() {
 You tried to give a type parameter where it wasn't needed. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0035
 struct Test;
 
 impl Test {
@@ -367,7 +369,7 @@ fn main() {
 This error occurrs when you pass too many or not enough type parameters to
 a method. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0036
 struct Test;
 
 impl Test {
@@ -417,7 +419,7 @@ fn main() {
 
 Here's an example of this error:
 
-```compile_fail
+```compile_fail,E0040
 struct Foo {
     x: i32,
 }
@@ -438,7 +440,7 @@ fn main() {
 E0044: r##"
 You can't use type parameters on foreign items. Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0044
 extern { fn some_func<T>(x: T); }
 ```
 
@@ -456,7 +458,9 @@ fn main() {
 FFI. As such, variadic parameters can only be used with functions which are
 using the C ABI. Examples of erroneous code:
 
-```compile_fail
+```compile_fail,E0045
+#![feature(unboxed_closures)]
+
 extern "rust-call" { fn foo(x: u8, ...); }
 
 // or
@@ -466,12 +470,6 @@ fn foo(x: u8, ...) {}
 
 To fix such code, put them in an extern "C" block:
 
-```ignore
-extern "C" fn foo(x: u8, ...);
-```
-
-Or:
-
 ```
 extern "C" {
     fn foo (x: u8, ...);
@@ -482,7 +480,7 @@ fn foo(x: u8, ...) {}
 E0046: r##"
 Items are missing in a trait implementation. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0046
 trait Foo {
     fn foo();
 }
@@ -518,7 +516,7 @@ fn foo() {} // ok!
 For example, the trait below has a method `foo` with a type parameter `T`,
 but the implementation of `foo` for the type `Bar` is missing this parameter:
 
-```compile_fail
+```compile_fail,E0049
 trait Foo {
     fn foo<T: Default>(x: T) -> Self;
 }
@@ -541,7 +539,7 @@ fn foo(x: bool) -> Self { Bar }
 (`&self` and `u8`), but the implementation of `foo` for the type `Bar` omits
 the `u8` parameter:
 
-```compile_fail
+```compile_fail,E0050
 trait Foo {
     fn foo(&self, x: u8) -> bool;
 }
@@ -562,7 +560,7 @@ fn foo(&self) -> bool { true }
 
 Here are a couple examples of this error:
 
-```compile_fail
+```compile_fail,E0053
 trait Foo {
     fn foo(x: u16);
     fn bar(&self);
@@ -584,7 +582,7 @@ fn bar(&mut self) { }
 It is not allowed to cast to a bool. If you are trying to cast a numeric type
 to a bool, you can compare it with zero instead:
 
-```compile_fail
+```compile_fail,E0054
 let x = 5;
 
 // Not allowed, won't compile
@@ -607,7 +605,7 @@ fn bar(&mut self) { }
 
 For a somewhat artificial example:
 
-```compile_fail,ignore
+```compile_fail,E0055
 #![recursion_limit="2"]
 
 struct Foo;
@@ -637,7 +635,7 @@ fn main() {
 
 An example using a closure:
 
-```compile_fail
+```compile_fail,E0057
 let f = |x| x * 3;
 let a = f();        // invalid, too few parameters
 let b = f(4);       // this works!
@@ -663,13 +661,17 @@ fn foo<F: Fn()>(f: F) {
 The most likely source of this error is using angle-bracket notation without
 wrapping the function argument type into a tuple, for example:
 
-```compile_fail
+```compile_fail,E0059
+#![feature(unboxed_closures)]
+
 fn foo<F: Fn<i32>>(f: F) -> F::Output { f(3) }
 ```
 
 It can be fixed by adjusting the trait bound like this:
 
-```ignore
+```
+#![feature(unboxed_closures)]
+
 fn foo<F: Fn<(i32,)>>(f: F) -> F::Output { f(3) }
 ```
 
@@ -726,9 +728,9 @@ fn f(a: u16, b: &str) {}
 enum variant, one of the fields was specified more than once. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0062
 struct Foo {
-    x: i32
+    x: i32,
 }
 
 fn main() {
@@ -743,7 +745,7 @@ fn main() {
 
 ```
 struct Foo {
-    x: i32
+    x: i32,
 }
 
 fn main() {
@@ -756,10 +758,10 @@ fn main() {
 This error indicates that during an attempt to build a struct or struct-like
 enum variant, one of the fields was not provided. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0063
 struct Foo {
     x: i32,
-    y: i32
+    y: i32,
 }
 
 fn main() {
@@ -772,7 +774,7 @@ fn main() {
 ```
 struct Foo {
     x: i32,
-    y: i32
+    y: i32,
 }
 
 fn main() {
@@ -799,7 +801,7 @@ fn main() {
 
 Let's start with some erroneous code examples:
 
-```compile_fail
+```compile_fail,E0067
 use std::collections::LinkedList;
 
 // Bad: assignment to non-lvalue expression
@@ -831,7 +833,7 @@ fn some_func(i: &mut i32) {
 The compiler found a function whose body contains a `return;` statement but
 whose return type is not `()`. An example of this is:
 
-```compile_fail
+```compile_fail,E0069
 // error
 fn foo() -> u8 {
     return;
@@ -853,7 +855,7 @@ fn foo() -> u8 {
 
 Now, we can go further. Here are some erroneous code examples:
 
-```compile_fail
+```compile_fail,E0070
 struct SomeStruct {
     x: i32,
     y: i32
@@ -897,7 +899,7 @@ fn some_func(x: &mut i32) {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0071
 enum Foo { FirstValue(i32) };
 
 let u = Foo::FirstValue { value: 0 }; // error: Foo::FirstValue
@@ -976,7 +978,7 @@ struct Foo { x: Option<Box<Foo>> }
 
 This will cause an error:
 
-```compile_fail
+```compile_fail,E0075
 #![feature(repr_simd)]
 
 #[repr(simd)]
@@ -1000,7 +1002,7 @@ struct Foo { x: Option<Box<Foo>> }
 
 This will cause an error:
 
-```compile_fail
+```compile_fail,E0076
 #![feature(repr_simd)]
 
 #[repr(simd)]
@@ -1023,7 +1025,7 @@ struct Foo { x: Option<Box<Foo>> }
 
 This will cause an error:
 
-```compile_fail
+```compile_fail,E0077
 #![feature(repr_simd)]
 
 #[repr(simd)]
@@ -1047,9 +1049,9 @@ struct Foo { x: Option<Box<Foo>> }
 
 For example, in the following code:
 
-```compile_fail
+```compile_fail,E0079
 enum Foo {
-    Q = "32"
+    Q = "32",
 }
 ```
 
@@ -1060,7 +1062,7 @@ enum Foo {
 
 ```
 enum Foo {
-    Q = 32
+    Q = 32,
 }
 ```
 
@@ -1084,12 +1086,12 @@ fn get_str(&self) -> &'static str {
 This error indicates that the same value was used for two or more variants,
 making them impossible to tell apart.
 
-```compile_fail
+```compile_fail,E0081
 // Bad.
 enum Enum {
     P = 3,
     X = 3,
-    Y = 5
+    Y = 5,
 }
 ```
 
@@ -1098,7 +1100,7 @@ enum Enum {
 enum Enum {
     P,
     X = 3,
-    Y = 5
+    Y = 5,
 }
 ```
 
@@ -1106,7 +1108,7 @@ enum Enum {
 top to bottom starting from 0, so clashes can occur with seemingly unrelated
 variants.
 
-```compile_fail
+```compile_fail,E0081
 enum Bad {
     X,
     Y = 0
@@ -1128,7 +1130,7 @@ enum Bad {
 #[repr(u8)]
 enum Thing {
     A = 1024,
-    B = 5
+    B = 5,
 }
 ```
 
@@ -1137,7 +1139,7 @@ enum Thing {
 
 ```ignore
 enum DependsOnPointerSize {
-    A = 1 << 32
+    A = 1 << 32,
 }
 ```
 
@@ -1153,7 +1155,7 @@ enum DependsOnPointerSize {
 
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0084
 #[repr(i32)]
 enum NightsWatch {} // error: unsupported representation for zero-variant enum
 ```
@@ -1181,7 +1183,7 @@ enum NightsWatch {}
 E0087: r##"
 Too many type parameters were supplied for a function. For example:
 
-```compile_fail
+```compile_fail,E0087
 fn foo<T>() {}
 
 fn main() {
@@ -1196,7 +1198,7 @@ fn main() {
 E0088: r##"
 You gave too many lifetime parameters. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0088
 fn f() {}
 
 fn main() {
@@ -1241,7 +1243,7 @@ fn main() {
 E0089: r##"
 Not enough type parameters were supplied for a function. For example:
 
-```compile_fail
+```compile_fail,E0089
 fn foo<T, U>() {}
 
 fn main() {
@@ -1252,7 +1254,7 @@ fn main() {
 Note that if a function takes multiple type parameters but you want the compiler
 to infer some of them, you can use type placeholders:
 
-```compile_fail
+```compile_fail,E0089
 fn foo<T, U>(x: T) {}
 
 fn main() {
@@ -1267,7 +1269,7 @@ fn main() {
 You gave an unnecessary type parameter in a type alias. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0091
 type Foo<T> = u32; // error: type parameter `T` is unused
 // or:
 type Foo<A,B> = Box<A>; // error: type parameter `B` is unused
@@ -1285,7 +1287,7 @@ fn main() {
 You tried to declare an undefined atomic operation function.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0092
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
@@ -1310,7 +1312,7 @@ fn main() {
 E0093: r##"
 You declared an unknown intrinsic function. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0093
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
@@ -1347,7 +1349,7 @@ fn main() {
 You gave an invalid number of type parameters to an intrinsic function.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0094
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
@@ -1373,10 +1375,8 @@ fn main() {
 You hit this error because the compiler lacks the information to
 determine a type for this expression. Erroneous code example:
 
-```compile_fail
-fn main() {
-    let x = |_| {}; // error: cannot determine a type for this expression
-}
+```compile_fail,E0101
+let x = |_| {}; // error: cannot determine a type for this expression
 ```
 
 You have two possibilities to solve this situation:
@@ -1386,12 +1386,10 @@ fn main() {
 Examples:
 
 ```
-fn main() {
-    let x = |_ : u32| {}; // ok!
-    // or:
-    let x = |_| {};
-    x(0u32);
-}
+let x = |_ : u32| {}; // ok!
+// or:
+let x = |_| {};
+x(0u32);
 ```
 "##,
 
@@ -1399,11 +1397,9 @@ fn main() {
 You hit this error because the compiler lacks the information to
 determine the type of this variable. Erroneous code example:
 
-```compile_fail
-fn main() {
-    // could be an array of anything
-    let x = []; // error: cannot determine a type for this local variable
-}
+```compile_fail,E0102
+// could be an array of anything
+let x = []; // error: cannot determine a type for this local variable
 ```
 
 To solve this situation, constrain the type of the variable.
@@ -1425,7 +1421,7 @@ fn main() {
 
 Here are some simple examples of where you'll run into this error:
 
-```compile_fail
+```compile_fail,E0106
 struct Foo { x: &bool }        // error
 struct Foo<'a> { x: &'a bool } // correct
 
@@ -1453,7 +1449,7 @@ enum Bar<'a> { A(u8), B(&'a bool), } // correct
 
 Here are some examples of elision errors:
 
-```compile_fail
+```compile_fail,E0106
 // error, no input lifetimes
 fn foo() -> &str { }
 
@@ -1473,7 +1469,7 @@ fn baz<'a>(x: &'a str, y: &str) -> &str { }
 
 Some basic examples include:
 
-```compile_fail
+```compile_fail,E0107
 struct Foo<'a>(&'a str);
 enum Bar { A, B, C }
 
@@ -1486,7 +1482,7 @@ struct Baz<'a> {
 Here's an example that is currently an error, but may work in a future version
 of Rust:
 
-```compile_fail
+```compile_fail,E0107
 struct Foo<'a>(&'a str);
 
 trait Quux { }
@@ -1504,7 +1500,7 @@ impl Quux for Foo { } // error: expected 1, found 0
 where the type was defined. For example, an `impl` block as below is not allowed
 since `Vec` is defined in the standard library:
 
-```compile_fail
+```compile_fail,E0116
 impl Vec<u8> { } // error
 ```
 
@@ -1518,7 +1514,7 @@ impl Vec<u8> { } // error
 Note that using the `type` keyword does not work here because `type` only
 introduces a type alias:
 
-```compile_fail
+```compile_fail,E0116
 type Bytes = Vec<u8>;
 
 impl Bytes { } // error, same as above
@@ -1536,7 +1532,7 @@ trait defined in another crate) where
 
 Here's one example of this error:
 
-```compile_fail
+```compile_fail,E0117
 impl Drop for u32 {}
 ```
 
@@ -1579,7 +1575,7 @@ fn get(&self) -> usize { 0 }
 You're trying to write an inherent implementation for something which isn't a
 struct nor an enum. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0118
 impl (u8, u8) { // error: no base type found for inherent implementation
     fn get_state(&self) -> String {
         // ...
@@ -1623,7 +1619,7 @@ fn get_state(&self) -> String {
 There are conflicting trait implementations for the same type.
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0119
 trait MyTrait {
     fn get(&self) -> usize;
 }
@@ -1684,7 +1680,7 @@ fn main() {
 An attempt was made to implement Drop on a trait, which is not allowed: only
 structs and enums can implement Drop. An example causing this error:
 
-```compile_fail
+```compile_fail,E0120
 trait MyTrait {}
 
 impl Drop for MyTrait {
@@ -1725,7 +1721,7 @@ fn drop(&mut self) {}
 
 Examples of this error include:
 
-```compile_fail
+```compile_fail,E0121
 fn foo() -> _ { 5 } // error, explicitly write out the return type instead
 
 static BAR: _ = "test"; // error, explicitly write out the type instead
@@ -1756,7 +1752,7 @@ fn main() {
 You declared two fields of a struct with the same name. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0124
 struct Foo {
     field1: i32,
     field1: i32, // error: field is already declared
@@ -1777,7 +1773,7 @@ struct Foo {
 Type parameter defaults can only use parameters that occur before them.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0128
 struct Foo<T=U, U=()> {
     field1: T,
     filed2: U,
@@ -1805,7 +1801,7 @@ struct Foo<U=(), T=U> {
 parameters. When `main` is present, it must take no arguments and return `()`.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0131
 fn main<T>() { // error: main function is not allowed to have type parameters
 }
 ```
@@ -1816,7 +1812,7 @@ fn main<T>() { // error: main function is not allowed to have type parameters
 
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0132
 #![feature(start)]
 
 #[start]
@@ -1847,7 +1843,7 @@ fn my_start(argc: isize, argv: *const *const u8) -> isize {
 This error means that an attempt was made to match a struct type enum
 variant as a non-struct type:
 
-```compile_fail
+```compile_fail,E0164
 enum Foo { B { i: u32 } }
 
 fn bar(foo: Foo) -> u32 {
@@ -1875,7 +1871,7 @@ fn bar(foo: Foo) -> u32 {
 marked as diverging. A function diverges if it has `!` in the place of the
 return type in its signature. For example:
 
-```compile_fail
+```compile_fail,E0166
 fn foo() -> ! { return; } // error
 ```
 
@@ -1888,7 +1884,7 @@ fn bar(foo: Foo) -> u32 {
 This error means that an attempt was made to specify the type of a variable with
 a combination of a concrete type and a trait. Consider the following example:
 
-```compile_fail
+```compile_fail,E0172
 fn foo(bar: i32+std::fmt::Display) {}
 ```
 
@@ -1917,7 +1913,7 @@ fn foo(bar: i32) {}
 
 For example:
 
-```compile_fail
+```compile_fail,E0178
 trait Foo {}
 
 struct Bar<'a> {
@@ -1949,7 +1945,7 @@ struct Bar<'a> {
 
 Here's an example of this error:
 
-```compile_fail
+```compile_fail,E0185
 trait Foo {
     fn foo();
 }
@@ -1971,7 +1967,7 @@ fn foo(&self) {}
 
 Here's an example of this error:
 
-```compile_fail
+```compile_fail,E0186
 trait Foo {
     fn foo(&self);
 }
@@ -1990,7 +1986,7 @@ fn foo() {}
 Trait objects need to have all associated types specified. Erroneous code
 example:
 
-```compile_fail
+```compile_fail,E0191
 trait Trait {
     type Bar;
 }
@@ -2066,7 +2062,7 @@ fn bar(&self) { }
 A type parameter was declared which shadows an existing one. An example of this
 error:
 
-```compile_fail
+```compile_fail,E0194
 trait Foo<T> {
     fn do_something(&self) -> T;
     fn do_something_else<T: Clone>(&self, bar: T);
@@ -2082,7 +2078,7 @@ trait Foo<T> {
 Your method's lifetime parameters do not match the trait declaration.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0195
 trait Trait {
     fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
 }
@@ -2121,7 +2117,7 @@ fn t<'a,'b:'a>(x: &'a str, y: &'b str) { // ok!
 implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
 implementation will resolve this error.
 
-```compile_fail
+```compile_fail,E0197
 struct Foo;
 
 // this will cause this error
@@ -2168,7 +2164,7 @@ impl !Enterprise for Foo { }
 implementation for a safe trait unsafe will cause a compiler error. Removing
 the unsafe marker on the trait noted in the error will resolve this problem.
 
-```compile_fail
+```compile_fail,E0199
 struct Foo;
 
 trait Bar { }
@@ -2185,7 +2181,7 @@ impl Bar for Foo { }
 implementation for an unsafe trait isn't marked as unsafe. This may be resolved
 by marking the unsafe implementation as unsafe.
 
-```compile_fail
+```compile_fail,E0200
 struct Foo;
 
 unsafe trait Bar { }
@@ -2203,7 +2199,7 @@ unsafe impl Bar for Foo { }
 
 For example:
 
-```compile_fail
+```compile_fail,E0201
 struct Foo(u8);
 
 impl Foo {
@@ -2258,7 +2254,7 @@ fn bar(&self) -> bool { self.0 }
 fields does not implement `Copy`. To fix this, you must implement `Copy` for the
 mentioned field. Note that this may not be possible, as in the example of
 
-```compile_fail
+```compile_fail,E0204
 struct Foo {
     foo : Vec<u32>,
 }
@@ -2270,7 +2266,7 @@ impl Copy for Foo { }
 
 Here's another example that will fail:
 
-```compile_fail
+```compile_fail,E0204
 #[derive(Copy)]
 struct Foo<'a> {
     ty: &'a mut bool,
@@ -2286,7 +2282,7 @@ struct Foo<'a> {
 variants does not implement `Copy`. To fix this, you must implement `Copy` for
 the mentioned variant. Note that this may not be possible, as in the example of
 
-```compile_fail
+```compile_fail,E0205
 enum Foo {
     Bar(Vec<u32>),
     Baz,
@@ -2299,11 +2295,11 @@ impl Copy for Foo { }
 
 Here's another example that will fail:
 
-```compile_fail
+```compile_fail,E0205
 #[derive(Copy)]
 enum Foo<'a> {
     Bar(&'a mut bool),
-    Baz
+    Baz,
 }
 ```
 
@@ -2316,7 +2312,7 @@ enum Foo<'a> {
 examples will fail, because neither `i32` (primitive type) nor `&'static Bar`
 (reference to `Bar`) is a struct or enum:
 
-```compile_fail
+```compile_fail,E0206
 type Foo = i32;
 impl Copy for Foo { } // error
 
@@ -2339,7 +2335,7 @@ impl Copy for &'static Bar { } // error
 Suppose we have a struct `Foo` and we would like to define some methods for it.
 The following definition leads to a compiler error:
 
-```compile_fail
+```compile_fail,E0207
 struct Foo;
 
 impl<T: Default> Foo {
@@ -2372,7 +2368,7 @@ fn get<T: Default>(&self) -> T {
 As another example, suppose we have a `Maker` trait and want to establish a
 type `FooMaker` that makes `Foo`s:
 
-```compile_fail
+```compile_fail,E0207
 trait Maker {
     type Item;
     fn make(&mut self) -> Self::Item;
@@ -2468,11 +2464,13 @@ fn make(&mut self) -> Foo<T> {
 If `ForeignTrait` is a trait defined in some external crate `foo`, then the
 following trait `impl` is an error:
 
-```compile_fail
-extern crate foo;
-use foo::ForeignTrait;
+```compile_fail,E0210
+extern crate collections;
+use collections::range::RangeArgument;
+
+impl<T> RangeArgument<T> for T { } // error
 
-impl<T> ForeignTrait for T { } // error
+fn main() {}
 ```
 
 To work around this, it can be covered with a local type, `MyType`:
@@ -2611,7 +2609,7 @@ fn x(self: Box<Foo>) {} // ok!
 A generic type was described using parentheses rather than angle brackets. For
 example:
 
-```compile_fail
+```compile_fail,E0214
 fn main() {
     let v: Vec(&str) = vec!["foo"];
 }
@@ -2626,7 +2624,7 @@ fn main() {
 You used an associated type which isn't defined in the trait.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0220
 trait T1 {
     type Bar;
 }
@@ -2670,7 +2668,7 @@ trait T2 {
 An attempt was made to retrieve an associated type, but the type was ambiguous.
 For example:
 
-```compile_fail
+```compile_fail,E0221
 trait T1 {}
 trait T2 {}
 
@@ -2716,7 +2714,7 @@ fn do_something() {
 An attempt was made to retrieve an associated type, but the type was ambiguous.
 For example:
 
-```compile_fail
+```compile_fail,E0223
 trait MyTrait {type X; }
 
 fn main() {
@@ -2751,7 +2749,7 @@ fn main() {
 You attempted to use multiple types as bounds for a closure or trait object.
 Rust does not currently support this. A simple example that causes this error:
 
-```compile_fail
+```compile_fail,E0225
 fn main() {
     let _: Box<std::io::Read + std::io::Write>;
 }
@@ -2771,7 +2769,7 @@ fn main() {
 E0232: r##"
 The attribute must have a value. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0232
 #![feature(on_unimplemented)]
 
 #[rustc_on_unimplemented] // error: this attribute must have a value
@@ -2795,7 +2793,7 @@ trait Bar {}
 For example, the `Foo` struct below is defined to be generic in `T`, but the
 type parameter is missing in the definition of `Bar`:
 
-```compile_fail
+```compile_fail,E0243
 struct Foo<T> { x: T }
 
 struct Bar { x: Foo }
@@ -2809,7 +2807,7 @@ struct Bar { x: Foo }
 For example, the `Foo` struct below has no type parameters, but is supplied
 with two in the definition of `Bar`:
 
-```compile_fail
+```compile_fail,E0244
 struct Foo { x: bool }
 
 struct Bar<S, T> { x: Foo<S, T> }
@@ -2820,7 +2818,7 @@ struct Bar<S, T> { x: Foo<S, T> }
 This error indicates an attempt to use a value where a type is expected. For
 example:
 
-```compile_fail
+```compile_fail,E0248
 enum Foo {
     Bar(u32)
 }
@@ -2845,14 +2843,14 @@ fn do_something(x: Foo::Bar) { }
 A cross-crate opt-out trait was implemented on something which wasn't a struct
 or enum type. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0321
 #![feature(optin_builtin_traits)]
 
 struct Foo;
 
 impl !Sync for Foo {}
 
-unsafe impl Send for &'static Foo {
+unsafe impl Send for &'static Foo {}
 // error: cross-crate traits with a default impl, like `core::marker::Send`,
 //        can only be implemented for a struct/enum type, not
 //        `&'static Foo`
@@ -2874,7 +2872,7 @@ unsafe impl Send for &'static Foo {
 An associated const was implemented when another trait item was expected.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0323
 #![feature(associated_consts)]
 
 trait Foo {
@@ -2926,7 +2924,9 @@ impl Foo for Bar {
 A method was implemented when another trait item was expected. Erroneous
 code example:
 
-```compile_fail
+```compile_fail,E0324
+#![feature(associated_consts)]
+
 struct Bar;
 
 trait Foo {
@@ -2968,7 +2968,9 @@ fn M() {} // ok!
 An associated type was implemented when another trait item was expected.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0325
+#![feature(associated_consts)]
+
 struct Bar;
 
 trait Foo {
@@ -3020,7 +3022,9 @@ impl Foo for Bar {
 
 Here's an example of this error:
 
-```compile_fail
+```compile_fail,E0326
+#![feature(associated_consts)]
+
 trait Foo {
     const BAR: bool;
 }
@@ -3078,7 +3082,7 @@ fn get_bar_good() -> f64 {
 An attempt was made to implement `Drop` on a concrete specialization of a
 generic type. An example is shown below:
 
-```compile_fail
+```compile_fail,E0366
 struct Foo<T> {
     t: T
 }
@@ -3111,7 +3115,7 @@ fn drop(&mut self) {}
 An attempt was made to implement `Drop` on a specialization of a generic type.
 An example is shown below:
 
-```compile_fail
+```compile_fail,E0367
 trait Foo{}
 
 struct MyStruct<T> {
@@ -3149,7 +3153,7 @@ fn drop(&mut self) {}
 This error indicates that a binary assignment operator like `+=` or `^=` was
 applied to a type that doesn't support it. For example:
 
-```compile_fail
+```compile_fail,E0368
 let mut x = 12f32; // error: binary operation `<<` cannot be applied to
                    //        type `f32`
 
@@ -3172,7 +3176,7 @@ fn drop(&mut self) {}
 operator for some type `Foo` by implementing the `std::ops::Add` trait for
 `Foo`, but you find that using `+=` does not work, as in this example:
 
-```compile_fail
+```compile_fail,E0368
 use std::ops::Add;
 
 struct Foo(u32);
@@ -3199,7 +3203,7 @@ fn main() {
 A binary operation was attempted on a type which doesn't support it.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0369
 let x = 12f32; // error: binary operation `<<` cannot be applied to
                //        type `f32`
 
@@ -3262,7 +3266,7 @@ enum Foo {
 
 Example:
 
-```compile_fail
+```compile_fail,E0371
 trait Foo { fn foo(&self) { } }
 trait Bar: Foo { }
 trait Baz: Bar { }
@@ -3283,7 +3287,7 @@ impl Baz for Bar { } // Note: This is OK
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0374
 #![feature(coerce_unsized)]
 use std::ops::CoerceUnsized;
 
@@ -3342,7 +3346,7 @@ impl `CoerceUnsized` from `T` to `U` which are both types that the struct
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0375
 #![feature(coerce_unsized)]
 use std::ops::CoerceUnsized;
 
@@ -3397,7 +3401,7 @@ fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
 
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0376
 #![feature(coerce_unsized)]
 use std::ops::CoerceUnsized;
 
@@ -3448,7 +3452,7 @@ impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
 E0390: r##"
 You tried to implement methods for a primitive type. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0390
 struct Foo {
     x: i32
 }
@@ -3482,7 +3486,7 @@ fn bar() {} // ok!
 
 The following example contains a circular dependency between two traits:
 
-```compile_fail
+```compile_fail,E0391
 trait FirstTrait : SecondTrait {
 
 }
@@ -3497,9 +3501,9 @@ trait SecondTrait : FirstTrait {
 This error indicates that a type or lifetime parameter has been declared
 but not actually used. Here is an example that demonstrates the error:
 
-```compile_fail
+```compile_fail,E0392
 enum Foo<T> {
-    Bar
+    Bar,
 }
 ```
 
@@ -3508,7 +3512,7 @@ enum Foo<T> {
 
 ```
 enum Foo {
-    Bar
+    Bar,
 }
 ```
 
@@ -3517,7 +3521,7 @@ enum Foo {
 
 ```
 enum Foo<T> {
-    Bar(T)
+    Bar(T),
 }
 ```
 
@@ -3526,9 +3530,9 @@ enum Foo<T> {
 which the pointed-at data is valid. An initial attempt (below) causes this
 error:
 
-```compile_fail
+```compile_fail,E0392
 struct Foo<'a, T> {
-    x: *const T
+    x: *const T,
 }
 ```
 
@@ -3557,7 +3561,7 @@ struct Foo<'a, T: 'a> {
 A type parameter which references `Self` in its default value was not specified.
 Example of erroneous code:
 
-```compile_fail
+```compile_fail,E0393
 trait A<T=Self> {}
 
 fn together_we_will_rule_the_galaxy(son: &A) {}
@@ -3588,7 +3592,7 @@ fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok!
 The length of the platform-intrinsic function `simd_shuffle`
 wasn't specified. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0439
 #![feature(platform_intrinsics)]
 
 extern "platform-intrinsic" {
@@ -3613,7 +3617,7 @@ fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok!
 A platform-specific intrinsic function has the wrong number of type
 parameters. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0440
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 
@@ -3647,7 +3651,7 @@ fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok!
 An unknown platform-specific intrinsic function was used. Erroneous
 code example:
 
-```compile_fail
+```compile_fail,E0441
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 
@@ -3681,7 +3685,7 @@ fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok!
 Intrinsic argument(s) and/or return value have the wrong type.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0442
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 
@@ -3719,7 +3723,7 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
 Intrinsic argument(s) and/or return value have the wrong type.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0443
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 
@@ -3754,7 +3758,7 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
 A platform-specific intrinsic function has wrong number of arguments.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0444
 #![feature(repr_simd)]
 #![feature(platform_intrinsics)]
 
@@ -3787,7 +3791,7 @@ struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
 The `typeof` keyword is currently reserved but unimplemented.
 Erroneous code example:
 
-```compile_fail
+```compile_fail,E0516
 fn main() {
     let x: typeof(92) = 92;
 }
@@ -3806,7 +3810,7 @@ fn main() {
 A non-default implementation was already made on this type so it cannot be
 specialized further. Erroneous code example:
 
-```compile_fail
+```compile_fail,E0520
 #![feature(specialization)]
 
 trait SpaceLlama {
@@ -4084,4 +4088,9 @@ struct Simba {
     E0513, // no type for local variable ..
     E0521, // redundant default implementations of trait
     E0533, // `{}` does not name a unit variant, unit struct or a constant
+    E0562, // `impl Trait` not allowed outside of function
+           // and inherent method return types
+    E0563, // cannot determine a type for this `impl Trait`: {}
+    E0564, // only named lifetimes are allowed in `impl Trait`,
+           // but `{}` was found in the type `{}`
 }
index 65e00705121a7e6dcc5745d3034f10d5c0550053..0dd4bc4143927ce6dd0081a4e8767d3c727cb30d 100644 (file)
 use rustc::infer::TypeOrigin;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::traits::ProjectionMode;
+use rustc::traits::{self, Reveal};
 use session::{config, CompileResult};
 use util::common::time;
 
@@ -139,9 +139,6 @@ pub struct TypeAndSubsts<'tcx> {
 pub struct CrateCtxt<'a, 'tcx: 'a> {
     ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
 
-    /// A mapping from method call sites to traits that have that method.
-    pub trait_map: hir::TraitMap,
-
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
     /// error reporting, and so is lazily initialised and generally
@@ -153,6 +150,11 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
     pub stack: RefCell<Vec<collect::AstConvRequest>>,
 
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+
+    /// Obligations which will have to be checked at the end of
+    /// type-checking, after all functions have been inferred.
+    /// The key is the NodeId of the item the obligations were from.
+    pub deferred_obligations: RefCell<NodeMap<Vec<traits::DeferredObligation<'tcx>>>>,
 }
 
 // Functions that write types into the node type table
@@ -181,8 +183,10 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
                              abi: Abi,
                              span: Span) {
     if decl.variadic && abi != Abi::C {
-        span_err!(tcx.sess, span, E0045,
+        let mut err = struct_span_err!(tcx.sess, span, E0045,
                   "variadic function must have C calling convention");
+        err.span_label(span, &("variadics require C calling conventions").to_string())
+            .emit();
     }
 }
 
@@ -191,7 +195,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 t1: Ty<'tcx>,
                                 t2: Ty<'tcx>)
                                 -> bool {
-    ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
+    ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
         if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
             infcx.report_mismatched_types(origin, t1, t2, err);
             false
@@ -265,9 +269,10 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                     match it.node {
                         hir::ItemFn(_,_,_,_,ref ps,_)
                         if ps.is_parameterized() => {
-                            struct_span_err!(tcx.sess, start_span, E0132,
+                            let sp = if let Some(sp) = ps.span() { sp } else { start_span };
+                            struct_span_err!(tcx.sess, sp, E0132,
                                 "start function is not allowed to have type parameters")
-                                .span_label(ps.span().unwrap(),
+                                .span_label(sp,
                                             &format!("start function cannot have type parameters"))
                                 .emit();
                             return;
@@ -321,16 +326,15 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
     }
 }
 
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             trait_map: hir::TraitMap)
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                              -> CompileResult {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         ast_ty_to_ty_cache: RefCell::new(NodeMap()),
-        trait_map: trait_map,
         all_traits: RefCell::new(None),
         stack: RefCell::new(Vec::new()),
-        tcx: tcx
+        tcx: tcx,
+        deferred_obligations: RefCell::new(NodeMap()),
     };
 
     // this ensures that later parts of type checking can assume that items
index 336a61708683e0d6b05bea15cc3b490a54d67632..58d1ec9d02a954d32047024e8b23b6919a03f9b8 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 
-use rustc::ty;
+use rustc::ty::{self, TyCtxt};
+use rustc::ty::subst::Substs;
 
 use std::cell::Cell;
 use syntax_pos::Span;
@@ -50,6 +51,79 @@ fn anon_regions(&self,
     /// computing `object_lifetime_default` (in particular, in legacy
     /// modes, it may not be relevant).
     fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
+
+    /// If this scope allows anonymized types, return the generics in
+    /// scope, that anonymized types will close over. For example,
+    /// if you have a function like:
+    ///
+    ///     fn foo<'a, T>() -> impl Trait { ... }
+    ///
+    /// then, for the rscope that is used when handling the return type,
+    /// `anon_type_scope()` would return a `Some(AnonTypeScope {...})`,
+    /// on which `.fresh_substs(...)` can be used to obtain identity
+    /// Substs for `'a` and `T`, to track them in `TyAnon`. This property
+    /// is controlled by the region scope because it's fine-grained enough
+    /// to allow restriction of anonymized types to the syntactical extent
+    /// of a function's return type.
+    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
+        None
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct AnonTypeScope<'a> {
+    generics: &'a ty::Generics<'a>
+}
+
+impl<'a, 'b, 'gcx, 'tcx> AnonTypeScope<'a> {
+    pub fn new(generics: &'a ty::Generics<'a>) -> AnonTypeScope<'a> {
+        AnonTypeScope {
+            generics: generics
+        }
+    }
+
+    pub fn fresh_substs(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx Substs<'tcx> {
+        use collect::mk_item_substs;
+
+        mk_item_substs(tcx, self.generics)
+    }
+}
+
+/// A scope wrapper which optionally allows anonymized types.
+#[derive(Copy, Clone)]
+pub struct MaybeWithAnonTypes<'a, R> {
+    base_scope: R,
+    anon_scope: Option<AnonTypeScope<'a>>
+}
+
+impl<'a, R: RegionScope> MaybeWithAnonTypes<'a, R>  {
+    pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope<'a>>) -> Self {
+        MaybeWithAnonTypes {
+            base_scope: base_scope,
+            anon_scope: anon_scope
+        }
+    }
+}
+
+impl<'a, R: RegionScope> RegionScope for MaybeWithAnonTypes<'a, R> {
+    fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
+        self.base_scope.object_lifetime_default(span)
+    }
+
+    fn anon_regions(&self,
+                    span: Span,
+                    count: usize)
+                    -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
+        self.base_scope.anon_regions(span, count)
+    }
+
+    fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
+        self.base_scope.base_object_lifetime_default(span)
+    }
+
+    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
+        self.anon_scope
+    }
 }
 
 // A scope in which all regions must be explicitly named. This is used
@@ -221,6 +295,10 @@ fn anon_regions(&self,
     {
         self.base_scope.anon_regions(span, count)
     }
+
+    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
+        self.base_scope.anon_type_scope()
+    }
 }
 
 /// A scope which simply shifts the Debruijn index of other scopes
@@ -262,4 +340,8 @@ fn anon_regions(&self,
             }
         }
     }
+
+    fn anon_type_scope(&self) -> Option<AnonTypeScope> {
+        self.base_scope.anon_type_scope()
+    }
 }
index 01a310da25ddd26a364f0526a51df43c7e8f844f..b9e0b4a10ea45ec9396a186cd103800ac0b085c1 100644 (file)
@@ -326,7 +326,7 @@ fn add_constraints_from_ty(&mut self,
                 /* leaf type -- noop */
             }
 
-            ty::TyClosure(..) => {
+            ty::TyClosure(..) | ty::TyAnon(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
index d609ad84a83831dd8920ab84b60e9791231f93f3..73bc647fa9ffbcf63d8129fb30d8f66e452a5502 100644 (file)
 use rustc_trans::back::link;
 use rustc::middle::cstore;
 use rustc::middle::privacy::AccessLevels;
+use rustc::middle::resolve_lifetime::DefRegion::*;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::fold::Folder;
 use rustc::hir::print as pprust;
 use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::ty;
@@ -1490,6 +1492,9 @@ pub enum Type {
 
     // for<'a> Foo(&'a)
     PolyTraitRef(Vec<TyParamBound>),
+
+    // impl TraitA+TraitB
+    ImplTrait(Vec<TyParamBound>),
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
@@ -1636,6 +1641,43 @@ pub fn to_def_index(&self) -> DefIndex {
     }
 }
 
+
+// Poor man's type parameter substitution at HIR level.
+// Used to replace private type aliases in public signatures with their aliased types.
+struct SubstAlias<'a, 'tcx: 'a> {
+    tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>,
+    // Table type parameter definition -> substituted type
+    ty_substs: HashMap<Def, hir::Ty>,
+    // Table node id of lifetime parameter definition -> substituted lifetime
+    lt_substs: HashMap<ast::NodeId, hir::Lifetime>,
+}
+
+impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> {
+    fn fold_ty(&mut self, ty: P<hir::Ty>) -> P<hir::Ty> {
+        if let hir::TyPath(..) = ty.node {
+            let def = self.tcx.expect_def(ty.id);
+            if let Some(new_ty) = self.ty_substs.get(&def).cloned() {
+                return P(new_ty);
+            }
+        }
+        hir::fold::noop_fold_ty(ty, self)
+    }
+    fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime {
+        let def = self.tcx.named_region_map.defs.get(&lt.id).cloned();
+        match def {
+            Some(DefEarlyBoundRegion(_, _, node_id)) |
+            Some(DefLateBoundRegion(_, node_id)) |
+            Some(DefFreeRegion(_, node_id)) => {
+                if let Some(lt) = self.lt_substs.get(&node_id).cloned() {
+                    return lt;
+                }
+            }
+            _ => {}
+        }
+        hir::fold::noop_fold_lifetime(lt, self)
+    }
+}
+
 impl Clean<Type> for hir::Ty {
     fn clean(&self, cx: &DocContext) -> Type {
         use rustc::hir::*;
@@ -1665,8 +1707,46 @@ fn clean(&self, cx: &DocContext) -> Type {
                 FixedVector(box ty.clean(cx), n)
             },
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(None, ref p) => {
-                resolve_type(cx, p.clean(cx), self.id)
+            TyPath(None, ref path) => {
+                if let Some(tcx) = cx.tcx_opt() {
+                    // Substitute private type aliases
+                    let def = tcx.expect_def(self.id);
+                    if let Def::TyAlias(def_id) = def {
+                        if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+                            if !cx.access_levels.borrow().is_exported(def_id) {
+                                let item = tcx.map.expect_item(node_id);
+                                if let hir::ItemTy(ref ty, ref generics) = item.node {
+                                    let provided_params = &path.segments.last().unwrap().parameters;
+                                    let mut ty_substs = HashMap::new();
+                                    let mut lt_substs = HashMap::new();
+                                    for (i, ty_param) in generics.ty_params.iter().enumerate() {
+                                        let ty_param_def = 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());
+                                        } else if let Some(default) = ty_param.default.clone() {
+                                            ty_substs.insert(ty_param_def, default.unwrap());
+                                        }
+                                    }
+                                    for (i, lt_param) in generics.lifetimes.iter().enumerate() {
+                                        if let Some(lt) = provided_params.lifetimes().get(i)
+                                                                                     .cloned()
+                                                                                     .cloned() {
+                                            lt_substs.insert(lt_param.lifetime.id, lt);
+                                        }
+                                    }
+                                    let mut subst_alias = SubstAlias {
+                                        tcx: &tcx,
+                                        ty_substs: ty_substs,
+                                        lt_substs: lt_substs
+                                    };
+                                    return subst_alias.fold_ty(ty.clone()).clean(cx);
+                                }
+                            }
+                        }
+                    }
+                }
+                resolve_type(cx, path.clean(cx), self.id)
             }
             TyPath(Some(ref qself), ref p) => {
                 let mut segments: Vec<_> = p.segments.clone().into();
@@ -1700,6 +1780,7 @@ fn clean(&self, cx: &DocContext) -> Type {
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyPolyTraitRef(ref bounds) => PolyTraitRef(bounds.clean(cx)),
+            TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)),
             TyInfer => Infer,
             TyTypeof(..) => panic!("Unimplemented type {:?}", self.node),
         }
@@ -1786,6 +1867,18 @@ fn clean(&self, cx: &DocContext) -> Type {
 
             ty::TyParam(ref p) => Generic(p.name.to_string()),
 
+            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().lookup_predicates(def_id);
+                let substs = cx.tcx().lift(&substs).unwrap();
+                let bounds = item_predicates.instantiate(cx.tcx(), substs);
+                let predicates = bounds.predicates.into_vec();
+                ImplTrait(predicates.into_iter().filter_map(|predicate| {
+                    predicate.to_opt_poly_trait_ref().clean(cx)
+                }).collect())
+            }
+
             ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::TyInfer(..) => panic!("TyInfer"),
index fc9ae73f5ce7e2ec96a4c584c4e8f652c9b38746..7d8ebc403b08f1c5cc59f050a0df042ce42a5650 100644 (file)
@@ -128,7 +128,6 @@ pub fn run_core(search_paths: SearchPaths,
 
     let codemap = Rc::new(codemap::CodeMap::new());
     let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
-                                                               None,
                                                                true,
                                                                false,
                                                                Some(codemap.clone()));
index eed2615175b27a62ce77ce4debd5a2de1aff430e..854ca57e8556c72a606a0f4e49c2de298c3e9c22 100644 (file)
@@ -539,6 +539,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 }
                 Ok(())
             }
+            clean::ImplTrait(ref bounds) => {
+                write!(f, "impl ")?;
+                for (i, bound) in bounds.iter().enumerate() {
+                    if i != 0 {
+                        write!(f, " + ")?;
+                    }
+                    write!(f, "{}", *bound)?;
+                }
+                Ok(())
+            }
             // It's pretty unsightly to look at `<A as B>::C` in output, and
             // we've got hyperlinking on our side, so try to avoid longer
             // notation as much as possible by making `C` a hyperlink to trait
index f9d0df9981a1d73bc9e796746aaca850cda0736d..5f1d28c8d316ad35014bd2f4a56f124449a6fdfc 100644 (file)
@@ -74,7 +74,6 @@ pub fn run(input: &str,
 
     let codemap = Rc::new(CodeMap::new());
     let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
-                                                               None,
                                                                true,
                                                                false,
                                                                Some(codemap.clone()));
@@ -228,9 +227,7 @@ fn drop(&mut self) {
     let data = Arc::new(Mutex::new(Vec::new()));
     let codemap = Rc::new(CodeMap::new());
     let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
-                                                None,
-                                                Some(codemap.clone()),
-                                                errors::snippet::FormatMode::EnvironmentSelected);
+                                                      Some(codemap.clone()));
     let old = io::set_panic(box Sink(data.clone()));
     let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
 
index fd7b0a2e6bbf6d9b0d8834c911e7dca320c7c298..8039421ae77306418d2895f00284e6dad9e6c030 100644 (file)
@@ -199,13 +199,12 @@ fn test_resize_policy() {
 /// A hash map implementation which uses linear probing with Robin
 /// Hood bucket stealing.
 ///
-/// The hashes are all keyed by the thread-local random number generator
-/// on creation by default. This means that the ordering of the keys is
-/// randomized, but makes the tables more resistant to
-/// denial-of-service attacks (Hash DoS). No guarantees are made to the
-/// quality of the random data. The implementation uses the best available
-/// random data from your platform at the time of creation. This behavior
-/// can be overridden with one of the constructors.
+/// By default, HashMap uses a somewhat slow hashing algorithm which can provide resistance
+/// to DoS attacks. Rust makes a best attempt at acquiring random numbers without IO
+/// blocking from your system. Because of this HashMap is not guaranteed to provide
+/// DoS resistance since the numbers generated might not be truly random. If you do
+/// require this behavior you can create your own hashing function using
+/// [BuildHasherDefault](../hash/struct.BuildHasherDefault.html).
 ///
 /// It is required that the keys implement the `Eq` and `Hash` traits, although
 /// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
index d6d62ce79d4e6ff94aa780736adcce7d8b9da3ba..753411991abeadab7cb77c8265c857a44e0891fd 100644 (file)
@@ -526,10 +526,10 @@ pub fn temp_dir() -> PathBuf {
 /// Ok("/home/alex/bar")
 /// ```
 ///
-/// This sort of behavior has been known to [lead to privledge escalation] when
+/// This sort of behavior has been known to [lead to privilege escalation] when
 /// used incorrectly, for example.
 ///
-/// [lead to privledge escalation]: http://securityvulns.com/Wdocument183.html
+/// [lead to privilege escalation]: http://securityvulns.com/Wdocument183.html
 ///
 /// # Examples
 ///
index e0501f9cc61d24c70781bab1cf2645d2ed143ffe..77b90c0846bbe44f2349b7a674223d6f47ea59f9 100644 (file)
@@ -99,11 +99,9 @@ pub struct CString {
 ///
 /// extern { fn my_string() -> *const c_char; }
 ///
-/// fn main() {
-///     unsafe {
-///         let slice = CStr::from_ptr(my_string());
-///         println!("string length: {}", slice.to_bytes().len());
-///     }
+/// unsafe {
+///     let slice = CStr::from_ptr(my_string());
+///     println!("string length: {}", slice.to_bytes().len());
 /// }
 /// ```
 ///
@@ -119,10 +117,8 @@ pub struct CString {
 ///     unsafe { work_with(data.as_ptr()) }
 /// }
 ///
-/// fn main() {
-///     let s = CString::new("data data data data").unwrap();
-///     work(&s);
-/// }
+/// let s = CString::new("data data data data").unwrap();
+/// work(&s);
 /// ```
 ///
 /// Converting a foreign C string into a Rust `String`
@@ -139,9 +135,7 @@ pub struct CString {
 ///     }
 /// }
 ///
-/// fn main() {
-///     println!("string: {}", my_string_safe());
-/// }
+/// println!("string: {}", my_string_safe());
 /// ```
 #[derive(Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -188,11 +182,9 @@ impl CString {
     ///
     /// extern { fn puts(s: *const c_char); }
     ///
-    /// fn main() {
-    ///     let to_print = CString::new("Hello!").unwrap();
-    ///     unsafe {
-    ///         puts(to_print.as_ptr());
-    ///     }
+    /// let to_print = CString::new("Hello!").unwrap();
+    /// unsafe {
+    ///     puts(to_print.as_ptr());
     /// }
     /// ```
     ///
index c6272012d66d5b13bb1010658e0c9b220b3bf85d..c05e0c3ca68dfeea25c7ba5c56a57fd65c00fed1 100644 (file)
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
+#![cfg_attr(test, feature(update_panic_count))]
 
 // Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
 // might be unavailable or disabled
index ba18d15f5c4e384a8be0eeb0c0d83f7442d5ba01..2f67081e0d71093c29625a4de7c292112cca4dad 100644 (file)
@@ -340,5 +340,5 @@ pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
 /// ```
 #[stable(feature = "resume_unwind", since = "1.9.0")]
 pub fn resume_unwind(payload: Box<Any + Send>) -> ! {
-    panicking::rust_panic(payload)
+    panicking::update_count_then_panic(payload)
 }
index 57a4c3df70a476eeeb680233db6ab390a4c95490..5961fd59699c1b8d0a92341e6c78f69729f0b648 100644 (file)
 use io::prelude::*;
 
 use any::Any;
-use cell::Cell;
 use cell::RefCell;
 use fmt;
 use intrinsics;
 use mem;
+use ptr;
 use raw;
-use sys_common::rwlock::RWLock;
 use sys::stdio::Stderr;
+use sys_common::rwlock::RWLock;
 use sys_common::thread_info;
 use sys_common::util;
 use thread;
@@ -39,8 +39,6 @@
     }
 }
 
-thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }
-
 // Binary interface to the panic runtime that the standard library depends on.
 //
 // The standard library is tagged with `#![needs_panic_runtime]` (introduced in
@@ -187,7 +185,7 @@ fn default_hook(info: &PanicInfo) {
     // for this panic. Otherwise only print it if logging is enabled.
     #[cfg(any(not(cargobuild), feature = "backtrace"))]
     let log_backtrace = {
-        let panics = PANIC_COUNT.with(|c| c.get());
+        let panics = update_panic_count(0);
 
         panics >= 2 || backtrace::log_enabled()
     };
@@ -238,54 +236,102 @@ fn default_hook(info: &PanicInfo) {
     }
 }
 
+
+#[cfg(not(test))]
+#[doc(hidden)]
+#[unstable(feature = "update_panic_count", issue = "0")]
+pub fn update_panic_count(amt: isize) -> usize {
+    use cell::Cell;
+    thread_local! { static PANIC_COUNT: Cell<usize> = Cell::new(0) }
+
+    PANIC_COUNT.with(|c| {
+        let next = (c.get() as isize + amt) as usize;
+        c.set(next);
+        return next
+    })
+}
+
+#[cfg(test)]
+pub use realstd::rt::update_panic_count;
+
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
-    let mut slot = None;
-    let mut f = Some(f);
-    let ret = PANIC_COUNT.with(|s| {
-        let prev = s.get();
-        s.set(0);
-
-        let mut to_run = || {
-            slot = Some(f.take().unwrap()());
-        };
-        let fnptr = get_call(&mut to_run);
-        let dataptr = &mut to_run as *mut _ as *mut u8;
-        let mut any_data = 0;
-        let mut any_vtable = 0;
-        let fnptr = mem::transmute::<fn(&mut _), fn(*mut u8)>(fnptr);
-        let r = __rust_maybe_catch_panic(fnptr,
-                                         dataptr,
-                                         &mut any_data,
-                                         &mut any_vtable);
-        s.set(prev);
-
-        if r == 0 {
-            Ok(())
-        } else {
-            Err(mem::transmute(raw::TraitObject {
-                data: any_data as *mut _,
-                vtable: any_vtable as *mut _,
-            }))
-        }
-    });
+    struct Data<F, R> {
+        f: F,
+        r: R,
+    }
 
-    return ret.map(|()| {
-        slot.take().unwrap()
-    });
+    // We do some sketchy operations with ownership here for the sake of
+    // performance. The `Data` structure is never actually fully valid, but
+    // instead it always contains at least one uninitialized field. We can only
+    // pass pointers down to `__rust_maybe_catch_panic` (can't pass objects by
+    // value), so we do all the ownership tracking here manully.
+    //
+    // Note that this is all invalid if any of these functions unwind, but the
+    // whole point of this function is to prevent that! As a result we go
+    // through a transition where:
+    //
+    // * First, only the closure we're going to call is initialized. The return
+    //   value is uninitialized.
+    // * When we make the function call, the `do_call` function below, we take
+    //   ownership of the function pointer, replacing it with uninitialized
+    //   data. At this point the `Data` structure is entirely uninitialized, but
+    //   it won't drop due to an unwind because it's owned on the other side of
+    //   the catch panic.
+    // * If the closure successfully returns, we write the return value into the
+    //   data's return slot. Note that `ptr::write` is used as it's overwriting
+    //   uninitialized data.
+    // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're
+    //   in one of two states:
+    //
+    //      1. The closure didn't panic, in which case the return value was
+    //         filled in. We have to be careful to `forget` the closure,
+    //         however, as ownership was passed to the `do_call` function.
+    //      2. The closure panicked, in which case the return value wasn't
+    //         filled in. In this case the entire `data` structure is invalid,
+    //         so we forget the entire thing.
+    //
+    // Once we stack all that together we should have the "most efficient'
+    // method of calling a catch panic whilst juggling ownership.
+    let mut any_data = 0;
+    let mut any_vtable = 0;
+    let mut data = Data {
+        f: f,
+        r: mem::uninitialized(),
+    };
 
-    fn get_call<F: FnMut()>(_: &mut F) -> fn(&mut F) {
-        call
-    }
+    let r = __rust_maybe_catch_panic(do_call::<F, R>,
+                                     &mut data as *mut _ as *mut u8,
+                                     &mut any_data,
+                                     &mut any_vtable);
+
+    return if r == 0 {
+        let Data { f, r } = data;
+        mem::forget(f);
+        debug_assert!(update_panic_count(0) == 0);
+        Ok(r)
+    } else {
+        mem::forget(data);
+        update_panic_count(-1);
+        debug_assert!(update_panic_count(0) == 0);
+        Err(mem::transmute(raw::TraitObject {
+            data: any_data as *mut _,
+            vtable: any_vtable as *mut _,
+        }))
+    };
 
-    fn call<F: FnMut()>(f: &mut F) {
-        f()
+    fn do_call<F: FnOnce() -> R, R>(data: *mut u8) {
+        unsafe {
+            let data = data as *mut Data<F, R>;
+            let f = ptr::read(&mut (*data).f);
+            ptr::write(&mut (*data).r, f());
+        }
     }
 }
 
 /// Determines whether the current thread is unwinding because of panic.
 pub fn panicking() -> bool {
-    PANIC_COUNT.with(|c| c.get() != 0)
+    update_panic_count(0) != 0
 }
 
 /// Entry point of panic from the libcore crate.
@@ -350,18 +396,14 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
                         file_line: &(&'static str, u32)) -> ! {
     let (file, line) = *file_line;
 
-    let panics = PANIC_COUNT.with(|c| {
-        let prev = c.get();
-        c.set(prev + 1);
-        prev
-    });
+    let panics = update_panic_count(1);
 
     // If this is the third nested call (e.g. panics == 2, this is 0-indexed),
     // the panic hook probably triggered the last panic, otherwise the
     // double-panic check would have aborted the process. In this case abort the
     // process real quickly as we don't want to try calling it again as it'll
     // probably just panic again.
-    if panics > 1 {
+    if panics > 2 {
         util::dumb_print(format_args!("thread panicked while processing \
                                        panic. aborting.\n"));
         unsafe { intrinsics::abort() }
@@ -383,7 +425,7 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
         HOOK_LOCK.read_unlock();
     }
 
-    if panics > 0 {
+    if panics > 1 {
         // If a thread panics while it's already unwinding then we
         // have limited options. Currently our preference is to
         // just abort. In the future we may consider resuming
@@ -396,6 +438,12 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
     rust_panic(msg)
 }
 
+/// Shim around rust_panic. Called by resume_unwind.
+pub fn update_count_then_panic(msg: Box<Any + Send>) -> ! {
+    update_panic_count(1);
+    rust_panic(msg)
+}
+
 /// A private no-mangle function on which to slap yer breakpoints.
 #[no_mangle]
 #[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
index 5a7c0fe4816c981334849c6fd2d5a91602fe08f2..a3d9e4db7d19a4b0927b5e30356b813c412438d7 100644 (file)
@@ -25,7 +25,7 @@
 
 
 // Reexport some of our utilities which are expected by other crates.
-pub use panicking::{begin_panic, begin_panic_fmt};
+pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
 
 #[cfg(not(test))]
 #[lang = "start"]
index b5287cce4843c13a511e4a16cdbae1d7410941a2..a4564b9543b3430cdd810b87ecf5c5bf65b434c2 100644 (file)
@@ -110,7 +110,7 @@ fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<S
         })
     }
 
-    /// Returns true iff the address is unnamed.
+    /// Returns true if and only if the address is unnamed.
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn is_unnamed(&self) -> bool {
         if let AddressKind::Unnamed = self.address() {
index a8bb255fba4a4d4b099c936239dee1abdc7fee7c..3f929e6d23aea0cedcd5eda3d8aa9256e7a3ae5e 100644 (file)
@@ -1368,6 +1368,8 @@ pub enum TyKind {
     ObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
     PolyTraitRef(TyParamBounds),
+    /// An `impl TraitA+TraitB` type.
+    ImplTrait(TyParamBounds),
     /// No-op; kept solely so that we can pretty-print faithfully
     Paren(P<Ty>),
     /// Unused for now
index ca2be89def0f17c4176967c0d728de5556ee7e9d..6ba3b92483fddd8ad617a677fcece75f1f5da94a 100644 (file)
@@ -633,7 +633,7 @@ pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
 
     /// Returns a `Folder` for deeply expanding all macros in an AST node.
     pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
-        expand::MacroExpander::new(self)
+        expand::MacroExpander::new(self, false, false)
     }
 
     pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree])
index 5293d2ab0001a5309587f1115481f6ceb1aeeb9a..031d9a2d3f46e781debb012b0325b787345ddcfb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ast::{Block, Crate, Ident, Mac_, Name, PatKind};
+use ast::{Block, Crate, Ident, Mac_, PatKind};
 use ast::{MacStmtStyle, Stmt, StmtKind, ItemKind};
 use ast;
 use ext::hygiene::Mark;
@@ -29,8 +29,6 @@
 use visit::Visitor;
 use std_inject;
 
-use std::collections::HashSet;
-
 // A trait for AST nodes and AST node lists into which macro invocations may expand.
 trait MacroGenerable: Sized {
     // Expand the given MacResult using its appropriate `make_*` method.
@@ -218,8 +216,7 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
                     }
                 });
 
-                // DON'T mark before expansion.
-                fld.cx.insert_macro(ast::MacroDef {
+                let def = ast::MacroDef {
                     ident: ident,
                     id: ast::DUMMY_NODE_ID,
                     span: call_site,
@@ -229,10 +226,30 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
                     export: attr::contains_name(&attrs, "macro_export"),
                     allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
                     attrs: attrs,
-                });
+                };
 
-                // macro_rules! has a side effect but expands to nothing.
-                Some(Box::new(MacroScopePlaceholder))
+                fld.cx.insert_macro(def.clone());
+
+                // macro_rules! has a side effect, but expands to nothing.
+                // If keep_macs is true, expands to a MacEager::items instead.
+                if fld.keep_macs {
+                    Some(MacEager::items(SmallVector::one(P(ast::Item {
+                        ident: def.ident,
+                        attrs: def.attrs.clone(),
+                        id: ast::DUMMY_NODE_ID,
+                        node: ast::ItemKind::Mac(ast::Mac {
+                            span: def.span,
+                            node: ast::Mac_ {
+                                path: path.clone(),
+                                tts: def.body.clone(),
+                            }
+                        }),
+                        vis: ast::Visibility::Inherited,
+                        span: def.span,
+                    }))))
+                } else {
+                    Some(Box::new(MacroScopePlaceholder))
+                }
             }
 
             MultiDecorator(..) | MultiModifier(..) => {
@@ -260,7 +277,13 @@ fn mac_result<'a>(path: &ast::Path, ident: Option<Ident>, tts: Vec<TokenTree>, m
     let marked = expanded.fold_with(&mut Marker { mark: mark, expn_id: Some(fld.cx.backtrace()) });
     let configured = marked.fold_with(&mut fld.strip_unconfigured());
     fld.load_macros(&configured);
-    let fully_expanded = configured.fold_with(fld);
+
+    let fully_expanded = if fld.single_step {
+        configured
+    } else {
+        configured.fold_with(fld)
+    };
+
     fld.cx.bt_pop();
     fully_expanded
 }
@@ -490,11 +513,19 @@ pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
 /// A tree-folder that performs macro expansion
 pub struct MacroExpander<'a, 'b:'a> {
     pub cx: &'a mut ExtCtxt<'b>,
+    pub single_step: bool,
+    pub keep_macs: bool,
 }
 
 impl<'a, 'b> MacroExpander<'a, 'b> {
-    pub fn new(cx: &'a mut ExtCtxt<'b>) -> MacroExpander<'a, 'b> {
-        MacroExpander { cx: cx }
+    pub fn new(cx: &'a mut ExtCtxt<'b>,
+               single_step: bool,
+               keep_macs: bool) -> MacroExpander<'a, 'b> {
+        MacroExpander {
+            cx: cx,
+            single_step: single_step,
+            keep_macs: keep_macs
+        }
     }
 
     fn strip_unconfigured(&mut self) -> StripUnconfigured {
@@ -672,38 +703,45 @@ fn enable_pushpop_unsafe = pushpop_unsafe,
     }
 }
 
-pub fn expand_crate(mut cx: ExtCtxt,
+pub fn expand_crate(cx: &mut ExtCtxt,
                     user_exts: Vec<NamedSyntaxExtension>,
-                    mut c: Crate) -> (Crate, HashSet<Name>) {
+                    c: Crate) -> Crate {
+    let mut expander = MacroExpander::new(cx, false, false);
+    expand_crate_with_expander(&mut expander, user_exts, c)
+}
+
+// Expands crate using supplied MacroExpander - allows for
+// non-standard expansion behaviour (e.g. step-wise).
+pub fn expand_crate_with_expander(expander: &mut MacroExpander,
+                                  user_exts: Vec<NamedSyntaxExtension>,
+                                  mut c: Crate) -> Crate {
     if std_inject::no_core(&c) {
-        cx.crate_root = None;
+        expander.cx.crate_root = None;
     } else if std_inject::no_std(&c) {
-        cx.crate_root = Some("core");
+        expander.cx.crate_root = Some("core");
     } else {
-        cx.crate_root = Some("std");
+        expander.cx.crate_root = Some("std");
     }
-    let ret = {
-        let mut expander = MacroExpander::new(&mut cx);
 
-        for (name, extension) in user_exts {
-            expander.cx.syntax_env.insert(name, extension);
-        }
+    // User extensions must be added before expander.load_macros is called,
+    // so that macros from external crates shadow user defined extensions.
+    for (name, extension) in user_exts {
+        expander.cx.syntax_env.insert(name, extension);
+    }
 
-        let items = SmallVector::many(c.module.items);
-        expander.load_macros(&items);
-        c.module.items = items.into();
+    let items = SmallVector::many(c.module.items);
+    expander.load_macros(&items);
+    c.module.items = items.into();
 
-        let err_count = cx.parse_sess.span_diagnostic.err_count();
-        let mut ret = expander.fold_crate(c);
-        ret.exported_macros = expander.cx.exported_macros.clone();
+    let err_count = expander.cx.parse_sess.span_diagnostic.err_count();
+    let mut ret = expander.fold_crate(c);
+    ret.exported_macros = expander.cx.exported_macros.clone();
 
-        if cx.parse_sess.span_diagnostic.err_count() > err_count {
-            cx.parse_sess.span_diagnostic.abort_if_errors();
-        }
+    if expander.cx.parse_sess.span_diagnostic.err_count() > err_count {
+        expander.cx.parse_sess.span_diagnostic.abort_if_errors();
+    }
 
-        ret
-    };
-    return (ret, cx.syntax_env.names);
+    ret
 }
 
 // A Marker adds the given mark to the syntax context and
@@ -779,8 +817,8 @@ fn test_ecfg() -> ExpansionConfig<'static> {
             Vec::new(), &sess).unwrap();
         // should fail:
         let mut loader = DummyMacroLoader;
-        let ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
-        expand_crate(ecx, vec![], crate_ast);
+        let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
+        expand_crate(&mut ecx, vec![], crate_ast);
     }
 
     // make sure that macros can't escape modules
@@ -794,8 +832,8 @@ fn test_ecfg() -> ExpansionConfig<'static> {
             src,
             Vec::new(), &sess).unwrap();
         let mut loader = DummyMacroLoader;
-        let ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
-        expand_crate(ecx, vec![], crate_ast);
+        let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
+        expand_crate(&mut ecx, vec![], crate_ast);
     }
 
     // macro_use modules should allow macros to escape
@@ -808,8 +846,8 @@ fn test_ecfg() -> ExpansionConfig<'static> {
             src,
             Vec::new(), &sess).unwrap();
         let mut loader = DummyMacroLoader;
-        let ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
-        expand_crate(ecx, vec![], crate_ast);
+        let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
+        expand_crate(&mut ecx, vec![], crate_ast);
     }
 
     fn expand_crate_str(crate_str: String) -> ast::Crate {
@@ -817,8 +855,8 @@ fn expand_crate_str(crate_str: String) -> ast::Crate {
         let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
         // the cfg argument actually does matter, here...
         let mut loader = DummyMacroLoader;
-        let ecx = ExtCtxt::new(&ps, vec![], test_ecfg(), &mut loader);
-        expand_crate(ecx, vec![], crate_ast).0
+        let mut ecx = ExtCtxt::new(&ps, vec![], test_ecfg(), &mut loader);
+        expand_crate(&mut ecx, vec![], crate_ast)
     }
 
     #[test] fn macro_tokens_should_match(){
index 813afb935762e9e7d9a40ac40e8ee6d6fb29882f..7db03e9a8634a9031cc16ecbf9d5b389506d2e8f 100644 (file)
@@ -79,7 +79,7 @@
 use self::TokenTreeOrTokenTreeVec::*;
 
 use ast;
-use ast::{Name, Ident};
+use ast::Ident;
 use syntax_pos::{self, BytePos, mk_sp, Span};
 use codemap::Spanned;
 use errors::FatalError;
@@ -202,9 +202,9 @@ pub enum NamedMatch {
 }
 
 pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
-            -> ParseResult<HashMap<Name, Rc<NamedMatch>>> {
+            -> ParseResult<HashMap<Ident, Rc<NamedMatch>>> {
     fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
-             ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize)
+             ret_val: &mut HashMap<Ident, Rc<NamedMatch>>, idx: &mut usize)
              -> Result<(), (syntax_pos::Span, String)> {
         match *m {
             TokenTree::Sequence(_, ref seq) => {
@@ -218,7 +218,7 @@ fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
                 }
             }
             TokenTree::Token(sp, MatchNt(bind_name, _)) => {
-                match ret_val.entry(bind_name.name) {
+                match ret_val.entry(bind_name) {
                     Vacant(spot) => {
                         spot.insert(res[*idx].clone());
                         *idx += 1;
@@ -257,7 +257,7 @@ pub enum ParseResult<T> {
     Error(syntax_pos::Span, String)
 }
 
-pub type NamedParseResult = ParseResult<HashMap<Name, Rc<NamedMatch>>>;
+pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
 pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;
 
 /// Perform a token equality check, ignoring syntax context (that is, an
index db12ef24f7149fd95fd3ab362af7606ff517793b..d197741e9a367bc39d6726cfafc850afe0def94e 100644 (file)
@@ -302,7 +302,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
     let mut valid = true;
 
     // Extract the arguments:
-    let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
+    let lhses = match **argument_map.get(&lhs_nm).unwrap() {
         MatchedSeq(ref s, _) => {
             s.iter().map(|m| match **m {
                 MatchedNonterminal(NtTT(ref tt)) => {
@@ -315,7 +315,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
         _ => cx.span_bug(def.span, "wrong-structured lhs")
     };
 
-    let rhses = match **argument_map.get(&rhs_nm.name).unwrap() {
+    let rhses = match **argument_map.get(&rhs_nm).unwrap() {
         MatchedSeq(ref s, _) => {
             s.iter().map(|m| match **m {
                 MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(),
index 29a300b172e7562972aa22a645dfbff63ee05999..939425378def699da15025a14cff36795f30c360 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 use self::LockstepIterSize::*;
 
-use ast::{Ident, Name};
+use ast::Ident;
 use syntax_pos::{Span, DUMMY_SP};
 use errors::{Handler, DiagnosticBuilder};
 use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
@@ -38,7 +38,7 @@ pub struct TtReader<'a> {
     /// the unzipped tree:
     stack: Vec<TtFrame>,
     /* for MBE-style macro transcription */
-    interpolations: HashMap<Name, Rc<NamedMatch>>,
+    interpolations: HashMap<Ident, Rc<NamedMatch>>,
     imported_from: Option<Ident>,
 
     // Some => return imported_from as the next token
@@ -57,7 +57,7 @@ pub struct TtReader<'a> {
 /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
 pub fn new_tt_reader(sp_diag: &Handler,
-                     interp: Option<HashMap<Name, Rc<NamedMatch>>>,
+                     interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
                      imported_from: Option<Ident>,
                      src: Vec<tokenstream::TokenTree>)
                      -> TtReader {
@@ -71,7 +71,7 @@ pub fn new_tt_reader(sp_diag: &Handler,
 /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
 pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler,
-                                   interp: Option<HashMap<Name, Rc<NamedMatch>>>,
+                                   interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
                                    imported_from: Option<Ident>,
                                    src: Vec<tokenstream::TokenTree>,
                                    desugar_doc_comments: bool)
@@ -119,7 +119,7 @@ fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<Name
 }
 
 fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> {
-    let matched_opt = r.interpolations.get(&name.name).cloned();
+    let matched_opt = r.interpolations.get(&name).cloned();
     matched_opt.map(|s| lookup_cur_matched_by_matched(r, s))
 }
 
index 29da0fb1a2735aa14c4ac71633ac9be97f9b9ebb..ad52184a6dcb0cd658cb607b31fc5a97352ad3b6 100644 (file)
@@ -277,7 +277,14 @@ pub fn new() -> Features {
     (active, cfg_target_has_atomic, "1.9.0", Some(32976)),
 
     // Allows `..` in tuple (struct) patterns
-    (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627))
+    (active, dotdot_in_tuple_patterns, "1.10.0", Some(33627)),
+
+    // Allows `impl Trait` in function return types.
+    (active, conservative_impl_trait, "1.12.0", Some(34511)),
+
+    // Allows tuple structs and variants in more contexts,
+    // Permits numeric fields in struct expressions and patterns.
+    (active, relaxed_adts, "1.12.0", Some(35626))
 );
 
 declare_features! (
@@ -952,6 +959,10 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
                 self.check_abi(bare_fn_ty.abi, ty.span);
             }
+            ast::TyKind::ImplTrait(..) => {
+                gate_feature_post!(&self, conservative_impl_trait, ty.span,
+                                   "`impl Trait` is experimental");
+            }
             _ => {}
         }
         visit::walk_ty(self, ty)
@@ -1015,9 +1026,8 @@ fn visit_pat(&mut self, pattern: &ast::Pat) {
             }
             PatKind::TupleStruct(_, ref fields, ddpos)
                     if ddpos.is_none() && fields.is_empty() => {
-                self.context.span_handler.struct_span_err(pattern.span,
-                                                          "nullary enum variants are written with \
-                                                           no trailing `( )`").emit();
+                gate_feature_post!(&self, relaxed_adts, pattern.span,
+                                   "empty tuple structs patterns are unstable");
             }
             _ => {}
         }
@@ -1100,6 +1110,19 @@ fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
         visit::walk_impl_item(self, ii);
     }
 
+    fn visit_variant_data(&mut self, vdata: &ast::VariantData, _: ast::Ident,
+                          _: &ast::Generics, _: NodeId, span: Span) {
+        if vdata.fields().is_empty() {
+            if vdata.is_tuple() {
+                gate_feature_post!(&self, relaxed_adts, span,
+                                   "empty tuple structs and enum variants are unstable, \
+                                    use unit structs and enum variants instead");
+            }
+        }
+
+        visit::walk_struct_def(self, vdata)
+    }
+
     fn visit_vis(&mut self, vis: &ast::Visibility) {
         let span = match *vis {
             ast::Visibility::Crate(span) => span,
index ac3d643b185cac725fd7139d14ae4541970a3be6..afc990f498e6f824d5502292a77a80f1ec18f778 100644 (file)
@@ -397,6 +397,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyKind::PolyTraitRef(bounds) => {
                 TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
             }
+            TyKind::ImplTrait(bounds) => {
+                TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+            }
             TyKind::Mac(mac) => {
                 TyKind::Mac(fld.fold_mac(mac))
             }
index 5ea1d6be9fec9903b3155b7faf60cafe2efe240d..9e9ea09646088bd2b2726eab8058939a45e6bc44 100644 (file)
@@ -1685,9 +1685,7 @@ mod tests {
     fn mk_sh(cm: Rc<CodeMap>) -> errors::Handler {
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
-                                                None,
-                                                Some(cm),
-                                                errors::snippet::FormatMode::EnvironmentSelected);
+                                                Some(cm));
         errors::Handler::with_emitter(true, false, Box::new(emitter))
     }
 
index 7b28952aff6b6576b740ab809ed75fd1a15e77a6..cd1fdcfe9d130ce94a4e428a9c6d1255222c8190 100644 (file)
@@ -51,7 +51,6 @@ impl ParseSess {
     pub fn new() -> ParseSess {
         let cm = Rc::new(CodeMap::new());
         let handler = Handler::with_tty_emitter(ColorConfig::Auto,
-                                                None,
                                                 true,
                                                 false,
                                                 Some(cm.clone()));
index c143e190c6fc16ce814c785d88aab8e0d5889974..e174f3ad08d6adb4ef916d5a9f85bdb1ac65a27b 100644 (file)
@@ -1051,7 +1051,7 @@ pub fn get_lifetime(&mut self) -> ast::Ident {
     pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
         /*
         Parses whatever can come after a `for` keyword in a type.
-        The `for` has already been consumed.
+        The `for` hasn't been consumed.
 
         Deprecated:
 
@@ -1091,6 +1091,23 @@ pub fn parse_for_in_type(&mut self) -> PResult<'a, TyKind> {
         }
     }
 
+    pub fn parse_impl_trait_type(&mut self) -> PResult<'a, TyKind> {
+        /*
+        Parses whatever can come after a `impl` keyword in a type.
+        The `impl` has already been consumed.
+        */
+
+        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Modified)?;
+
+        if !bounds.iter().any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) {
+            let last_span = self.last_span;
+            self.span_err(last_span, "at least one trait must be specified");
+        }
+
+        Ok(ast::TyKind::ImplTrait(bounds))
+    }
+
+
     pub fn parse_ty_path(&mut self) -> PResult<'a, TyKind> {
         Ok(TyKind::Path(None, self.parse_path(PathStyle::Type)?))
     }
@@ -1406,6 +1423,8 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
             self.parse_borrowed_pointee()?
         } else if self.check_keyword(keywords::For) {
             self.parse_for_in_type()?
+        } else if self.eat_keyword(keywords::Impl) {
+            self.parse_impl_trait_type()?
         } else if self.token_is_bare_fn_keyword() {
             // BARE FUNCTION
             self.parse_ty_bare_fn(Vec::new())?
@@ -1990,10 +2009,19 @@ pub fn parse_mutability(&mut self) -> PResult<'a, Mutability> {
         }
     }
 
+    pub fn parse_field_name(&mut self) -> PResult<'a, Ident> {
+        if let token::Literal(token::Integer(name), None) = self.token {
+            self.bump();
+            Ok(Ident::with_empty_ctxt(name))
+        } else {
+            self.parse_ident()
+        }
+    }
+
     /// Parse ident COLON expr
     pub fn parse_field(&mut self) -> PResult<'a, Field> {
         let lo = self.span.lo;
-        let i = self.parse_ident()?;
+        let i = self.parse_field_name()?;
         let hi = self.last_span.hi;
         self.expect(&token::Colon)?;
         let e = self.parse_expr()?;
@@ -3489,7 +3517,7 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPa
             // Check if a colon exists one ahead. This means we're parsing a fieldname.
             let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
                 // Parsing a pattern of the form "fieldname: pat"
-                let fieldname = self.parse_ident()?;
+                let fieldname = self.parse_field_name()?;
                 self.bump();
                 let pat = self.parse_pat()?;
                 hi = pat.span.hi;
@@ -3760,19 +3788,18 @@ fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
     }
 
     /// Parse a structure field
-    fn parse_name_and_ty(&mut self, pr: Visibility,
-                         attrs: Vec<Attribute> ) -> PResult<'a, StructField> {
-        let lo = match pr {
-            Visibility::Inherited => self.span.lo,
-            _ => self.last_span.lo,
-        };
+    fn parse_name_and_ty(&mut self,
+                         lo: BytePos,
+                         vis: Visibility,
+                         attrs: Vec<Attribute>)
+                         -> PResult<'a, StructField> {
         let name = self.parse_ident()?;
         self.expect(&token::Colon)?;
         let ty = self.parse_ty_sum()?;
         Ok(StructField {
             span: mk_sp(lo, self.last_span.hi),
             ident: Some(name),
-            vis: pr,
+            vis: vis,
             id: ast::DUMMY_NODE_ID,
             ty: ty,
             attrs: attrs,
@@ -5092,10 +5119,11 @@ pub fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
 
     /// Parse a structure field declaration
     pub fn parse_single_struct_field(&mut self,
+                                     lo: BytePos,
                                      vis: Visibility,
                                      attrs: Vec<Attribute> )
                                      -> PResult<'a, StructField> {
-        let a_var = self.parse_name_and_ty(vis, attrs)?;
+        let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
         match self.token {
             token::Comma => {
                 self.bump();
@@ -5116,8 +5144,9 @@ pub fn parse_single_struct_field(&mut self,
     /// Parse an element of a struct definition
     fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
         let attrs = self.parse_outer_attributes()?;
+        let lo = self.span.lo;
         let vis = self.parse_visibility(true)?;
-        self.parse_single_struct_field(vis, attrs)
+        self.parse_single_struct_field(lo, vis, attrs)
     }
 
     // If `allow_path` is false, just parse the `pub` in `pub(path)` (but still parse `pub(crate)`)
index a619da84b2d510529d679312641bf89b257b50e0..62e55eb78b72383eda8accaa5bbbec407af72564 100644 (file)
@@ -1018,6 +1018,9 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             ast::TyKind::PolyTraitRef(ref bounds) => {
                 try!(self.print_bounds("", &bounds[..]));
             }
+            ast::TyKind::ImplTrait(ref bounds) => {
+                try!(self.print_bounds("impl ", &bounds[..]));
+            }
             ast::TyKind::FixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
                 try!(self.print_type(&ty));
index 89ead21cc10cb2fda48f0f88258cee98e759244a..0171f24101aecd6565fa29655481cf5f928a63bd 100644 (file)
@@ -340,6 +340,11 @@ pub struct TokenStream {
     ts: InternalTS,
 }
 
+// This indicates the maximum size for a leaf in the concatenation algorithm.
+// If two leafs will be collectively smaller than this, they will be merged.
+// If a leaf is larger than this, it will be concatenated at the top.
+const LEAF_SIZE : usize = 32;
+
 // NB If Leaf access proves to be slow, inroducing a secondary Leaf without the bounds
 // for unsliced Leafs may lead to some performance improvemenet.
 #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
@@ -483,6 +488,37 @@ fn slice(&self, range: ops::Range<usize>) -> TokenStream {
             }
         }
     }
+
+    fn to_vec(&self) -> Vec<&TokenTree> {
+        let mut res = Vec::with_capacity(self.len());
+        fn traverse_and_append<'a>(res: &mut Vec<&'a TokenTree>, ts: &'a InternalTS) {
+            match *ts {
+                InternalTS::Empty(..) => {},
+                InternalTS::Leaf { ref tts, offset, len, .. } => {
+                    let mut to_app = tts[offset..offset + len].iter().collect();
+                    res.append(&mut to_app);
+                }
+                InternalTS::Node { ref left, ref right, .. } => {
+                    traverse_and_append(res, left);
+                    traverse_and_append(res, right);
+                }
+            }
+        }
+        traverse_and_append(&mut res, self);
+        res
+    }
+
+    fn to_tts(&self) -> Vec<TokenTree> {
+        self.to_vec().into_iter().cloned().collect::<Vec<TokenTree>>()
+    }
+
+    // Returns an internal node's children.
+    fn children(&self) -> Option<(Rc<InternalTS>, Rc<InternalTS>)> {
+        match *self {
+            InternalTS::Node { ref left, ref right, .. } => Some((left.clone(), right.clone())),
+            _ => None,
+        }
+    }
 }
 
 /// TokenStream operators include basic destructuring, boolean operations, `maybe_...`
@@ -496,14 +532,17 @@ fn slice(&self, range: ops::Range<usize>) -> TokenStream {
 ///
 ///    `maybe_path_prefix("a::b::c(a,b,c).foo()") -> (a::b::c, "(a,b,c).foo()")`
 impl TokenStream {
+    // Construct an empty node with a dummy span.
     pub fn mk_empty() -> TokenStream {
         TokenStream { ts: InternalTS::Empty(DUMMY_SP) }
     }
 
+    // Construct an empty node with the provided span.
     fn mk_spanned_empty(sp: Span) -> TokenStream {
         TokenStream { ts: InternalTS::Empty(sp) }
     }
 
+    // Construct a leaf node with a 0 offset and length equivalent to the input.
     fn mk_leaf(tts: Rc<Vec<TokenTree>>, sp: Span) -> TokenStream {
         let len = tts.len();
         TokenStream {
@@ -516,6 +555,7 @@ fn mk_leaf(tts: Rc<Vec<TokenTree>>, sp: Span) -> TokenStream {
         }
     }
 
+    // Construct a leaf node with the provided values.
     fn mk_sub_leaf(tts: Rc<Vec<TokenTree>>, offset: usize, len: usize, sp: Span) -> TokenStream {
         TokenStream {
             ts: InternalTS::Leaf {
@@ -527,6 +567,7 @@ fn mk_sub_leaf(tts: Rc<Vec<TokenTree>>, offset: usize, len: usize, sp: Span) ->
         }
     }
 
+    // Construct an internal node with the provided values.
     fn mk_int_node(left: Rc<InternalTS>,
                    right: Rc<InternalTS>,
                    len: usize,
@@ -561,11 +602,56 @@ pub fn respan(self, span: Span) -> TokenStream {
         }
     }
 
-    /// Concatenates two TokenStreams into a new TokenStream
+    /// Concatenates two TokenStreams into a new TokenStream.
     pub fn concat(left: TokenStream, right: TokenStream) -> TokenStream {
-        let new_len = left.len() + right.len();
-        let new_span = combine_spans(left.span(), right.span());
-        TokenStream::mk_int_node(Rc::new(left.ts), Rc::new(right.ts), new_len, new_span)
+        // This internal procedure performs 'aggressive compacting' during concatenation as
+        // follows:
+        // - If the nodes' combined total total length is less than 32, we copy both of
+        //   them into a new vector and build a new leaf node.
+        // - If one node is an internal node and the other is a 'small' leaf (length<32),
+        //   we recur down the internal node on the appropriate side.
+        // - Otherwise, we construct a new internal node that points to them as left and
+        // right.
+        fn concat_internal(left: Rc<InternalTS>, right: Rc<InternalTS>) -> TokenStream {
+            let llen = left.len();
+            let rlen = right.len();
+            let len = llen + rlen;
+            let span = combine_spans(left.span(), right.span());
+            if len <= LEAF_SIZE {
+                let mut new_vec = left.to_tts();
+                let mut rvec = right.to_tts();
+                new_vec.append(&mut rvec);
+                return TokenStream::mk_leaf(Rc::new(new_vec), span);
+            }
+
+            match (left.children(), right.children()) {
+                (Some((lleft, lright)), None) => {
+                    if rlen <= LEAF_SIZE  {
+                        let new_right = concat_internal(lright, right);
+                        TokenStream::mk_int_node(lleft, Rc::new(new_right.ts), len, span)
+                    } else {
+                       TokenStream::mk_int_node(left, right, len, span)
+                    }
+                }
+                (None, Some((rleft, rright))) => {
+                    if rlen <= LEAF_SIZE  {
+                        let new_left = concat_internal(left, rleft);
+                        TokenStream::mk_int_node(Rc::new(new_left.ts), rright, len, span)
+                    } else {
+                       TokenStream::mk_int_node(left, right, len, span)
+                    }
+                }
+                (_, _) => TokenStream::mk_int_node(left, right, len, span),
+            }
+        }
+
+        if left.is_empty() {
+            right
+        } else if right.is_empty() {
+            left
+        } else {
+            concat_internal(Rc::new(left.ts), Rc::new(right.ts))
+        }
     }
 
     /// Indicate if the TokenStream is empty.
@@ -580,27 +666,13 @@ pub fn len(&self) -> usize {
 
     /// Convert a TokenStream into a vector of borrowed TokenTrees.
     pub fn to_vec(&self) -> Vec<&TokenTree> {
-        fn internal_to_vec(ts: &InternalTS) -> Vec<&TokenTree> {
-            match *ts {
-                InternalTS::Empty(..) => Vec::new(),
-                InternalTS::Leaf { ref tts, offset, len, .. } => {
-                    tts[offset..offset + len].iter().collect()
-                }
-                InternalTS::Node { ref left, ref right, .. } => {
-                    let mut v1 = internal_to_vec(left);
-                    let mut v2 = internal_to_vec(right);
-                    v1.append(&mut v2);
-                    v1
-                }
-            }
-        }
-        internal_to_vec(&self.ts)
+        self.ts.to_vec()
     }
 
     /// Convert a TokenStream into a vector of TokenTrees (by cloning the TokenTrees).
     /// (This operation is an O(n) deep copy of the underlying structure.)
     pub fn to_tts(&self) -> Vec<TokenTree> {
-        self.to_vec().into_iter().cloned().collect::<Vec<TokenTree>>()
+        self.ts.to_tts()
     }
 
     /// Return the TokenStream's span.
index 1fc4e54d21807c26145f6d10e98e7d85f34eed15..6d3cdbdc6da7cc414e63de5ef5bcf4f0023ee849 100644 (file)
@@ -343,6 +343,9 @@ pub fn walk_ty<V: Visitor>(visitor: &mut V, typ: &Ty) {
         TyKind::PolyTraitRef(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
+        TyKind::ImplTrait(ref bounds) => {
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+        }
         TyKind::Typeof(ref expression) => {
             visitor.visit_expr(expression)
         }
index 248f6f98650a526778ae67e84d66f4eb2d3bea6b..850127d9f29505f72f0998f50e584346fd026dbd 100644 (file)
@@ -42,6 +42,7 @@
 #![feature(staged_api)]
 #![feature(question_mark)]
 #![feature(panic_unwind)]
+#![feature(mpsc_recv_timeout)]
 
 extern crate getopts;
 extern crate term;
@@ -73,6 +74,8 @@
 use std::thread;
 use std::time::{Instant, Duration};
 
+const TEST_WARN_TIMEOUT_S: u64 = 60;
+
 // to be used by rustc to compile tests in libtest
 pub mod test {
     pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed,
@@ -300,6 +303,7 @@ pub struct TestOpts {
     pub nocapture: bool,
     pub color: ColorConfig,
     pub quiet: bool,
+    pub test_threads: Option<usize>,
 }
 
 impl TestOpts {
@@ -314,6 +318,7 @@ fn new() -> TestOpts {
             nocapture: false,
             color: AutoColor,
             quiet: false,
+            test_threads: None,
         }
     }
 }
@@ -331,6 +336,8 @@ fn optgroups() -> Vec<getopts::OptGroup> {
                           of stdout", "PATH"),
       getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
                                          task, allow printing directly"),
+      getopts::optopt("", "test-threads", "Number of threads used for running tests \
+                                           in parallel", "n_threads"),
       getopts::optflag("q", "quiet", "Display one character per test instead of one line"),
       getopts::optopt("", "color", "Configure coloring of output:
             auto   = colorize if stdout is a tty and tests are run on serially (default);
@@ -346,7 +353,8 @@ fn usage(binary: &str) {
 tests whose names contain the filter are run.
 
 By default, all tests are run in parallel. This can be altered with the
-RUST_TEST_THREADS environment variable when running tests (set it to 1).
+--test-threads flag or the RUST_TEST_THREADS environment variable when running
+tests (set it to 1).
 
 All tests have their standard output and standard error captured by default.
 This can be overridden with the --nocapture flag or setting RUST_TEST_NOCAPTURE
@@ -405,6 +413,18 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         };
     }
 
+    let test_threads = match matches.opt_str("test-threads") {
+        Some(n_str) =>
+            match n_str.parse::<usize>() {
+                Ok(n) => Some(n),
+                Err(e) =>
+                    return Some(Err(format!("argument for --test-threads must be a number > 0 \
+                                             (error: {})", e)))
+            },
+        None =>
+            None,
+    };
+
     let color = match matches.opt_str("color").as_ref().map(|s| &**s) {
         Some("auto") | None => AutoColor,
         Some("always") => AlwaysColor,
@@ -426,6 +446,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
         nocapture: nocapture,
         color: color,
         quiet: quiet,
+        test_threads: test_threads,
     };
 
     Some(Ok(test_opts))
@@ -592,6 +613,12 @@ pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> {
         }
     }
 
+    pub fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> {
+        self.write_plain(&format!("test {} has been running for over {} seconds\n",
+                                  desc.name,
+                                  TEST_WARN_TIMEOUT_S))
+    }
+
     pub fn write_log(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> {
         match self.log_out {
             None => Ok(()),
@@ -709,6 +736,7 @@ fn callback<T: Write>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::Re
         match (*event).clone() {
             TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
             TeWait(ref test, padding) => st.write_test_start(test, padding),
+            TeTimeout(ref test) => st.write_timeout(test),
             TeResult(test, result, stdout) => {
                 st.write_log(&test, &result)?;
                 st.write_result(&result)?;
@@ -830,6 +858,7 @@ enum TestEvent {
     TeFiltered(Vec<TestDesc>),
     TeWait(TestDesc, NamePadding),
     TeResult(TestDesc, TestResult, Vec<u8>),
+    TeTimeout(TestDesc),
 }
 
 pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
@@ -838,6 +867,9 @@ enum TestEvent {
 fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
     where F: FnMut(TestEvent) -> io::Result<()>
 {
+    use std::collections::HashMap;
+    use std::sync::mpsc::RecvTimeoutError;
+
     let mut filtered_tests = filter_tests(opts, tests);
     if !opts.bench_benchmarks {
         filtered_tests = convert_benchmarks_to_tests(filtered_tests);
@@ -857,9 +889,10 @@ fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) ->
             }
         });
 
-    // It's tempting to just spawn all the tests at once, but since we have
-    // many tests that run in other processes we would be making a big mess.
-    let concurrency = get_concurrency();
+    let concurrency = match opts.test_threads {
+        Some(n) => n,
+        None => get_concurrency(),
+    };
 
     let mut remaining = filtered_tests;
     remaining.reverse();
@@ -867,6 +900,29 @@ fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) ->
 
     let (tx, rx) = channel::<MonitorMsg>();
 
+    let mut running_tests: HashMap<TestDesc, Instant> = HashMap::new();
+
+    fn get_timed_out_tests(running_tests: &mut HashMap<TestDesc, Instant>) -> Vec<TestDesc> {
+        let now = Instant::now();
+        let timed_out = running_tests.iter()
+            .filter_map(|(desc, timeout)| if &now >= timeout { Some(desc.clone())} else { None })
+            .collect();
+        for test in &timed_out {
+            running_tests.remove(test);
+        }
+        timed_out
+    };
+
+    fn calc_timeout(running_tests: &HashMap<TestDesc, Instant>) -> Option<Duration> {
+        running_tests.values().min().map(|next_timeout| {
+            let now = Instant::now();
+            if *next_timeout >= now {
+                *next_timeout - now
+            } else {
+                Duration::new(0, 0)
+            }})
+    };
+
     while pending > 0 || !remaining.is_empty() {
         while pending < concurrency && !remaining.is_empty() {
             let test = remaining.pop().unwrap();
@@ -876,11 +932,31 @@ fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) ->
                 // that hang forever.
                 callback(TeWait(test.desc.clone(), test.testfn.padding()))?;
             }
+            let timeout = Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S);
+            running_tests.insert(test.desc.clone(), timeout);
             run_test(opts, !opts.run_tests, test, tx.clone());
             pending += 1;
         }
 
-        let (desc, result, stdout) = rx.recv().unwrap();
+        let mut res;
+        loop {
+            if let Some(timeout) = calc_timeout(&running_tests) {
+                res = rx.recv_timeout(timeout);
+                for test in get_timed_out_tests(&mut running_tests) {
+                    callback(TeTimeout(test))?;
+                }
+                if res != Err(RecvTimeoutError::Timeout) {
+                    break;
+                }
+            } else {
+                res = rx.recv().map_err(|_| RecvTimeoutError::Disconnected);
+                break;
+            }
+        }
+
+        let (desc, result, stdout) = res.unwrap();
+        running_tests.remove(&desc);
+
         if concurrency != 1 {
             callback(TeWait(desc.clone(), PadNone))?;
         }
index d1cc48989b13780f21c408fef17dceb104a09c9d..786aad117be48547f4ca50fae84c4879fa992d4d 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d
+Subproject commit 786aad117be48547f4ca50fae84c4879fa992d4d
index 3a20bb2714ece5b7967f9ee0eb698cd46d3a11dd..0555a96ff24ce900d6b6f53f56021a6c02496a91 100644 (file)
@@ -226,6 +226,58 @@ from_rust(LLVMRustCodeGenOptLevel level)
   }
 }
 
+#if LLVM_RUSTLLVM
+/// getLongestEntryLength - Return the length of the longest entry in the table.
+///
+static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
+  size_t MaxLen = 0;
+  for (auto &I : Table)
+    MaxLen = std::max(MaxLen, std::strlen(I.Key));
+  return MaxLen;
+}
+
+extern "C" void
+LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
+    const TargetMachine *Target = unwrap(TM);
+    const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
+    const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
+    unsigned MaxCPULen = getLongestEntryLength(CPUTable);
+
+    printf("Available CPUs for this target:\n");
+    for (auto &CPU : CPUTable)
+        printf("    %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
+    printf("\n");
+}
+
+extern "C" void
+LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
+    const TargetMachine *Target = unwrap(TM);
+    const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
+    const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
+    unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
+
+    printf("Available features for this target:\n");
+    for (auto &Feature : FeatTable)
+        printf("    %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
+    printf("\n");
+
+    printf("Use +feature to enable a feature, or -feature to disable it.\n"
+            "For example, rustc -C -target-cpu=mycpu -C target-feature=+feature1,-feature2\n\n");
+}
+
+#else
+
+extern "C" void
+LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
+    printf("Target CPU help is not supported by this LLVM version.\n\n");
+}
+
+extern "C" void
+LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
+    printf("Target features help is not supported by this LLVM version.\n\n");
+}
+#endif
+
 extern "C" LLVMTargetMachineRef
 LLVMRustCreateTargetMachine(const char *triple,
                             const char *cpu,
index e871763a48dc3fafb34f81ee2d10ad2c6cb4402c..378810a8b89fc9f0caad49ae7101c62d4241e8a0 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2016-07-25b
+2016-08-07
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
new file mode 100644 (file)
index 0000000..b40bb7f
--- /dev/null
@@ -0,0 +1,93 @@
+// 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-tidy-linelength
+
+// We specify -Z incremental here because we want to test the partitioning for
+// incremental compilation
+// compile-flags:-Zprint-trans-items=lazy -Zincremental=tmp/partitioning-tests/vtable-through-const
+
+// This test case makes sure, that references made through constants are
+// recorded properly in the InliningMap.
+
+mod mod1 {
+    pub trait Trait1 {
+        fn do_something(&self) {}
+        fn do_something_else(&self) {}
+    }
+
+    impl Trait1 for u32 {}
+
+    pub trait Trait1Gen<T> {
+        fn do_something(&self, x: T) -> T;
+        fn do_something_else(&self, x: T) -> T;
+    }
+
+    impl<T> Trait1Gen<T> for u32 {
+        fn do_something(&self, x: T) -> T { x }
+        fn do_something_else(&self, x: T) -> T { x }
+    }
+
+    fn id<T>(x: T) -> T { x }
+
+    // These are referenced, so they produce trans-items (see main())
+    pub const TRAIT1_REF: &'static Trait1 = &0u32 as &Trait1;
+    pub const TRAIT1_GEN_REF: &'static Trait1Gen<u8> = &0u32 as &Trait1Gen<u8>;
+    pub const ID_CHAR: fn(char) -> char = id::<char>;
+
+
+
+    pub trait Trait2 {
+        fn do_something(&self) {}
+        fn do_something_else(&self) {}
+    }
+
+    impl Trait2 for u32 {}
+
+    pub trait Trait2Gen<T> {
+        fn do_something(&self, x: T) -> T;
+        fn do_something_else(&self, x: T) -> T;
+    }
+
+    impl<T> Trait2Gen<T> for u32 {
+        fn do_something(&self, x: T) -> T { x }
+        fn do_something_else(&self, x: T) -> T { x }
+    }
+
+    // These are not referenced, so they do not produce trans-items
+    pub const TRAIT2_REF: &'static Trait2 = &0u32 as &Trait2;
+    pub const TRAIT2_GEN_REF: &'static Trait2Gen<u8> = &0u32 as &Trait2Gen<u8>;
+    pub const ID_I64: fn(i64) -> i64 = id::<i64>;
+}
+
+//~ TRANS_ITEM fn vtable_through_const::main[0] @@ vtable_through_const[External]
+fn main() {
+
+    // Since Trait1::do_something() is instantiated via its default implementation,
+    // it is considered a generic and is instantiated here only because it is
+    // referenced in this module.
+    //~ TRANS_ITEM fn vtable_through_const::mod1[0]::Trait1[0]::do_something_else[0]<u32> @@ vtable_through_const[Internal]
+
+    // Although it is never used, Trait1::do_something_else() has to be
+    // instantiated locally here too, otherwise the <&u32 as &Trait1> vtable
+    // could not be fully constructed.
+    //~ TRANS_ITEM fn vtable_through_const::mod1[0]::Trait1[0]::do_something[0]<u32> @@ vtable_through_const[Internal]
+    mod1::TRAIT1_REF.do_something();
+
+    // Same as above
+    //~ TRANS_ITEM fn vtable_through_const::mod1[0]::{{impl}}[1]::do_something[0]<u8> @@ vtable_through_const[Internal]
+    //~ TRANS_ITEM fn vtable_through_const::mod1[0]::{{impl}}[1]::do_something_else[0]<u8> @@ vtable_through_const[Internal]
+    mod1::TRAIT1_GEN_REF.do_something(0u8);
+
+    //~ TRANS_ITEM fn vtable_through_const::mod1[0]::id[0]<char> @@ vtable_through_const[Internal]
+    mod1::ID_CHAR('x');
+}
+
+//~ TRANS_ITEM drop-glue i8
index bfc0f1afe3ad3d5bca94df7233a60cfeecd9ed9c..4be115b8afdace66329a8d4c5a97b31f32eb3346 100644 (file)
 fn main() {
     let x = Some("s".to_string());
     match x {
-        op_string @ Some(s) => {}, //~ ERROR E0007
-                                   //~| ERROR E0303
+        op_string @ Some(s) => {},
+        //~^ ERROR E0007
+        //~| NOTE binds an already bound by-move value by moving it
+        //~| ERROR E0303
         None => {},
     }
 }
index 97dd0f368bd12fd954cf8256b0d624e2cda35702..20cc1cbd2232df233d3e92734901b112247bc1a5 100644 (file)
@@ -10,7 +10,9 @@
 
 fn main() {
     match Some("hi".to_string()) {
-        Some(s) if s.len() == 0 => {}, //~ ERROR E0008
+        Some(s) if s.len() == 0 => {},
+        //~^ ERROR E0008
+        //~| NOTE moves value into pattern guard
         _ => {},
     }
 }
index 13f2c23d8c4a9912624fc6a67505262d3a963769..1223a01cbcb6f29fc0d14d04215597b02c5cd58b 100644 (file)
 const C: i32 = 2;
 
 const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+                                     //~| NOTE constants require immutable values
                                      //~| ERROR E0017
+                                     //~| NOTE constants require immutable values
 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+                                              //~| NOTE statics require immutable values
                                               //~| ERROR E0017
+                                              //~| NOTE statics require immutable values
                                               //~| ERROR E0388
 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+                                             //~| NOTE statics require immutable values
                                              //~| ERROR E0017
-
+                                             //~| NOTE statics require immutable values
 fn main() {}
index 05f126baf9a7036764b1f1ea4a6fc72969d18831..c3623e3177b56207606de2bf18b45f8e38d45aa3 100644 (file)
@@ -13,10 +13,15 @@ enum Fruit {
     Pear(u32),
 }
 
+
 fn main() {
     let x = Fruit::Apple(String::new(), String::new());
     match x {
         Fruit::Apple(a) => {}, //~ ERROR E0023
+                               //~| NOTE expected 2 fields, found 1
         Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
+                                     //~| NOTE expected 2 fields, found 3
+        Fruit::Pear(1, 2) => {}, //~ ERROR E0023
+                                 //~| NOTE expected 1 field, found 2
     }
 }
index 359c2a822a243d40fca9275d401f0bff8eace55a..ac609da4cbdde72a105871b8e8e74a1d6edf4845 100644 (file)
@@ -16,6 +16,8 @@ struct Thing {
 fn main() {
     let thing = Thing { x: 0, y: 0 };
     match thing {
-        Thing { x, y, z } => {} //~ ERROR E0026
+        Thing { x, y, z } => {}
+        //~^ ERROR struct `Thing` does not have a field named `z` [E0026]
+        //~| NOTE struct `Thing` does not have field `z`
     }
 }
index 26d2f339763aa6c91639202dd6d118b8c0d14f23..6cf3f1ebf19e4526d1c8b6b37fe6af2a9b4bd894 100644 (file)
@@ -12,7 +12,10 @@ trait Trait {
     fn foo(&self) -> Self;
 }
 
-fn call_foo(x: Box<Trait>) { //~ ERROR E0038
+fn call_foo(x: Box<Trait>) {
+    //~^ ERROR E0038
+    //~| NOTE the trait `Trait` cannot be made into an object
+    //~| NOTE method `foo` references the `Self` type in its arguments or return type
     let y = x.foo();
 }
 
index 2a731596b4be8005c57ac9ba2ecdee156654b9d4..a3fea8e0db299b2a810f6b1790221e340d6b691d 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern "Rust" { fn foo(x: u8, ...); } //~ ERROR E0045
+extern "Rust" { fn foo(x: u8, ...); }   //~ ERROR E0045
+                                        //~| NOTE variadics require C calling conventions
 
 fn main() {
 }
index 6f0e55efffc921dc31a991972b007f515b5f46de..c13ba7bf136712efd1cb50732de9e8a36b81688e 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-enum Foo { FirstValue(i32) }
+enum Foo {}
 
 fn main() {
-    let u = Foo::FirstValue { value: 0 };
-    //~^ ERROR `Foo::FirstValue` does not name a struct or a struct variant [E0071]
+    let u = Foo { value: 0 };
+    //~^ ERROR `Foo` does not name a struct or a struct variant [E0071]
     //~| NOTE not a struct
 
     let t = u32 { value: 4 };
index 2f96ba1046d7487c1116e86621f8987e8e364293..e6de7921b30363a648723d5aaf14c71db276c9ef 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 struct ListNode { //~ ERROR E0072
+                  //~| NOTE recursive type has infinite size
     head: u8,
     tail: Option<ListNode>,
 }
index b63265564b334674ff9a86000f065cc92a10aef7..9911e093a898036d5fcae44fe656f6add46c2225 100644 (file)
@@ -9,8 +9,10 @@
 // except according to those terms.
 
 enum Enum {
-    P = 3,
-    X = 3, //~ ERROR E0081
+    P = 3, //~ NOTE first use of `3isize`
+    X = 3,
+    //~^ ERROR discriminant value `3isize` already exists
+    //~| NOTE enum already has `3isize`
     Y = 5
 }
 
index ec559fc8389d25dd99d8865a8eb8ff12f9f49b79..437ad3698a20664a2f4792e0e28cb67e97a5fc2e 100644 (file)
@@ -12,4 +12,5 @@ fn foo<T>() {}
 
 fn main() {
     foo::<f64, bool>(); //~ ERROR E0087
+    //~^ NOTE expected
 }
index da988dbf819ac8c681a28d3bd4341c112c8e7d34..0d6c246de2a0e79f2c6e0f6d148165684820d556 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 
 type Foo<T> = u32; //~ ERROR E0091
+                   //~| NOTE unused type parameter
 type Foo2<A, B> = Box<A>; //~ ERROR E0091
+                          //~| NOTE unused type parameter
 
 fn main() {
 }
index b08164ac06d4235c0e95907f583406db6118efe9..c8bb31a7857ee1495ad17512b0af982cba14cac1 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(intrinsics)]
 extern "rust-intrinsic" {
     fn atomic_foo(); //~ ERROR E0092
-}
+}                    //~| NOTE unrecognized atomic operation
 
 fn main() {
 }
index 37071012825ec9b67f9984e7f202300f80eee315..f5829b93859412c007daad508a71767652eb9140 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 struct Foo<T=U, U=()> { //~ ERROR E0128
+                        //~| NOTE defaulted type parameters cannot be forward declared
     field1: T,
     field2: U,
 }
index ef5961e133894d37c90103238f9cbb280d64fd58..e9e027fd1dc1972aea32aabfc7005274dd2c4f76 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 
 extern {
-    fn foo((a, b): (u32, u32)); //~ ERROR E0130
+    fn foo((a, b): (u32, u32));
+    //~^ ERROR E0130
+    //~| NOTE pattern not allowed in foreign function
 }
 
 fn main() {
index 630ee851d0af006e6d320ee229cd3c5d37fa4952..b8a4476fc59671b2b5e4f6b769ce5bad5ad9bfd9 100644 (file)
@@ -11,5 +11,7 @@
 unsafe fn f() { return; }
 
 fn main() {
-    f(); //~ ERROR E0133
+    f();
+    //~^ ERROR E0133
+    //~| NOTE unsafe call requires unsafe function or block
 }
index e13b0af6f7977436c43684f1ee62b89eb1582cea..0b63d7c3f85c71873a0a405258513b483ac72483 100644 (file)
@@ -13,6 +13,7 @@
 fn main() {
     let irr = Irrefutable(0);
     if let Irrefutable(x) = irr { //~ ERROR E0162
+        //~| NOTE irrefutable pattern
         println!("{}", x);
     }
 }
index 489ebb033f84e8133c98961750ff7530ba4878dc..dcfe441ab0d00ca0287fde3100f1a3ea3cd4b19c 100644 (file)
@@ -13,6 +13,7 @@ trait Trait {
 }
 
 type Foo = Trait; //~ ERROR E0191
+                  //~| NOTE missing associated type `Bar` value
 
 fn main() {
 }
index 37ac57af524a6d1f5ba06d7752019b94e5e613e7..c73e7534301055dd55729582ad1229c5646e1be5 100644 (file)
@@ -14,11 +14,11 @@ enum Foo {
 }
 
 impl Copy for Foo { }
-//~^ ERROR E0205
+//~^ ERROR the trait `Copy` may not be implemented for this type
 //~| NOTE variant `Bar` does not implement `Copy`
 
 #[derive(Copy)]
-//~^ ERROR E0205
+//~^ ERROR the trait `Copy` may not be implemented for this type
 //~| NOTE variant `Bar` does not implement `Copy`
 //~| NOTE in this expansion of #[derive(Copy)]
 enum Foo2<'a> {
index 59609345ee5235f65ea67e669a3daa4d5489c37a..e9c3cb72c11b07a7075c5a905ea4f120b2a77a0b 100644 (file)
@@ -9,5 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let v: Vec(&str) = vec!["foo"]; //~ ERROR E0214
+    let v: Vec(&str) = vec!["foo"];
+    //~^ ERROR E0214
+    //~| NOTE only traits may use parentheses
 }
index fdfd41a456bf601316e05cf46fc78eb086697ab8..25568a323e161d42a1a6a8d219c76dae51f345dd 100644 (file)
@@ -13,6 +13,6 @@ enum Foo {
 }
 
 fn do_something(x: Foo::Bar) { } //~ ERROR E0248
-
+                //~| NOTE value used as a type
 fn main() {
 }
index 09f654c368c62471c5224bd25fb4741afb4eb48c..11a8ff443a8459d452a2d53b89c633b0a4302e7b 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { } //~ ERROR E0263
+fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) {
+    //~^ ERROR E0263
+    //~| NOTE declared twice
+    //~| NOTE previous declaration here
+}
 
 fn main() {}
diff --git a/src/test/compile-fail/E0365.rs b/src/test/compile-fail/E0365.rs
new file mode 100644 (file)
index 0000000..7b0fbcc
--- /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.
+
+mod foo {
+    pub const X: u32 = 1;
+}
+
+pub use foo as foo2; //~ ERROR E0365
+
+fn main() {}
diff --git a/src/test/compile-fail/E0370.rs b/src/test/compile-fail/E0370.rs
new file mode 100644 (file)
index 0000000..cafe26c
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+#![allow(dead_code)]
+
+#[deny(overflowing_literals)]
+#[repr(i64)]
+enum Foo {
+    X = 0x7fffffffffffffff,
+    Y, //~ ERROR E0370
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0374.rs b/src/test/compile-fail/E0374.rs
new file mode 100644 (file)
index 0000000..6c4782d
--- /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.
+
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: i32,
+}
+
+impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> //~ ERROR E0374
+    where T: CoerceUnsized<U> {}
+
+fn main() {}
diff --git a/src/test/compile-fail/E0375.rs b/src/test/compile-fail/E0375.rs
new file mode 100644 (file)
index 0000000..c6db7b8
--- /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.
+
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized, U: ?Sized> {
+    a: i32,
+    b: T,
+    c: U,
+}
+
+impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} //~ ERROR E0375
+
+fn main() {}
diff --git a/src/test/compile-fail/E0376.rs b/src/test/compile-fail/E0376.rs
new file mode 100644 (file)
index 0000000..65be358
--- /dev/null
@@ -0,0 +1,20 @@
+// 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(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: T,
+}
+
+impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
+
+fn main() {}
diff --git a/src/test/compile-fail/E0388.rs b/src/test/compile-fail/E0388.rs
new file mode 100644 (file)
index 0000000..13f2c23
--- /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.
+
+static X: i32 = 1;
+const C: i32 = 2;
+
+const CR: &'static mut i32 = &mut C; //~ ERROR E0017
+                                     //~| ERROR E0017
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
+                                              //~| ERROR E0017
+                                              //~| ERROR E0388
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0017
+                                             //~| ERROR E0017
+
+fn main() {}
diff --git a/src/test/compile-fail/E0389.rs b/src/test/compile-fail/E0389.rs
new file mode 100644 (file)
index 0000000..445831b
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; //~ ERROR E0389
+    println!("{}", fancy_ref.num);
+}
diff --git a/src/test/compile-fail/E0390.rs b/src/test/compile-fail/E0390.rs
new file mode 100644 (file)
index 0000000..cd530db
--- /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.
+
+struct Foo {
+    x: i32
+}
+
+impl *mut Foo {} //~ ERROR E0390
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0392.rs b/src/test/compile-fail/E0392.rs
new file mode 100644 (file)
index 0000000..4c3efcf
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+enum Foo<T> { Bar } //~ ERROR E0392
+
+fn main() {
+}
diff --git a/src/test/compile-fail/E0393.rs b/src/test/compile-fail/E0393.rs
new file mode 100644 (file)
index 0000000..1b89555
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+trait A<T=Self> {}
+
+fn together_we_will_rule_the_galaxy(son: &A) {} //~ ERROR E0393
+
+fn main() {
+}
index c1c72a5519bf10b5d81c389fad5481c8ee432db7..0541faa021356f0a0719423833dde86ee85b24c3 100644 (file)
           target_arch = "aarch64"))]
 pub fn main() {
     let x: isize;
-    x = 1; //~ NOTE prior assignment occurs here
+    x = 1; //~ NOTE first assignment
     foo(x);
     unsafe {
         asm!("mov $1, $0" : "=r"(x) : "r"(5));
         //~^ ERROR re-assignment of immutable variable `x`
+        //~| NOTE re-assignment of immutable
         //~| NOTE in this expansion of asm!
     }
     foo(x);
index 540272a8e2c58b511542504a666fdf20fb4be2c1..9a5d6289b589ecd3b5d556ffe3dff14b8d6b3f5c 100644 (file)
 
 fn test() {
     let v: isize;
-    v = 1; //~ NOTE prior assignment occurs here
+    v = 1; //~ NOTE first assignment
     println!("v={}", v);
     v = 2; //~ ERROR re-assignment of immutable variable
+           //~| NOTE re-assignment of immutable
     println!("v={}", v);
 }
 
index 95508a31044b87797dff021bc5a6a07b23cd2ff9..b3776091682da18b3f149c01f8786e830657df6d 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(associated_consts)]
 
 trait Foo {
-    const BAR: u32;
+    const BAR: u32; //~ NOTE original trait requirement
 }
 
 struct SignedBar;
@@ -19,7 +19,7 @@ trait Foo {
 impl Foo for SignedBar {
     const BAR: i32 = -1;
     //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
-    //~| expected u32, found i32
+    //~| NOTE expected u32, found i32
 }
 
 fn main() {}
index 2b34fcab24c04728918afa4130549f1f2b393a0c..a2a11c62bb83245a851c7158f7dea07901bcb2b9 100644 (file)
@@ -28,6 +28,7 @@ pub trait BoxCar : Box + Vehicle {
 
 fn dent<C:BoxCar>(c: C, color: C::Color) {
     //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+    //~| NOTE ambiguous associated type `Color`
     //~| NOTE could derive from `Vehicle`
     //~| NOTE could derive from `Box`
 }
@@ -35,12 +36,15 @@ fn dent<C:BoxCar>(c: C, color: C::Color) {
 fn dent_object<COLOR>(c: BoxCar<Color=COLOR>) {
     //~^ ERROR ambiguous associated type
     //~| ERROR the value of the associated type `Color` (from the trait `Vehicle`) must be specified
+    //~| NOTE ambiguous associated type `Color`
     //~| NOTE could derive from `Vehicle`
     //~| NOTE could derive from `Box`
+    //~| NOTE missing associated type `Color` value
 }
 
 fn paint<C:BoxCar>(c: C, d: C::Color) {
     //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+    //~| NOTE ambiguous associated type `Color`
     //~| NOTE could derive from `Vehicle`
     //~| NOTE could derive from `Box`
 }
index 22f65c2b0d8f86470130de485c70d5f33d514e99..dcbb0ce178bd8c487df447ee0124c0e535de5a6a 100644 (file)
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(relaxed_adts)]
+
 pub struct XEmpty1 {}
 pub struct XEmpty2;
+pub struct XEmpty6();
 
 pub enum XE {
     XEmpty3 {},
     XEmpty4,
+    XEmpty5(),
 }
index 7d79c48c06ae2a789da006b3ebd8bbb5198cdefd..6a9d8db9654ac9d70e6ff0064f836daf732fcc78 100644 (file)
@@ -29,6 +29,7 @@ fn main() {
 
     let mut map = HashMap::new();
     //~^ ERROR E0433
+    //~| NOTE Use of undeclared type or module `HashMap`
 
     for line in input.lines() {
         let line = line.unwrap();
index 0522a654a8528200a661fda6393ce0e836675e9e..52481517ce7512ca5289ac5eda9ed3cafd49da7d 100644 (file)
@@ -12,6 +12,8 @@
 
 // aux-build:empty-struct.rs
 
+#![feature(relaxed_adts)]
+
 extern crate empty_struct;
 use empty_struct::*;
 
@@ -21,13 +23,12 @@ fn main() {
     let e1 = Empty1 {};
     let xe1 = XEmpty1 {};
 
-    // Rejected by parser as yet
-    // match e1 {
-    //     Empty1() => () // ERROR unresolved enum variant, struct or const `Empty1`
-    // }
-    // match xe1 {
-    //     XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
-    // }
+    match e1 {
+        Empty1() => () //~ ERROR unresolved variant or struct `Empty1`
+    }
+    match xe1 {
+        XEmpty1() => () //~ ERROR unresolved variant or struct `XEmpty1`
+    }
     match e1 {
         Empty1(..) => () //~ ERROR unresolved variant or struct `Empty1`
     }
index 88249fc422f2cb8c37e0a22e4bb2ad5eb89a9ac8..cb859fe7501c677f7cf1232a7fb31a721f19e47e 100644 (file)
@@ -12,6 +12,8 @@
 
 // aux-build:empty-struct.rs
 
+#![feature(relaxed_adts)]
+
 extern crate empty_struct;
 use empty_struct::*;
 
@@ -23,13 +25,12 @@ fn main() {
     let e3 = E::Empty3 {};
     let xe3 = XE::XEmpty3 {};
 
-    // Rejected by parser as yet
-    // match e3 {
-    //     E::Empty3() => () // ERROR `E::Empty3` does not name a tuple variant or a tuple struct
-    // }
-    // match xe3 {
-    //     E::Empty3() => () // ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
-    // }
+    match e3 {
+        E::Empty3() => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
+    }
+    match xe3 {
+        XE::XEmpty3() => () //~ ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
+    }
     match e3 {
         E::Empty3(..) => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
     }
diff --git a/src/test/compile-fail/empty-struct-tuple-pat.rs b/src/test/compile-fail/empty-struct-tuple-pat.rs
new file mode 100644 (file)
index 0000000..be90e3b
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.
+
+// Can't use unit struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+#![feature(relaxed_adts)]
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2();
+
+enum E {
+    Empty4()
+}
+
+// remove attribute after warning cycle and promoting warnings to errors
+fn main() {
+    let e2 = Empty2();
+    let e4 = E::Empty4();
+    let xe6 = XEmpty6();
+    let xe5 = XE::XEmpty5();
+
+    match e2 {
+        Empty2 => () //~ ERROR `Empty2` does not name a unit variant, unit struct or a constant
+    }
+    match xe6 {
+        XEmpty6 => () //~ ERROR `XEmpty6` does not name a unit variant, unit struct or a constant
+    }
+
+    match e4 {
+        E::Empty4 => () //~ ERROR `E::Empty4` does not name a unit variant, unit struct or a
+    }
+    match xe5 {
+        XE::XEmpty5 => (), //~ ERROR `XE::XEmpty5` does not name a unit variant, unit struct or a
+        _ => {},
+    }
+}
diff --git a/src/test/compile-fail/empty-struct-unit-pat-1.rs b/src/test/compile-fail/empty-struct-unit-pat-1.rs
new file mode 100644 (file)
index 0000000..aec4ad4
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+// Can't use unit struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+#![feature(relaxed_adts)]
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2;
+
+enum E {
+    Empty4
+}
+
+// remove attribute after warning cycle and promoting warnings to errors
+fn main() {
+    let e2 = Empty2;
+    let e4 = E::Empty4;
+    let xe2 = XEmpty2;
+    let xe4 = XE::XEmpty4;
+
+    match e2 {
+        Empty2(..) => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
+            //~^ WARNING hard error
+    }
+    match xe2 {
+        XEmpty2(..) => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
+            //~^ WARNING hard error
+    }
+
+    match e4 {
+        E::Empty4(..) => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
+            //~^ WARNING hard error
+    }
+    match xe4 {
+        XE::XEmpty4(..) => (), //~ ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
+            //~^ WARNING hard error
+        _ => {},
+    }
+}
diff --git a/src/test/compile-fail/empty-struct-unit-pat-2.rs b/src/test/compile-fail/empty-struct-unit-pat-2.rs
new file mode 100644 (file)
index 0000000..6375a7f
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.
+
+// Can't use unit struct as enum pattern
+
+// aux-build:empty-struct.rs
+
+#![feature(relaxed_adts)]
+
+extern crate empty_struct;
+use empty_struct::*;
+
+struct Empty2;
+
+enum E {
+    Empty4
+}
+
+// remove attribute after warning cycle and promoting warnings to errors
+fn main() {
+    let e2 = Empty2;
+    let e4 = E::Empty4;
+    let xe2 = XEmpty2;
+    let xe4 = XE::XEmpty4;
+
+    match e2 {
+        Empty2() => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
+    }
+    match xe2 {
+        XEmpty2() => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
+    }
+
+    match e4 {
+        E::Empty4() => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
+    }
+    match xe4 {
+        XE::XEmpty4() => (), //~ ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
+        _ => {},
+    }
+}
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
deleted file mode 100644 (file)
index 0573376..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-// Can't use unit struct as enum pattern
-
-// aux-build:empty-struct.rs
-
-extern crate empty_struct;
-use empty_struct::*;
-
-struct Empty2;
-
-enum E {
-    Empty4
-}
-
-// remove attribute after warning cycle and promoting warnings to errors
-fn main() {
-    let e2 = Empty2;
-    let e4 = E::Empty4;
-    let xe2 = XEmpty2;
-    let xe4 = XE::XEmpty4;
-
-    // Rejected by parser as yet
-    // match e2 {
-    //     Empty2() => () // ERROR `Empty2` does not name a tuple variant or a tuple struct
-    // }
-    // match xe2 {
-    //     XEmpty2() => () // ERROR `XEmpty2` does not name a tuple variant or a tuple struct
-    // }
-    match e2 {
-        Empty2(..) => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
-            //~^ WARNING hard error
-    }
-    match xe2 {
-        XEmpty2(..) => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
-            //~^ WARNING hard error
-    }
-    // Rejected by parser as yet
-    // match e4 {
-    //     E::Empty4() => () // ERROR `E::Empty4` does not name a tuple variant or a tuple struct
-    // }
-    // match xe4 {
-    //     XE::XEmpty4() => (), // ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
-    //     _ => {},
-    // }
-    match e4 {
-        E::Empty4(..) => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
-            //~^ WARNING hard error
-    }
-    match xe4 {
-        XE::XEmpty4(..) => (), //~ ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
-            //~^ WARNING hard error
-        _ => {},
-    }
-}
diff --git a/src/test/compile-fail/feature-gate-relaxed-adts-2.rs b/src/test/compile-fail/feature-gate-relaxed-adts-2.rs
new file mode 100644 (file)
index 0000000..a75f264
--- /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.
+
+struct Z(u8, u8);
+
+enum E {
+    U(u8, u8),
+}
+
+fn main() {
+    match Z(0, 1) {
+        Z{..} => {} //~ ERROR tuple structs and variants in struct patterns are unstable
+    }
+    match E::U(0, 1) {
+        E::U{..} => {} //~ ERROR tuple structs and variants in struct patterns are unstable
+    }
+
+    let z1 = Z(0, 1);
+    let z2 = Z { ..z1 }; //~ ERROR tuple structs and variants in struct patterns are unstable
+}
diff --git a/src/test/compile-fail/feature-gate-relaxed-adts.rs b/src/test/compile-fail/feature-gate-relaxed-adts.rs
new file mode 100644 (file)
index 0000000..dc5e347
--- /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.
+
+struct S(); //~ ERROR empty tuple structs and enum variants are unstable
+struct Z(u8, u8);
+
+enum E {
+    V(), //~ ERROR empty tuple structs and enum variants are unstable
+    U(u8, u8),
+}
+
+fn main() {
+    match S() {
+        S() => {} //~ ERROR empty tuple structs patterns are unstable
+    }
+    match E::V() {
+        E::V() => {} //~ ERROR empty tuple structs patterns are unstable
+    }
+}
diff --git a/src/test/compile-fail/impl-trait/auto-trait-leak.rs b/src/test/compile-fail/impl-trait/auto-trait-leak.rs
new file mode 100644 (file)
index 0000000..2c78ce2
--- /dev/null
@@ -0,0 +1,70 @@
+// 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-tidy-linelength
+
+#![feature(conservative_impl_trait)]
+
+use std::cell::Cell;
+use std::rc::Rc;
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+    send(before());
+    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+    //~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE required because it appears within the type `[closure
+    //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
+    //~| NOTE required by `send`
+
+    send(after());
+    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+    //~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE required because it appears within the type `[closure
+    //~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
+    //~| NOTE required by `send`
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl Fn(i32) {
+    let p = Rc::new(Cell::new(0));
+    move |x| p.set(x)
+}
+
+// Cycles should work as the deferred obligations are
+// independently resolved and only require the concrete
+// return type, which can't depend on the obligation.
+fn cycle1() -> impl Clone {
+    send(cycle2().clone());
+    //~^ ERROR the trait bound `std::rc::Rc<std::string::String>: std::marker::Send` is not satisfied
+    //~| NOTE `std::rc::Rc<std::string::String>` cannot be sent between threads safely
+    //~| NOTE required because it appears within the type `impl std::clone::Clone`
+    //~| NOTE required by `send`
+
+    Rc::new(Cell::new(5))
+}
+
+fn cycle2() -> impl Clone {
+    send(cycle1().clone());
+    //~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
+    //~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
+    //~| NOTE required because it appears within the type `impl std::clone::Clone`
+    //~| NOTE required by `send`
+
+    Rc::new(String::from("foo"))
+}
diff --git a/src/test/compile-fail/impl-trait/disallowed-2.rs b/src/test/compile-fail/impl-trait/disallowed-2.rs
new file mode 100644 (file)
index 0000000..46b3106
--- /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.
+
+#![feature(conservative_impl_trait)]
+
+fn main() {
+    let _: impl Fn() = || {};
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+    let _ = || -> impl Fn() { || {} };
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
diff --git a/src/test/compile-fail/impl-trait/disallowed.rs b/src/test/compile-fail/impl-trait/disallowed.rs
new file mode 100644 (file)
index 0000000..09aba5d
--- /dev/null
@@ -0,0 +1,61 @@
+// 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(conservative_impl_trait)]
+
+fn arguments(_: impl Fn(),
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+             _: Vec<impl Clone>) {}
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+type Factory<R> = impl Fn() -> R;
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+type GlobalFactory<R> = fn() -> impl FnOnce() -> R;
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+trait LazyToString {
+    fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String;
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+}
+
+// Note that the following impl doesn't error, because the trait is invalid.
+impl LazyToString for String {
+    fn lazy_to_string<'a>(&'a self) -> impl Fn() -> String {
+        || self.clone()
+    }
+}
+
+#[derive(Copy, Clone)]
+struct Lazy<T>(T);
+
+impl std::ops::Add<Lazy<i32>> for Lazy<i32> {
+    type Output = impl Fn() -> Lazy<i32>;
+    //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+
+    fn add(self, other: Lazy<i32>) -> Self::Output {
+        move || Lazy(self.0 + other.0)
+    }
+}
+
+impl<F> std::ops::Add<F>
+for impl Fn() -> Lazy<i32>
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+where F: Fn() -> impl FnOnce() -> i32
+//~^ ERROR `impl Trait` not allowed outside of function and inherent method return types
+{
+    type Output = Self;
+
+    fn add(self, other: F) -> Self::Output {
+        move || Lazy(self().0 + other()())
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/impl-trait/equality.rs b/src/test/compile-fail/impl-trait/equality.rs
new file mode 100644 (file)
index 0000000..59ad113
--- /dev/null
@@ -0,0 +1,89 @@
+// 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(conservative_impl_trait, specialization)]
+
+trait Foo: Copy + ToString {}
+
+impl<T: Copy + ToString> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+fn two(x: bool) -> impl Foo {
+    if x {
+        return 1_i32;
+    }
+    0_u32
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
+
+fn sum_to(n: u32) -> impl Foo {
+    if n == 0 {
+        0
+    } else {
+        n + sum_to(n - 1)
+        //~^ ERROR the trait bound `u32: std::ops::Add<impl Foo>` is not satisfied
+    }
+}
+
+trait Leak: Sized {
+    type T;
+    fn leak(self) -> Self::T;
+}
+impl<T> Leak for T {
+    default type T = ();
+    default fn leak(self) -> Self::T { panic!() }
+}
+impl Leak for i32 {
+    type T = i32;
+    fn leak(self) -> i32 { self }
+}
+
+trait CheckIfSend: Sized {
+    type T: Default;
+    fn check(self) -> Self::T { Default::default() }
+}
+impl<T> CheckIfSend for T {
+    default type T = ();
+}
+impl<T: Send> CheckIfSend for T {
+    type T = bool;
+}
+
+fn main() {
+    let _: u32 = hide(0_u32);
+    //~^ ERROR mismatched types
+    //~| expected type `u32`
+    //~| found type `impl Foo`
+    //~| expected u32, found anonymized type
+
+    let _: i32 = Leak::leak(hide(0_i32));
+    //~^ ERROR mismatched types
+    //~| expected type `i32`
+    //~| found type `<impl Foo as Leak>::T`
+    //~| expected i32, found associated type
+
+    let _: bool = CheckIfSend::check(hide(0_i32));
+    //~^ ERROR mismatched types
+    //~| expected type `bool`
+    //~| found type `<impl Foo as CheckIfSend>::T`
+    //~| expected bool, found associated type
+
+    let mut x = (hide(0_u32), hide(0_i32));
+    x = (x.1,
+    //~^ ERROR mismatched types
+    //~| expected u32, found i32
+         x.0);
+    //~^ ERROR mismatched types
+    //~| expected i32, found u32
+}
diff --git a/src/test/compile-fail/impl-trait/feature-gate.rs b/src/test/compile-fail/impl-trait/feature-gate.rs
new file mode 100644 (file)
index 0000000..8239b06
--- /dev/null
@@ -0,0 +1,14 @@
+// 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 foo() -> impl Fn() { || {} }
+//~^ ERROR `impl Trait` is experimental
+
+fn main() {}
diff --git a/src/test/compile-fail/impl-trait/lifetimes.rs b/src/test/compile-fail/impl-trait/lifetimes.rs
new file mode 100644 (file)
index 0000000..9d9f6bf
--- /dev/null
@@ -0,0 +1,43 @@
+// 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(conservative_impl_trait)]
+
+// Helper creating a fake borrow, captured by the impl Trait.
+fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
+
+fn stack() -> impl Copy {
+    //~^ ERROR only named lifetimes are allowed in `impl Trait`
+    let x = 0;
+    &x
+}
+
+fn late_bound(x: &i32) -> impl Copy {
+    //~^ ERROR only named lifetimes are allowed in `impl Trait`
+    x
+}
+
+// FIXME(#34511) Should work but doesn't at the moment,
+// region-checking needs an overhault to support this.
+fn early_bound<'a>(x: &'a i32) -> impl Copy {
+    //~^ ERROR only named lifetimes are allowed in `impl Trait`
+    x
+}
+
+fn ambiguous<'a, 'b>(x: &'a [u32], y: &'b [u32]) -> impl Iterator<Item=u32> {
+    //~^ ERROR only named lifetimes are allowed in `impl Trait`
+    if x.len() < y.len() {
+        x.iter().cloned()
+    } else {
+        y.iter().cloned()
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/impl-trait/loan-extend.rs b/src/test/compile-fail/impl-trait/loan-extend.rs
new file mode 100644 (file)
index 0000000..ceaa8f4
--- /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.
+
+#![feature(conservative_impl_trait)]
+
+// Helper creating a fake borrow, captured by the impl Trait.
+fn borrow<'a, T>(_: &'a mut T) -> impl Copy { () }
+
+fn main() {
+    //~^ NOTE reference must be valid for the block
+    let long;
+    let mut short = 0;
+    //~^ NOTE but borrowed value is only valid for the block suffix following statement 1
+    long = borrow(&mut short);
+    //~^ ERROR `short` does not live long enough
+}
diff --git a/src/test/compile-fail/issue-12560-1.rs b/src/test/compile-fail/issue-12560-1.rs
deleted file mode 100644 (file)
index 80f551e..0000000
+++ /dev/null
@@ -1,25 +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.
-
-// For style and consistency reasons, non-parametrized enum variants must
-// be used simply as `ident` instead of `ident ()`.
-// This test-case covers enum declaration.
-
-enum Foo {
-    Bar(), //~ ERROR empty tuple structs and enum variants are not allowed
-    //~^ HELP remove trailing `()` to make a unit struct or unit enum variant
-    Baz(), //~ ERROR empty tuple structs and enum variants are not allowed
-    //~^ HELP remove trailing `()` to make a unit struct or unit enum variant
-    Bazar
-}
-
-fn main() {
-    println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 }) //~ ERROR unresolved name `Bar`
-}
diff --git a/src/test/compile-fail/issue-12560-2.rs b/src/test/compile-fail/issue-12560-2.rs
deleted file mode 100644 (file)
index 9cbe2eb..0000000
+++ /dev/null
@@ -1,29 +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 continue-parse-after-error
-
-// For style and consistency reasons, non-parametrized enum variants must
-// be used simply as `ident` instead of `ident ()`.
-// This test-case covers enum matching.
-
-enum Foo {
-    Bar,
-    Baz,
-    Bazar
-}
-
-fn main() {
-    println!("{}", match Bar {
-        Bar() => 1, //~ ERROR nullary enum variants are written with no trailing `( )`
-        Baz() => 2, //~ ERROR nullary enum variants are written with no trailing `( )`
-        Bazar => 3
-    })
-}
index 3d6f224c249040a1c1d168d0b5357ba9af7c06de..658a0c1546b9f337b27704fa31d060075e91bdfc 100644 (file)
 
 enum Foo {
     A = 1,
-    //~^ NOTE first use
-    //~| NOTE first use
-    //~| NOTE first use
-    B = 1, //~ ERROR discriminant value
-    //~^ NOTE enum already
+    //~^ NOTE first use of `1isize`
+    //~| NOTE first use of `1isize`
+    //~| NOTE first use of `1isize`
+    B = 1,
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
     C = 0,
-    D, //~ ERROR discriminant value
-    //~^ NOTE enum already
+    D,
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
 
-    E = N, //~ ERROR discriminant value
-    //~^ NOTE enum already
+    E = N,
+    //~^ ERROR discriminant value `1isize` already exists
+    //~| NOTE enum already has `1isize`
 
 }
 
index b229b91c7cd14d353b2df8a42bff9b8c09793677..4301b47f2e9b29ce956f8450d3d69c4fc543bccf 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
+struct TS ( //~ ERROR empty tuple structs and enum variants are unstable
     #[cfg(untrue)]
     i32,
 );
 
 enum E {
-    TV ( //~ ERROR empty tuple structs and enum variants are not allowed
+    TV ( //~ ERROR empty tuple structs and enum variants are unstable
         #[cfg(untrue)]
         i32,
     )
index 5196b6ea877f887d553e86b306ddba680ed70d3f..58d580a5c1a1ceb6ecf9b8d257e7f55b4a714f46 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(relaxed_adts)]
+
 enum MyOption<T> {
     MySome(T),
     MyNone,
@@ -16,7 +18,8 @@ enum MyOption<T> {
 fn main() {
     match MyOption::MySome(42) {
         MyOption::MySome { x: 42 } => (),
-        //~^ ERROR `MyOption::MySome` does not name a struct or a struct variant
+        //~^ ERROR struct `MyOption::MySome` does not have a field named `x`
+        //~| ERROR pattern does not mention field `0`
         _ => (),
     }
 }
index e6f3a2bdd33ad127a14960d350de8bba749b62af..b3fc3aea148ee3b6cdaf70e4e75a4af0c862a78b 100644 (file)
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 pub struct Foo<Bar=Bar>; //~ ERROR E0128
+                         //~| NOTE defaulted type parameters cannot be forward declared
 pub struct Baz(Foo);
 fn main() {}
index 1c9e588cb2cd18c051d904b69947ff8c549c4b41..3e44053875552cbf8fbc194c2939969c89a65365 100644 (file)
@@ -15,10 +15,12 @@ fn f<T: Array>(x: &T) {
     //~^ ERROR `Array` cannot be made into an object
     //~| NOTE the trait cannot require that `Self : Sized`
     //~| NOTE requirements on the impl of `std::ops::CoerceUnsized<&Array>`
+    //~| NOTE the trait `Array` cannot be made into an object
     as
     &Array;
     //~^ ERROR `Array` cannot be made into an object
     //~| NOTE the trait cannot require that `Self : Sized`
+    //~| NOTE the trait `Array` cannot be made into an object
 }
 
 fn main() {}
index 4e9cbc4f283b4e12a2d3b950e99dfce3505f177f..ded685152d49b63c83a0371c41e6cabcc301e369 100644 (file)
@@ -28,6 +28,7 @@ impl<K> Map for K {
 fn main() {
     let _ = &()
         as &Map<Key=u32,MapValue=u32>;
-    //~^ ERROR the trait `Map` cannot be made into an object
+    //~^ ERROR E0038
     //~| NOTE the trait cannot use `Self` as a type parameter
+    //~| NOTE the trait `Map` cannot be made into an object
 }
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
deleted file mode 100644 (file)
index e20e6ea..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-struct Foo(u32);
-struct Bar;
-
-enum Enum {
-    Foo(u32),
-    Bar
-}
-
-fn main() {
-    let x = Foo(1);
-    Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
-    let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
-
-    let x = Bar;
-    Bar { ..x };
-    let Bar { .. } = x;
-
-    match Enum::Bar {
-        Enum::Bar { .. }
-           => {}
-        Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
-           => {}
-    }
-}
diff --git a/src/test/compile-fail/issue-28514.rs b/src/test/compile-fail/issue-28514.rs
new file mode 100644 (file)
index 0000000..6ee3755
--- /dev/null
@@ -0,0 +1,45 @@
+// 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 use inner::C;
+
+mod inner {
+    trait A {
+        fn a(&self) { }
+    }
+
+    pub trait B {
+        fn b(&self) { }
+    }
+
+    pub trait C: A + B { //~ ERROR private trait in public interface
+                         //~^ WARN will become a hard error
+        fn c(&self) { }
+    }
+
+    impl A for i32 {}
+    impl B for i32 {}
+    impl C for i32 {}
+
+}
+
+fn main() {
+    // A is private
+    // B is pub, not reexported
+    // C : A + B is pub, reexported
+
+    // 0.a(); // can't call
+    // 0.b(); // can't call
+    0.c(); // ok
+
+    C::a(&0); // can call
+    C::b(&0); // can call
+    C::c(&0); // ok
+}
index ce06c8bf220ee0317c3a94c55b2bfb4c12666a56..52b0eba96cbdf59631f784bc662fe72f14cfc001 100644 (file)
@@ -11,5 +11,7 @@
 use std::ptr;
 
 fn main() {
-    (&ptr::write)(1 as *mut _, 42); //~ ERROR E0133
+    (&ptr::write)(1 as *mut _, 42);
+    //~^ ERROR E0133
+    //~| NOTE unsafe call requires unsafe function or block
 }
index a8db01b82da945dbf23dd745c8588db8ce4ea7c9..55c58ed021b27d77bb73ec9dfb2d1aa43b064e85 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
 #![allow(unused)]
 
 struct SemiPriv;
@@ -16,7 +15,7 @@
 mod m1 {
     struct Priv;
     impl ::SemiPriv {
-        pub fn f(_: Priv) {} //~ WARN private type in public interface
+        pub fn f(_: Priv) {} //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
 
@@ -28,7 +27,7 @@ pub fn f(_: Priv) {} // ok
 mod m2 {
     struct Priv;
     impl ::std::ops::Deref for ::SemiPriv {
-        type Target = Priv; //~ WARN private type in public interface
+        type Target = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
         fn deref(&self) -> &Self::Target { unimplemented!() }
     }
@@ -46,10 +45,9 @@ trait SemiPrivTrait {
 mod m3 {
     struct Priv;
     impl ::SemiPrivTrait for () {
-        type Assoc = Priv; //~ WARN private type in public interface
+        type Assoc = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
 }
 
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {}
index e6cc29634a1e8ebaf696f54192e82775336323a2..38b5fcbb3db0ee36b98b190945e09af7b1b33be4 100644 (file)
@@ -13,6 +13,7 @@
 enum foo { foo_(bar) }
 struct bar { x: bar }
 //~^ ERROR E0072
+//~| NOTE recursive type has infinite size
 
 fn main() {
 }
index 8af243afc22996b064c55ecc24e68aec2c7d82c4..afffe2a2c8d03d057a95eb4296f5dea955e1598e 100644 (file)
@@ -13,6 +13,7 @@
 // too big.
 
 enum Expr { //~ ERROR E0072
+            //~| NOTE recursive type has infinite size
     Plus(Expr, Expr),
     Literal(i64),
 }
diff --git a/src/test/compile-fail/issue-35450.rs b/src/test/compile-fail/issue-35450.rs
new file mode 100644 (file)
index 0000000..d890d02
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+macro_rules! m { ($t:tt) => { $t } }
+
+fn main() {
+    m!($t); //~ ERROR unknown macro variable
+            //~| ERROR expected expression
+}
index d96b1a1cbe35b1cd4f08bf56fa391ea88b25f733..71e9325ab75d135dfb7823e967f0f48d5b74466e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 struct S { //~ ERROR E0072
+           //~| NOTE recursive type has infinite size
     element: Option<S>
 }
 
index 55983c672aa08a8553ce28932d2db5202f277b63..a8a1b1482fc08b4ad0e69473d22679e32e9bdc08 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(relaxed_adts)]
+
 struct NonCopyable(());
 
 fn main() {
-    let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
+    let z = NonCopyable{ p: () }; //~ ERROR structure `NonCopyable` has no field named `p`
 }
index f50a934510697669557cbe2a014b13dd2570bb57..9d246f8ea5e0e5bb08f01569508b805abee44ebc 100644 (file)
@@ -12,7 +12,7 @@ fn test() {
     let v: isize;
     loop {
         v = 1; //~ ERROR re-assignment of immutable variable
-        //~^ NOTE prior assignment occurs here
+        //~^ NOTE re-assignment of immutable variable
         v.clone(); // just to prevent liveness warnings
     }
 }
index df57bb9e4417ed17e6b77c2cf027e25adcf5db7f..e1eb3246137d22a9d711d93d5dd518ff22b1dd37 100644 (file)
@@ -10,8 +10,9 @@
 
 fn test() {
     let v: isize;
-    v = 2;  //~ NOTE prior assignment occurs here
+    v = 2;  //~ NOTE first assignment
     v += 1; //~ ERROR re-assignment of immutable variable
+            //~| NOTE re-assignment of immutable
     v.clone();
 }
 
index 28218bff60d68c96051741f5c3d66b2d9c3a9bb7..2468c91f34bbd018a4c324eed5c3e924f4a28b5c 100644 (file)
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 fn test() {
-    let v: isize = 1; //~ NOTE prior assignment occurs here
+    let v: isize = 1; //~ NOTE first assignment
     v.clone();
     v = 2; //~ ERROR re-assignment of immutable variable
+           //~| NOTE re-assignment of immutable
     v.clone();
 }
 
index f41da77ee989655e9b28f9424d13a8257cb79b4e..945490cefb95a80ece1c29dea3e4dea0244a2419 100644 (file)
@@ -16,5 +16,16 @@ macro_rules! foo {
 
 foo!(Box);
 
+macro_rules! bar {
+    ($x:tt) => {
+        macro_rules! baz {
+            ($x:tt, $y:tt) => { ($x, $y) }
+        }
+    }
+}
+
 #[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() { //~ ERROR compilation successful
+    bar!($y);
+    let _: (i8, i16) = baz!(0i8, 0i16);
+}
index 3edbdf4ebc9584ce7d5770bd15064dd56fedf64f..b0278476998dd54b42a96a1a9b6089bb1a9db957 100644 (file)
 
 extern {
     fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
-                        //~^ NOTE this is a recent error
+                        //~^ NOTE pattern not allowed in foreign function
+                        //~| NOTE this is a recent error
     fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
+                     //~^ NOTE pattern not allowed in foreign function
     fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
-                        //~^ NOTE this is a recent error
+                        //~^ NOTE pattern not allowed in foreign function
+                        //~| NOTE this is a recent error
     fn g1(arg: u8); // OK
     fn g2(_: u8); // OK
     // fn g3(u8); // Not yet
diff --git a/src/test/compile-fail/numeric-fields.rs b/src/test/compile-fail/numeric-fields.rs
new file mode 100644 (file)
index 0000000..480d2dc
--- /dev/null
@@ -0,0 +1,20 @@
+// 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(relaxed_adts)]
+
+struct S(u8, u16);
+
+fn main() {
+    let s = S{0b1: 10, 0: 11}; //~ ERROR structure `S` has no field named `0b1`
+    match s {
+        S{0: a, 0x1: b, ..} => {} //~ ERROR does not have a field named `0x1`
+    }
+}
index 5097e3d7b10d4735cdc961e4b86d418b7a34fba0..6174d45b898d6971e00405c141930ba98590622c 100644 (file)
@@ -24,12 +24,14 @@ fn bar<T>(&self, t: T)
 fn make_bar<T:Bar>(t: &T) -> &Bar {
         //~^ ERROR E0038
         //~| NOTE method `bar` has generic type parameters
+        //~| NOTE the trait `Bar` cannot be made into an object
     t
 }
 
 fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
     //~^ ERROR E0038
-    //~^^ NOTE method `bar` has generic type parameters
+    //~| NOTE method `bar` has generic type parameters
+    //~| NOTE the trait `Bar` cannot be made into an object
     t as &Bar
 }
 
index edd31c1f79649fe98c89f8bc6b5e80f61c0a69eb..d85614fa5b538845359fa196638ff58dea68f82e 100644 (file)
@@ -27,12 +27,14 @@ trait Quux {
 fn make_bar<T:Bar>(t: &T) -> &Bar {
         //~^ ERROR E0038
         //~| NOTE method `bar` references the `Self` type in its arguments or return type
+        //~| NOTE the trait `Bar` cannot be made into an object
     loop { }
 }
 
 fn make_baz<T:Baz>(t: &T) -> &Baz {
         //~^ ERROR E0038
         //~| NOTE method `bar` references the `Self` type in its arguments or return type
+        //~| NOTE the trait `Baz` cannot be made into an object
     t
 }
 
index 501d61d20fed124453edb3b2bad2050c71f7d273..accd7fa87ac29bf435af31c3f2307f7995625b61 100644 (file)
@@ -18,6 +18,7 @@ trait Bar : Sized {
 fn make_bar<T:Bar>(t: &T) -> &Bar {
         //~^ ERROR E0038
         //~| NOTE the trait cannot require that `Self : Sized`
+        //~| NOTE the trait `Bar` cannot be made into an object
     t
 }
 
index 0a79ec30e4b942445b96da9bc08f970a4b023f01..74d1ad62f14c3be3fb4d8c0d0c21bb4a77c652e7 100644 (file)
@@ -25,6 +25,7 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
 fn make_baz<T:Baz>(t: &T) -> &Baz {
     //~^ ERROR E0038
     //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
+    //~| NOTE the trait `Baz` cannot be made into an object
     t
 }
 
index f9b049c5d3360e584af7a77e377f00e88d14dabe..8e23bfcfb10516bbcc84e8b4ad42d837cc0a0706 100644 (file)
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 mod m1 {
-    #![deny(private_in_public)]
-
     pub struct Pub;
     struct Priv;
 
index b9d632a8cf07e6ce33dcbcd4271e05758769b5d0..6d6af77be92b07182e5a0e5fa5ea567801bf2e74 100644 (file)
@@ -11,7 +11,6 @@
 // Private types and traits are not allowed in public interfaces.
 // This test also ensures that the checks are performed even inside private modules.
 
-#![feature(rustc_attrs)]
 #![feature(associated_consts)]
 #![feature(associated_type_defaults)]
 #![allow(dead_code)]
@@ -25,34 +24,34 @@ pub trait PubTr {
         type Alias;
     }
 
-    pub type Alias = Priv; //~ WARN private type in public interface
+    pub type Alias = Priv; //~ ERROR private type in public interface
     //~^ WARNING hard error
     pub enum E {
-        V1(Priv), //~ WARN private type in public interface
+        V1(Priv), //~ ERROR private type in public interface
         //~^ WARNING hard error
-        V2 { field: Priv }, //~ WARN private type in public interface
+        V2 { field: Priv }, //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     pub trait Tr {
-        const C: Priv = Priv; //~ WARN private type in public interface
+        const C: Priv = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
-        type Alias = Priv; //~ WARN private type in public interface
+        type Alias = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
-        fn f1(arg: Priv) {} //~ WARN private type in public interface
+        fn f1(arg: Priv) {} //~ ERROR private type in public interface
         //~^ WARNING hard error
-        fn f2() -> Priv { panic!() } //~ WARN private type in public interface
+        fn f2() -> Priv { panic!() } //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     extern {
-        pub static ES: Priv; //~ WARN private type in public interface
+        pub static ES: Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
-        pub fn ef1(arg: Priv); //~ WARN private type in public interface
+        pub fn ef1(arg: Priv); //~ ERROR private type in public interface
         //~^ WARNING hard error
-        pub fn ef2() -> Priv; //~ WARN private type in public interface
+        pub fn ef2() -> Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     impl PubTr for Pub {
-        type Alias = Priv; //~ WARN private type in public interface
+        type Alias = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
 }
@@ -62,22 +61,22 @@ trait PrivTr {}
     pub struct Pub<T>(T);
     pub trait PubTr {}
 
-    pub type Alias<T: PrivTr> = T; //~ WARN private trait in public interface
+    pub type Alias<T: PrivTr> = T; //~ ERROR private trait in public interface
     //~^ WARN trait bounds are not (yet) enforced in type definitions
     //~| WARNING hard error
-    pub trait Tr1: PrivTr {} //~ WARN private trait in public interface
+    pub trait Tr1: PrivTr {} //~ ERROR private trait in public interface
     //~^ WARNING hard error
-    pub trait Tr2<T: PrivTr> {} //~ WARN private trait in public interface
+    pub trait Tr2<T: PrivTr> {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
     pub trait Tr3 {
-        type Alias: PrivTr; //~ WARN private trait in public interface
+        type Alias: PrivTr; //~ ERROR private trait in public interface
         //~^ WARNING hard error
-        fn f<T: PrivTr>(arg: T) {} //~ WARN private trait in public interface
+        fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
     }
-    impl<T: PrivTr> Pub<T> {} //~ WARN private trait in public interface
+    impl<T: PrivTr> Pub<T> {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
-    impl<T: PrivTr> PubTr for Pub<T> {} //~ WARN private trait in public interface
+    impl<T: PrivTr> PubTr for Pub<T> {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
 }
 
@@ -86,17 +85,17 @@ trait PrivTr {}
     pub struct Pub<T>(T);
     pub trait PubTr {}
 
-    pub type Alias<T> where T: PrivTr = T; //~ WARN private trait in public interface
+    pub type Alias<T> where T: PrivTr = T; //~ ERROR private trait in public interface
         //~^ WARNING hard error
-    pub trait Tr2<T> where T: PrivTr {} //~ WARN private trait in public interface
+    pub trait Tr2<T> where T: PrivTr {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
     pub trait Tr3 {
-        fn f<T>(arg: T) where T: PrivTr {} //~ WARN private trait in public interface
+        fn f<T>(arg: T) where T: PrivTr {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
     }
-    impl<T> Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
+    impl<T> Pub<T> where T: PrivTr {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
-    impl<T> PubTr for Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
+    impl<T> PubTr for Pub<T> where T: PrivTr {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
 }
 
@@ -106,13 +105,13 @@ mod generics {
     trait PrivTr<T> {}
     pub trait PubTr<T> {}
 
-    pub trait Tr1: PrivTr<Pub> {} //~ WARN private trait in public interface
+    pub trait Tr1: PrivTr<Pub> {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
-    pub trait Tr2: PubTr<Priv> {} //~ WARN private type in public interface
+    pub trait Tr2: PubTr<Priv> {} //~ ERROR private type in public interface
         //~^ WARNING hard error
-    pub trait Tr3: PubTr<[Priv; 1]> {} //~ WARN private type in public interface
+    pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR private type in public interface
         //~^ WARNING hard error
-    pub trait Tr4: PubTr<Pub<Priv>> {} //~ WARN private type in public interface
+    pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR private type in public interface
         //~^ WARNING hard error
 }
 
@@ -139,7 +138,7 @@ impl PrivTr for Pub {
         type Alias = Priv; // OK
     }
     impl PubTr for Pub {
-        type Alias = Priv; //~ WARN private type in public interface
+        type Alias = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
 }
@@ -205,30 +204,29 @@ impl PrivTr for Priv {
     }
 
     pub fn f1(arg: PrivUseAlias) {} // OK
+    pub fn f2(arg: PrivAlias) {} // OK
 
     pub trait Tr1: PrivUseAliasTr {} // OK
-    // This should be OK, if type aliases are substituted
-    pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private type in public interface
-        //~^ WARNING hard error
+    pub trait Tr2: PrivUseAliasTr<PrivAlias> {} // OK
 
     impl PrivAlias {
-        pub fn f(arg: Priv) {} //~ WARN private type in public interface
+        pub fn f(arg: Priv) {} //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     // This doesn't even parse
     // impl <Priv as PrivTr>::AssocAlias {
-    //     pub fn f(arg: Priv) {} // WARN private type in public interface
+    //     pub fn f(arg: Priv) {} // ERROR private type in public interface
     // }
     impl PrivUseAliasTr for PrivUseAlias {
-        type Check = Priv; //~ WARN private type in public interface
+        type Check = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     impl PrivUseAliasTr for PrivAlias {
-        type Check = Priv; //~ WARN private type in public interface
+        type Check = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
     impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
-        type Check = Priv; //~ WARN private type in public interface
+        type Check = Priv; //~ ERROR private type in public interface
         //~^ WARNING hard error
     }
 }
@@ -253,10 +251,10 @@ impl PrivTr for Priv {
         type AssocAlias = Priv3;
     }
 
-    pub trait Tr1: PrivUseAliasTr {} //~ WARN private trait in public interface
+    pub trait Tr1: PrivUseAliasTr {} //~ ERROR private trait in public interface
         //~^ WARNING hard error
-    pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private trait in public interface
-     //~^ WARN private type in public interface
+    pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ ERROR private trait in public interface
+     //~^ ERROR private type in public interface
         //~| WARNING hard error
         //~| WARNING hard error
 
@@ -285,7 +283,8 @@ mod aliases_params {
     struct Priv;
     type PrivAliasGeneric<T = Priv> = T;
     type Result<T> = ::std::result::Result<T, Priv>;
+
+    pub fn f1(arg: PrivAliasGeneric<u8>) {} // OK, not an error
 }
 
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {}
index be22a2ef6a77f1bcb4ae118fa059b5a3dad4c6c3..7d4dcfd3145abdd313a6663c8fd620579d88fd26 100644 (file)
@@ -105,8 +105,6 @@ trait PrivTr {
     }
     impl PrivTr for Priv {}
 
-    // This should be OK, if type aliases are substituted
-    pub fn f2(arg: PrivAlias) {} //~ ERROR private type in public interface
     // This should be OK, but associated type aliases are not substituted yet
     pub fn f3(arg: <Priv as PrivTr>::AssocAlias) {} //~ ERROR private type in public interface
 
@@ -143,8 +141,6 @@ mod aliases_params {
     type PrivAliasGeneric<T = Priv> = T;
     type Result<T> = ::std::result::Result<T, Priv>;
 
-    // This should be OK, if type aliases are substituted
-    pub fn f1(arg: PrivAliasGeneric<u8>) {} //~ ERROR private type in public interface
     pub fn f2(arg: PrivAliasGeneric) {} //~ ERROR private type in public interface
     pub fn f3(arg: Result<u8>) {} //~ ERROR private type in public interface
 }
index 5811d82681e6b80ee0ccb10a2d436931efb39634..ce029e7eff7fcb11bfeb5844f9f77da1baeea031 100644 (file)
@@ -8,34 +8,32 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
 #![allow(dead_code)]
 
 extern crate core;
-pub use core as reexported_core; //~ WARN extern crate `core` is private, and cannot be reexported
+pub use core as reexported_core; //~ ERROR extern crate `core` is private, and cannot be reexported
 //~^ WARNING hard error
 
 mod m1 {
-    pub use ::E::V; //~ WARN variant `V` is private, and cannot be reexported
+    pub use ::E::V; //~ ERROR variant `V` is private, and cannot be reexported
     //~^ WARNING hard error
 }
 
 mod m2 {
-    pub use ::E::{V}; //~ WARN variant `V` is private, and cannot be reexported
+    pub use ::E::{V}; //~ ERROR variant `V` is private, and cannot be reexported
     //~^ WARNING hard error
 }
 
 mod m3 {
-    pub use ::E::V::{self}; //~ WARN variant `V` is private, and cannot be reexported
+    pub use ::E::V::{self}; //~ ERROR variant `V` is private, and cannot be reexported
     //~^ WARNING hard error
 }
 
 mod m4 {
-    pub use ::E::*; //~ WARN variant `V` is private, and cannot be reexported
+    pub use ::E::*; //~ ERROR variant `V` is private, and cannot be reexported
     //~^ WARNING hard error
 }
 
 enum E { V }
 
-#[rustc_error]
-fn main() {} //~ ERROR compilation successful
+fn main() {}
diff --git a/src/test/compile-fail/pub-struct-field-span-26083.rs b/src/test/compile-fail/pub-struct-field-span-26083.rs
deleted file mode 100644 (file)
index 0dc7e09..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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.
-
-// Regression test for issue #26083
-// Test that span for public struct fields start at `pub` instead of the identifier
-
-struct Foo {
-    pub bar: u8,
-
-    pub
-    //~^ error: field `bar` is already declared [E0124]
-    bar: u8,
-
-    pub bar:
-    //~^ error: field `bar` is already declared [E0124]
-    u8,
-
-    bar:
-    //~^ error: field `bar` is already declared [E0124]
-    u8,
-}
-
-fn main() { }
diff --git a/src/test/compile-fail/struct-no-fields-enumlike.rs b/src/test/compile-fail/struct-no-fields-enumlike.rs
deleted file mode 100644 (file)
index 6bdbae1..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.
-
-struct Foo(); //~ ERROR empty tuple structs and enum variants are not allowed
-
-fn main() {}
index 499b58f70d77ab5360a63458ba97188b875c6ff5..0df7ee8cabed21a4adb3db8a14e1d1962127f669 100644 (file)
@@ -18,7 +18,9 @@ fn foo(self) { }
 unsafe impl UnsafeTrait for *mut isize {
     fn foo(self) {
         // Unsafe actions are not made legal by taking place in an unsafe trait:
-        *self += 1; //~ ERROR E0133
+        *self += 1;
+        //~^ ERROR E0133
+        //~| NOTE unsafe call requires unsafe function or block
     }
 }
 
index df87a7bbdc9c223eb877f372d3987a14f9ab5dee..5fab271efce64cb72905e943b8b029531b75dff3 100644 (file)
@@ -11,6 +11,7 @@
 // Tests that `transmute` cannot be called on types of different size.
 
 #![allow(warnings)]
+#![feature(specialization)]
 
 use std::mem::transmute;
 
@@ -24,4 +25,15 @@ unsafe fn g<T>(x: &T) {
     //~^ ERROR transmute called with differently sized types
 }
 
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+unsafe fn specializable<T>(x: u16) -> <T as Specializable>::Output {
+    transmute(x)
+    //~^ ERROR transmute called with differently sized types
+}
+
 fn main() {}
index 4bb739800df368821aacde032015d05231cc3ea8..7b56c6c15ebb308b68b959338bacc1730a665cc5 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 struct t1 { //~ ERROR E0072
+            //~| NOTE recursive type has infinite size
     foo: isize,
     foolish: t1
 }
index 24ac41ce88437093797bfcd5ebe40057ff4ed72a..174939b09009cbd3ef0bef677506f6a3191146c8 100644 (file)
@@ -16,7 +16,9 @@
     !v
 }
 
-const VAL: u32 = dummy(0xFFFF); //~ ERROR E0133
+const VAL: u32 = dummy(0xFFFF);
+//~^ ERROR E0133
+//~| NOTE unsafe call requires unsafe function or block
 
 fn main() {
     assert_eq!(VAL, 0xFFFF0000);
index e81f828beb19fd4d3fd9b25588de8c382c6400ba..e8b187b5454f6dbe88cafef8dac49cc7b8b03d98 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2
+// compile-flags:-Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index 9a3097831c5631712d47788d7a6a8160c7c3f40e..64b7f2951d274595005c79abcd047ae80c409d89 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 cfail2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/foreign.rs b/src/test/incremental/foreign.rs
new file mode 100644 (file)
index 0000000..dbdebef
--- /dev/null
@@ -0,0 +1,45 @@
+// 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 what happens we save incremental compilation state that makes
+// use of foreign items. This used to ICE (#34991).
+
+// revisions: rpass1
+
+#![feature(libc)]
+
+extern crate libc;
+
+use std::ffi::CString;
+
+mod mlibc {
+    use libc::{c_char, c_long, c_longlong};
+
+    extern {
+        pub fn atol(x: *const c_char) -> c_long;
+        pub fn atoll(x: *const c_char) -> c_longlong;
+    }
+}
+
+fn atol(s: String) -> isize {
+    let c = CString::new(s).unwrap();
+    unsafe { mlibc::atol(c.as_ptr()) as isize }
+}
+
+fn atoll(s: String) -> i64 {
+    let c = CString::new(s).unwrap();
+    unsafe { mlibc::atoll(c.as_ptr()) as i64 }
+}
+
+pub fn main() {
+    assert_eq!(atol("1024".to_string()) * 10, atol("10240".to_string()));
+    assert_eq!((atoll("11111111111111111".to_string()) * 10),
+             atoll("111111111111111110".to_string()));
+}
index f98ae188bad9f2647bfb6aeb066caac4eaa01ca2..a06c25ac055c77b6ce313f8d345c5be8156af290 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
new file mode 100644 (file)
index 0000000..f28ecf7
--- /dev/null
@@ -0,0 +1,60 @@
+// 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.
+
+// Check that the hash for a method call is sensitive to the traits in
+// scope.
+
+// revisions: rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+fn test<T>() { }
+
+trait Trait1 {
+    fn method(&self) { }
+}
+
+impl Trait1 for () { }
+
+trait Trait2 {
+    fn method(&self) { }
+}
+
+impl Trait2 for () { }
+
+#[cfg(rpass1)]
+mod mod3 {
+    use Trait1;
+
+    fn bar() {
+        ().method();
+    }
+
+    fn baz() {
+        22; // no method call, traits in scope don't matter
+    }
+}
+
+#[cfg(rpass2)]
+mod mod3 {
+    use Trait2;
+
+    #[rustc_dirty(label="Hir", cfg="rpass2")]
+    fn bar() {
+        ().method();
+    }
+
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    fn baz() {
+        22; // no method call, traits in scope don't matter
+    }
+}
+
+fn main() { }
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
new file mode 100644 (file)
index 0000000..4466cfb
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+// Check that the hash of `foo` doesn't change just because we ordered
+// the nested items (or even added new ones).
+
+// revisions: rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+fn foo() {
+    fn bar() { }
+    fn baz() { }
+}
+
+#[cfg(rpass2)]
+#[rustc_clean(label="Hir", cfg="rpass2")]
+fn foo() {
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    fn baz() { } // order is different...
+
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    fn bar() { } // but that doesn't matter.
+
+    fn bap() { } // neither does adding a new item
+}
+
+fn main() { }
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
new file mode 100644 (file)
index 0000000..680a91d
--- /dev/null
@@ -0,0 +1,74 @@
+// 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.
+
+// Check that the hash for `mod3::bar` changes when we change the
+// `use` to something different.
+
+// revisions: rpass1 rpass2 rpass3
+
+#![feature(rustc_attrs)]
+
+fn test<T>() { }
+
+mod mod1 {
+    pub struct Foo(pub u32);
+}
+
+mod mod2 {
+    pub struct Foo(pub i64);
+}
+
+#[cfg(rpass1)]
+mod mod3 {
+    use test;
+    use mod1::Foo;
+
+    fn in_expr() {
+        Foo(0);
+    }
+
+    fn in_type() {
+        test::<Foo>();
+    }
+}
+
+#[cfg(rpass2)]
+mod mod3 {
+    use mod1::Foo; // <-- Nothing changed, but reordered!
+    use test;
+
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    fn in_expr() {
+        Foo(0);
+    }
+
+    #[rustc_clean(label="Hir", cfg="rpass2")]
+    fn in_type() {
+        test::<Foo>();
+    }
+}
+
+#[cfg(rpass3)]
+mod mod3 {
+    use test;
+    use mod2::Foo; // <-- This changed!
+
+    #[rustc_dirty(label="Hir", cfg="rpass3")]
+    fn in_expr() {
+        Foo(0);
+    }
+
+    #[rustc_dirty(label="Hir", cfg="rpass3")]
+    fn in_type() {
+        test::<Foo>();
+    }
+}
+
+fn main() { }
diff --git a/src/test/incremental/inlined_hir_34991/main.rs b/src/test/incremental/inlined_hir_34991/main.rs
new file mode 100644 (file)
index 0000000..a150a8c
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+// Regression test for #34991: an ICE occurred here because we inline
+// some of the vector routines and give them a local def-id `X`. This
+// got hashed after trans (`Hir(X)`). When we load back up, we get an
+// error because the `X` is remapped to the original def-id (in
+// libstd), and we can't hash a HIR node from std.
+
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+use std::vec::Vec;
+
+pub fn foo() -> Vec<i32> {
+    vec![1, 2, 3]
+}
+
+pub fn bar() {
+    foo();
+}
+
+pub fn main() {
+    bar();
+}
diff --git a/src/test/incremental/krate_reassign_34991/auxiliary/a.rs b/src/test/incremental/krate_reassign_34991/auxiliary/a.rs
new file mode 100644 (file)
index 0000000..8651560
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+#![crate_type="rlib"]
+
+pub type X = u32;
+
diff --git a/src/test/incremental/krate_reassign_34991/main.rs b/src/test/incremental/krate_reassign_34991/main.rs
new file mode 100644 (file)
index 0000000..1c80705
--- /dev/null
@@ -0,0 +1,30 @@
+// 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:a.rs
+// revisions:rpass1 rpass2
+
+#![feature(rustc_attrs)]
+
+#[cfg(rpass1)]
+extern crate a;
+
+#[cfg(rpass1)]
+pub fn use_X() -> u32 {
+    let x: a::X = 22;
+    x as u32
+}
+
+#[cfg(rpass2)]
+pub fn use_X() -> u32 {
+    22
+}
+
+pub fn main() { }
index 55398370425a3bcecedd4b3d0e12a8bee55d73a2..21b654bdf584bcda118c948979e413395621a0e7 100644 (file)
@@ -16,7 +16,7 @@
 // aux-build:a.rs
 // revisions:rpass1 rpass2 rpass3
 // no-prefer-dynamic
-
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index 68af20d41915159dcc778d9e028c50e1589567e5..257699cd3fce15b53a2d61ec02271eb1584858d8 100644 (file)
@@ -35,14 +35,10 @@ fn make() -> X {
         X { x: 11, y: 11 }
     }
 
-    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
-    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
     pub fn new() -> X {
         make()
     }
 
-    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
-    #[rustc_clean(label="ItemSignature", cfg="rpass2")]
     pub fn sum(x: &X) -> u32 {
         x.x + x.y
     }
@@ -51,7 +47,6 @@ pub fn sum(x: &X) -> u32 {
 mod y {
     use x;
 
-    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
     pub fn assert_sum() -> bool {
         let x = x::new();
         x::sum(&x) == 22
index 0aa728b94dda9634e818fdc6909f14a72454d52c..72072248ec05f2990c2bfe1e026e882319b32b6c 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // revisions: rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -40,8 +41,10 @@ pub fn x() {
 mod y {
     use x;
 
-    #[rustc_clean(label="TypeckItemBody", cfg="rpass2")]
-    #[rustc_clean(label="TransCrateItem", cfg="rpass2")]
+    // FIXME(#35078) -- when body of `x` changes, we treat it as
+    // though signature changed.
+    #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")]
+    #[rustc_dirty(label="TransCrateItem", cfg="rpass2")]
     pub fn y() {
         x::x();
     }
index cc8ef8aedd77bbcf4472c882ba6f45a9f830e525..da1b32cd73d6ebd2905d98625961c4fae4212b02 100644 (file)
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index fe29ad66b5fd8da5b8f4ee5621ef99cbfa251b17..ba469c62002e4da2f372eee3d77129507cc9fce4 100644 (file)
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 cfail2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index 1a50d515db6d07c08d568c23494b7279e2f9a19c..65f3b1b4f368f54cdf32ad748c437d4ab408999e 100644 (file)
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index 7a4900d1d9a903c5aedcd996ae4a13bdebaf87f6..95e15d0b7f9a070f1ea618e766f278dfd678548c 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index 8095e1ecd84a095cc1aca02506ed707981c23530..2bc636153f73522a823b38d144cd61eb7b4fe388 100644 (file)
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index ae6399463b81b138ebb25adb4221b9875aaa48da..a7ed79d1a5a35036eef6e822ccd64ede592eb9b2 100644 (file)
@@ -12,6 +12,7 @@
 // in between revisions (hashing should be stable).
 
 // revisions:rpass1 rpass2
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
index c5421fcbf5cb2310362327ad5ffe0f9e1e8b470e..09d4db331980dcaadd6961e24fd57b77b24c61e5 100644 (file)
@@ -10,6 +10,7 @@
 
 // aux-build:a.rs
 // revisions:rpass1 rpass2 rpass3
+// compile-flags: -Z query-dep-graph
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/mir-opt/deaggregator_test_enum.rs b/src/test/mir-opt/deaggregator_test_enum.rs
new file mode 100644 (file)
index 0000000..ccfa760
--- /dev/null
@@ -0,0 +1,45 @@
+// 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.
+
+enum Baz {
+    Empty,
+    Foo { x: usize },
+}
+
+fn bar(a: usize) -> Baz {
+    Baz::Foo { x: a }
+}
+
+fn main() {
+    let x = bar(10);
+    match x {
+        Baz::Empty => println!("empty"),
+        Baz::Foo { x } => println!("{}", x),
+    };
+}
+
+// END RUST SOURCE
+// START rustc.node10.Deaggregator.before.mir
+// bb0: {
+//     var0 = arg0;                     // scope 0 at main.rs:7:8: 7:9
+//     tmp0 = var0;                     // scope 1 at main.rs:8:19: 8:20
+//     return = Baz::Foo { x: tmp0 };   // scope 1 at main.rs:8:5: 8:21
+//     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
+// }
+// END rustc.node10.Deaggregator.before.mir
+// START rustc.node10.Deaggregator.after.mir
+// bb0: {
+//     var0 = arg0;                     // scope 0 at main.rs:7:8: 7:9
+//     tmp0 = var0;                     // scope 1 at main.rs:8:19: 8:20
+//     ((return as Foo).0: usize) = tmp0; // scope 1 at main.rs:8:5: 8:21
+//     discriminant(return) = 1;         // scope 1 at main.rs:8:5: 8:21
+//     goto -> bb1;                     // scope 1 at main.rs:7:1: 9:2
+// }
+// END rustc.node10.Deaggregator.after.mir
\ No newline at end of file
index 46be2385636952ef58cff581a3ef23a08286cae3..24ff20ea89242ef7f54009eec003a83d967f2de5 100644 (file)
@@ -2,4 +2,4 @@
 
 all:
        $(RUSTC) foo.rs --crate-type staticlib
-       $(RUSTC) bar.rs 2>&1 | grep "error: found staticlib"
+       $(RUSTC) bar.rs 2>&1 | grep "found staticlib"
index 0da4af34ef03d9ae30dd28a9200174f47f21ee55..239b689b52645b8a00fa63e798a4b13c67babc86 100644 (file)
@@ -27,7 +27,7 @@ all:
        mv $(TMPDIR)/$(call RLIB_GLOB,crateA) $(A3)
        # Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
        $(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
-       grep "error: found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
+       grep "found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
        grep "note: perhaps that crate needs to be recompiled?" $(LOG)
        grep "note: crate \`crateA\` path #1:" $(LOG)
        grep "note: crate \`crateA\` path #2:" $(LOG)
index 275658047d3cec690de04572d4da06eb3b09ef8c..4275c9b3f9fa341e30f06bdf76f9debda6a71eaa 100644 (file)
@@ -6,4 +6,4 @@ all:
        $(call REMOVE_RLIBS,crateA)
        # Ensure crateC fails to compile since dependency crateA is missing
        $(RUSTC) crateC.rs 2>&1 | \
-               grep "error: can't find crate for \`crateA\` which \`crateB\` depends on"
+               grep "can't find crate for \`crateA\` which \`crateB\` depends on"
diff --git a/src/test/run-make/unicode-input/Makefile b/src/test/run-make/unicode-input/Makefile
deleted file mode 100644 (file)
index f834a85..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
--include ../tools.mk
-
-# This test attempts to run rustc itself from the compiled binary; but
-# that means that you need to set the LD_LIBRARY_PATH for rustc itself
-# while running multiple_files, and that won't work for stage1.
-
-# FIXME ignore windows
-ifndef IS_WINDOWS
-ifeq ($(RUST_BUILD_STAGE),1)
-DOTEST=
-else
-DOTEST=dotest
-endif
-endif
-
-all: $(DOTEST)
-
-dotest:
-       # check that we don't ICE on unicode input, issue #11178
-       $(RUSTC) multiple_files.rs
-       $(call RUN,multiple_files)  "$(RUSTC)" "$(TMPDIR)"
-
-       # check that our multibyte-ident spans are (approximately) the
-       # correct length. issue #8706
-       $(RUSTC) span_length.rs
-       $(call RUN,span_length) "$(RUSTC)" "$(TMPDIR)"
diff --git a/src/test/run-make/unicode-input/multiple_files.rs b/src/test/run-make/unicode-input/multiple_files.rs
deleted file mode 100644 (file)
index b1fe938..0000000
+++ /dev/null
@@ -1,74 +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.
-
-#![feature(rand)]
-
-use std::fs::File;
-use std::io::prelude::*;
-use std::path::Path;
-use std::process::Command;
-use std::__rand::{thread_rng, Rng};
-use std::{char, env};
-
-// creates unicode_input_multiple_files_{main,chars}.rs, where the
-// former imports the latter. `_chars` just contains an identifier
-// made up of random characters, because will emit an error message
-// about the ident being in the wrong place, with a span (and creating
-// this span used to upset the compiler).
-
-fn random_char() -> char {
-    let mut rng = thread_rng();
-    // a subset of the XID_start Unicode table (ensuring that the
-    // compiler doesn't fail with an "unrecognised token" error)
-    let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
-        1 => (0x41, 0x5a),
-        2 => (0xf8, 0x1ba),
-        3 => (0x1401, 0x166c),
-        _ => (0x10400, 0x1044f)
-    };
-
-    char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let rustc = &args[1];
-    let tmpdir = Path::new(&args[2]);
-
-    let main_file = tmpdir.join("unicode_input_multiple_files_main.rs");
-    {
-        let _ = File::create(&main_file).unwrap()
-            .write_all(b"mod unicode_input_multiple_files_chars;").unwrap();
-    }
-
-    for _ in 0..100 {
-        {
-            let randoms = tmpdir.join("unicode_input_multiple_files_chars.rs");
-            let mut w = File::create(&randoms).unwrap();
-            for _ in 0..30 {
-                write!(&mut w, "{}", random_char()).unwrap();
-            }
-        }
-
-        // rustc is passed to us with --out-dir and -L etc., so we
-        // can't exec it directly
-        let result = Command::new("sh")
-                             .arg("-c")
-                             .arg(&format!("{} {}",
-                                           rustc,
-                                           main_file.display()))
-                             .output().unwrap();
-        let err = String::from_utf8_lossy(&result.stderr);
-
-        // positive test so that this test will be updated when the
-        // compiler changes.
-        assert!(err.contains("expected item, found"))
-    }
-}
diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs
deleted file mode 100644 (file)
index da8769e..0000000
+++ /dev/null
@@ -1,130 +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.
-
-#![feature(rand)]
-
-use std::fs::File;
-use std::io::prelude::*;
-use std::iter::repeat;
-use std::path::Path;
-use std::process::Command;
-use std::__rand::{thread_rng, Rng};
-use std::{char, env};
-
-pub fn check_old_skool() -> bool {
-    use std::env;
-    env::var("RUST_NEW_ERROR_FORMAT").is_err()
-}
-
-// creates a file with `fn main() { <random ident> }` and checks the
-// compiler emits a span of the appropriate length (for the
-// "unresolved name" message); currently just using the number of code
-// points, but should be the number of graphemes (FIXME #7043)
-
-fn random_char() -> char {
-    let mut rng = thread_rng();
-    // a subset of the XID_start Unicode table (ensuring that the
-    // compiler doesn't fail with an "unrecognised token" error)
-    let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
-        1 => (0x41, 0x5a),
-        2 => (0xf8, 0x1ba),
-        3 => (0x1401, 0x166c),
-        _ => (0x10400, 0x1044f)
-    };
-
-    char::from_u32(rng.gen_range(lo, hi + 1)).unwrap()
-}
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    let rustc = &args[1];
-    let tmpdir = Path::new(&args[2]);
-    let main_file = tmpdir.join("span_main.rs");
-
-    for _ in 0..100 {
-        let n = thread_rng().gen_range(3, 20);
-
-        {
-            let _ = write!(&mut File::create(&main_file).unwrap(),
-                           "#![feature(non_ascii_idents)] fn main() {{ {} }}",
-                           // random string of length n
-                           (0..n).map(|_| random_char()).collect::<String>());
-        }
-
-        // rustc is passed to us with --out-dir and -L etc., so we
-        // can't exec it directly
-        let result = Command::new("sh")
-                             .arg("-c")
-                             .arg(&format!("{} {}",
-                                           rustc,
-                                           main_file.to_str()
-                                                    .unwrap()))
-                             .output().unwrap();
-
-        let err = String::from_utf8_lossy(&result.stderr);
-
-        if check_old_skool() {
-            // the span should end the line (e.g no extra ~'s)
-            let expected_span = format!("^{}\n", repeat("~").take(n - 1)
-                                                            .collect::<String>());
-            assert!(err.contains(&expected_span));
-        } else {
-            // the span should end the line (e.g no extra ~'s)
-            let expected_span = format!("^{}\n", repeat("^").take(n - 1)
-                                                            .collect::<String>());
-            assert!(err.contains(&expected_span));
-        }
-    }
-
-    // Test multi-column characters and tabs
-    {
-        let _ = write!(&mut File::create(&main_file).unwrap(),
-                       r#"extern "路濫狼á́́" fn foo() {{}} extern "路濫狼á́" fn bar() {{}}"#);
-    }
-
-    let result = Command::new("sh")
-                         .arg("-c")
-                         .arg(format!("{} {}",
-                                      rustc,
-                                      main_file.display()))
-                         .output().unwrap();
-
-    let err = String::from_utf8_lossy(&result.stderr);
-
-    // Test both the length of the snake and the leading spaces up to it
-
-    if check_old_skool() {
-        // Extra characters. Every line is preceded by `filename:lineno <actual code>`
-        let offset = main_file.to_str().unwrap().len() + 3;
-
-        // First snake is 8 ~s long, with 7 preceding spaces (excluding file name/line offset)
-        let expected_span = format!("\n{}^{}\n",
-                                    repeat(" ").take(offset + 7).collect::<String>(),
-                                    repeat("~").take(8).collect::<String>());
-        assert!(err.contains(&expected_span));
-        // Second snake is only 7 ~s long, with 36 preceding spaces,
-        // because rustc counts chars() now rather than width(). This
-        // is because width() functions are to be removed from
-        // librustc_unicode
-        let expected_span = format!("\n{}^{}\n",
-                                    repeat(" ").take(offset + 36).collect::<String>(),
-                                    repeat("~").take(7).collect::<String>());
-        assert!(err.contains(&expected_span));
-    } else {
-        let expected_span = format!("\n  |>{}{}\n",
-                                    repeat(" ").take(8).collect::<String>(),
-                                    repeat("^").take(9).collect::<String>());
-        assert!(err.contains(&expected_span));
-        let expected_span = format!("\n  |>{}{}\n",
-                                    repeat(" ").take(37).collect::<String>(),
-                                    repeat("^").take(8).collect::<String>());
-        assert!(err.contains(&expected_span));
-    }
-}
index 5b1e210b0b2586b9449b341868910557cc1dbdb7..2b50c4fe11e9328f3bc5fb595d4c400018f33ff5 100644 (file)
@@ -36,7 +36,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
 
     let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) {
         Success(map) => {
-            match (&*map[&str_to_ident("matched").name], &*map[&str_to_ident("pat").name]) {
+            match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) {
                 (&MatchedNonterminal(NtExpr(ref matched_expr)),
                  &MatchedSeq(ref pats, seq_sp)) => {
                     let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt|
index 22f65c2b0d8f86470130de485c70d5f33d514e99..b599d7bee73defca8eb7261063c7ebcde99bf465 100644 (file)
@@ -8,10 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(relaxed_adts)]
+
 pub struct XEmpty1 {}
 pub struct XEmpty2;
+pub struct XEmpty7();
 
 pub enum XE {
     XEmpty3 {},
     XEmpty4,
+    XEmpty6(),
 }
diff --git a/src/test/run-pass/empty-struct-braces-gate-1.rs b/src/test/run-pass/empty-struct-braces-gate-1.rs
deleted file mode 100644 (file)
index 8287e15..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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 gate test for empty struct with braces
-// Can't define an empty braced struct
-
-struct Empty1 {}
-struct Empty2;
-
-enum E {
-    Empty4 {},
-    Empty5,
-}
-
-fn main() {
-}
diff --git a/src/test/run-pass/empty-struct-braces-gate-2.rs b/src/test/run-pass/empty-struct-braces-gate-2.rs
deleted file mode 100644 (file)
index 0ec3c89..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <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 gate test for empty struct with braces
-// Can't use braced expressions and patterns with structs defined without braces
-
-struct Empty2;
-
-enum E {
-    Empty5,
-}
-
-fn main() {
-    let e2: Empty2 = Empty2 {};
-    let e2: Empty2 = Empty2;
-    let e5: E = E::Empty5 {};
-    let e5: E = E::Empty5;
-
-    match e2 {
-        Empty2 {} => {}
-    }
-    match e2 {
-        Empty2 => {}
-    }
-    match e2 {
-        Empty2 { .. } => {}
-    }
-    match e5 {
-        E::Empty5 {} => {}
-    }
-    match e5 {
-        E::Empty5 => {}
-    }
-    match e5 {
-        E::Empty5 { .. } => {}
-    }
-
-    let e22 = Empty2 { ..e2 };
-}
index 0060150fbece01b90c07e411bfb31b4db4ae8a58..48966f24a2e5eca4afead2914955c92cf5ed0a94 100644 (file)
 
 // aux-build:empty-struct.rs
 
+#![feature(relaxed_adts)]
+
 extern crate empty_struct;
 use empty_struct::*;
 
 struct Empty1 {}
 struct Empty2;
+struct Empty7();
 
 #[derive(PartialEq, Eq)]
 struct Empty3 {}
@@ -27,6 +30,7 @@ struct Empty3 {}
 enum E {
     Empty4 {},
     Empty5,
+    Empty6(),
 }
 
 fn local() {
@@ -38,6 +42,12 @@ fn local() {
     let e4: E = E::Empty4 {};
     let e5: E = E::Empty5 {};
     let e5: E = E::Empty5;
+    let e6: E = E::Empty6 {};
+    let e6: E = E::Empty6();
+    let ctor6: fn() -> E = E::Empty6;
+    let e7: Empty7 = Empty7 {};
+    let e7: Empty7 = Empty7();
+    let ctor7: fn() -> Empty7 = Empty7;
 
     match e1 {
         Empty1 {} => {}
@@ -56,6 +66,13 @@ fn local() {
         E::Empty5 {} => {}
         _ => {}
     }
+    match e6 {
+        E::Empty6 {} => {}
+        _ => {}
+    }
+    match e7 {
+        Empty7 {} => {}
+    }
 
     match e1 {
         Empty1 { .. } => {}
@@ -74,6 +91,13 @@ fn local() {
         E::Empty5 { .. } => {}
         _ => {}
     }
+    match e6 {
+        E::Empty6 { .. } => {}
+        _ => {}
+    }
+    match e7 {
+        Empty7 { .. } => {}
+    }
 
     match e2 {
         Empty2 => {}
@@ -85,10 +109,25 @@ fn local() {
         E::Empty5 => {}
         _ => {}
     }
+    match e6 {
+        E::Empty6() => {}
+        _ => {}
+    }
+    match e6 {
+        E::Empty6(..) => {}
+        _ => {}
+    }
+    match e7 {
+        Empty7() => {}
+    }
+    match e7 {
+        Empty7(..) => {}
+    }
 
     let e11: Empty1 = Empty1 { ..e1 };
     let e22: Empty2 = Empty2 { ..e2 };
     let e33: Empty3 = Empty3 { ..e3 };
+    let e77: Empty7 = Empty7 { ..e7 };
 }
 
 fn xcrate() {
@@ -98,6 +137,12 @@ fn xcrate() {
     let e3: XE = XE::XEmpty3 {};
     let e4: XE = XE::XEmpty4 {};
     let e4: XE = XE::XEmpty4;
+    let e6: XE = XE::XEmpty6 {};
+    let e6: XE = XE::XEmpty6();
+    let ctor6: fn() -> XE = XE::XEmpty6;
+    let e7: XEmpty7 = XEmpty7 {};
+    let e7: XEmpty7 = XEmpty7();
+    let ctor7: fn() -> XEmpty7 = XEmpty7;
 
     match e1 {
         XEmpty1 {} => {}
@@ -113,6 +158,13 @@ fn xcrate() {
         XE::XEmpty4 {} => {}
         _ => {}
     }
+    match e6 {
+        XE::XEmpty6 {} => {}
+        _ => {}
+    }
+    match e7 {
+        XEmpty7 {} => {}
+    }
 
     match e1 {
         XEmpty1 { .. } => {}
@@ -128,6 +180,13 @@ fn xcrate() {
         XE::XEmpty4 { .. } => {}
         _ => {}
     }
+    match e6 {
+        XE::XEmpty6 { .. } => {}
+        _ => {}
+    }
+    match e7 {
+        XEmpty7 { .. } => {}
+    }
 
     match e2 {
         XEmpty2 => {}
@@ -136,9 +195,24 @@ fn xcrate() {
         XE::XEmpty4 => {}
         _ => {}
     }
+    match e6 {
+        XE::XEmpty6() => {}
+        _ => {}
+    }
+    match e6 {
+        XE::XEmpty6(..) => {}
+        _ => {}
+    }
+    match e7 {
+        XEmpty7() => {}
+    }
+    match e7 {
+        XEmpty7(..) => {}
+    }
 
     let e11: XEmpty1 = XEmpty1 { ..e1 };
     let e22: XEmpty2 = XEmpty2 { ..e2 };
+    let e77: XEmpty7 = XEmpty7 { ..e7 };
 }
 
 fn main() {
diff --git a/src/test/run-pass/impl-trait/auto-trait-leak.rs b/src/test/run-pass/impl-trait/auto-trait-leak.rs
new file mode 100644 (file)
index 0000000..c1201e7
--- /dev/null
@@ -0,0 +1,44 @@
+// 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(conservative_impl_trait)]
+
+// Fast path, main can see the concrete type returned.
+fn before() -> impl FnMut(i32) {
+    let mut p = Box::new(0);
+    move |x| *p = x
+}
+
+fn send<T: Send>(_: T) {}
+
+fn main() {
+    send(before());
+    send(after());
+}
+
+// Deferred path, main has to wait until typeck finishes,
+// to check if the return type of after is Send.
+fn after() -> impl FnMut(i32) {
+    let mut p = Box::new(0);
+    move |x| *p = x
+}
+
+// Cycles should work as the deferred obligations are
+// independently resolved and only require the concrete
+// return type, which can't depend on the obligation.
+fn cycle1() -> impl Clone {
+    send(cycle2().clone());
+    5
+}
+
+fn cycle2() -> impl Clone {
+    send(cycle1().clone());
+    String::from("foo")
+}
diff --git a/src/test/run-pass/impl-trait/equality.rs b/src/test/run-pass/impl-trait/equality.rs
new file mode 100644 (file)
index 0000000..72b0e58
--- /dev/null
@@ -0,0 +1,43 @@
+// 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(conservative_impl_trait, specialization)]
+
+trait Foo: std::fmt::Debug + Eq {}
+
+impl<T: std::fmt::Debug + Eq> Foo for T {}
+
+fn hide<T: Foo>(x: T) -> impl Foo {
+    x
+}
+
+trait Leak<T>: Sized {
+    fn leak(self) -> T;
+}
+impl<T, U> Leak<T> for U {
+    default fn leak(self) -> T { panic!("type mismatch") }
+}
+impl<T> Leak<T> for T {
+    fn leak(self) -> T { self }
+}
+
+fn lucky_seven() -> impl Fn(usize) -> u8 {
+    let a = [1, 2, 3, 4, 5, 6, 7];
+    move |i| a[i]
+}
+
+fn main() {
+    assert_eq!(hide(42), hide(42));
+
+    assert_eq!(std::mem::size_of_val(&hide([0_u8; 5])), 5);
+    assert_eq!(std::mem::size_of_val(&lucky_seven()), 7);
+
+    assert_eq!(Leak::<i32>::leak(hide(5_i32)), 5_i32);
+}
diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs
new file mode 100644 (file)
index 0000000..2a9af26
--- /dev/null
@@ -0,0 +1,929 @@
+// 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(conservative_impl_trait, fn_traits, step_trait, unboxed_closures)]
+
+//! Derived from: <https://raw.githubusercontent.com/quickfur/dcal/master/dcal.d>.
+//!
+//! Originally converted to Rust by [Daniel Keep](https://github.com/DanielKeep).
+
+use std::fmt::Write;
+use std::mem;
+
+/// Date representation.
+#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+struct NaiveDate(i32, u32, u32);
+
+impl NaiveDate {
+    pub fn from_ymd(y: i32, m: u32, d: u32) -> NaiveDate {
+        assert!(1 <= m && m <= 12, "m = {:?}", m);
+        assert!(1 <= d && d <= NaiveDate(y, m, 1).days_in_month(), "d = {:?}", d);
+        NaiveDate(y, m, d)
+    }
+
+    pub fn year(&self) -> i32 {
+        self.0
+    }
+
+    pub fn month(&self) -> u32 {
+        self.1
+    }
+
+    pub fn day(&self) -> u32 {
+        self.2
+    }
+
+    pub fn succ(&self) -> NaiveDate {
+        let (mut y, mut m, mut d, n) = (
+            self.year(), self.month(), self.day()+1, self.days_in_month());
+        if d > n {
+            d = 1;
+            m += 1;
+        }
+        if m > 12 {
+            m = 1;
+            y += 1;
+        }
+        NaiveDate::from_ymd(y, m, d)
+    }
+
+    pub fn weekday(&self) -> Weekday {
+        use Weekday::*;
+
+        // 0 = Sunday
+        let year = self.year();
+        let dow_jan_1 = (year*365 + ((year-1) / 4) - ((year-1) / 100) + ((year-1) / 400)) % 7;
+        let dow = (dow_jan_1 + (self.day_of_year() as i32 - 1)) % 7;
+        [Sun, Mon, Tue, Wed, Thu, Fri, Sat][dow as usize]
+    }
+
+    pub fn isoweekdate(&self) -> (i32, u32, Weekday) {
+        let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday();
+
+        // Work out this date's DOtY and week number, not including year adjustment.
+        let doy_0 = self.day_of_year() - 1;
+        let mut week_mon_0: i32 = ((first_dow_mon_0 + doy_0) / 7) as i32;
+
+        if self.first_week_in_prev_year() {
+            week_mon_0 -= 1;
+        }
+
+        let weeks_in_year = self.last_week_number();
+
+        // Work out the final result.
+        // If the week is -1 or >= weeks_in_year, we will need to adjust the year.
+        let year = self.year();
+        let wd = self.weekday();
+
+        if week_mon_0 < 0 {
+            (year - 1, NaiveDate::from_ymd(year - 1, 1, 1).last_week_number(), wd)
+        } else if week_mon_0 >= weeks_in_year as i32 {
+            (year + 1, (week_mon_0 + 1 - weeks_in_year as i32) as u32, wd)
+        } else {
+            (year, (week_mon_0 + 1) as u32, wd)
+        }
+    }
+
+    fn first_week_in_prev_year(&self) -> bool {
+        let first_dow_mon_0 = self.year_first_day_of_week().num_days_from_monday();
+
+        // Any day in the year *before* the first Monday of that year
+        // is considered to be in the last week of the previous year,
+        // assuming the first week has *less* than four days in it.
+        // Adjust the week appropriately.
+        ((7 - first_dow_mon_0) % 7) < 4
+    }
+
+    fn year_first_day_of_week(&self) -> Weekday {
+        NaiveDate::from_ymd(self.year(), 1, 1).weekday()
+    }
+
+    fn weeks_in_year(&self) -> u32 {
+        let days_in_last_week = self.year_first_day_of_week().num_days_from_monday() + 1;
+        if days_in_last_week >= 4 { 53 } else { 52 }
+    }
+
+    fn last_week_number(&self) -> u32 {
+        let wiy = self.weeks_in_year();
+        if self.first_week_in_prev_year() { wiy - 1 } else { wiy }
+    }
+
+    fn day_of_year(&self) -> u32 {
+        (1..self.1).map(|m| NaiveDate::from_ymd(self.year(), m, 1).days_in_month())
+            .fold(0, |a,b| a+b) + self.day()
+    }
+
+    fn is_leap_year(&self) -> bool {
+        let year = self.year();
+        if year % 4 != 0 {
+            return false
+        } else if year % 100 != 0 {
+            return true
+        } else if year % 400 != 0 {
+            return false
+        } else {
+            return true
+        }
+    }
+
+    fn days_in_month(&self) -> u32 {
+        match self.month() {
+            /* Jan */ 1 => 31,
+            /* Feb */ 2 => if self.is_leap_year() { 29 } else { 28 },
+            /* Mar */ 3 => 31,
+            /* Apr */ 4 => 30,
+            /* May */ 5 => 31,
+            /* Jun */ 6 => 30,
+            /* Jul */ 7 => 31,
+            /* Aug */ 8 => 31,
+            /* Sep */ 9 => 30,
+            /* Oct */ 10 => 31,
+            /* Nov */ 11 => 30,
+            /* Dec */ 12 => 31,
+            _ => unreachable!()
+        }
+    }
+}
+
+impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate {
+    type Output = NaiveDate;
+
+    fn add(self, other: &'b NaiveDate) -> NaiveDate {
+        assert_eq!(*other, NaiveDate(0, 0, 1));
+        self.succ()
+    }
+}
+
+impl std::iter::Step for NaiveDate {
+    fn step(&self, by: &Self) -> Option<Self> {
+        Some(self + by)
+    }
+
+    fn steps_between(_: &Self, _: &Self, _: &Self) -> Option<usize> {
+        unimplemented!()
+    }
+
+    fn steps_between_by_one(_: &Self, _: &Self) -> Option<usize> {
+        unimplemented!()
+    }
+
+    fn is_negative(&self) -> bool {
+        false
+    }
+
+    fn replace_one(&mut self) -> Self {
+        mem::replace(self, NaiveDate(0, 0, 1))
+    }
+
+    fn replace_zero(&mut self) -> Self {
+        mem::replace(self, NaiveDate(0, 0, 0))
+    }
+
+    fn add_one(&self) -> Self {
+        self.succ()
+    }
+
+    fn sub_one(&self) -> Self {
+        unimplemented!()
+    }
+}
+
+#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum Weekday {
+    Mon,
+    Tue,
+    Wed,
+    Thu,
+    Fri,
+    Sat,
+    Sun,
+}
+
+impl Weekday {
+    pub fn num_days_from_monday(&self) -> u32 {
+        use Weekday::*;
+        match *self {
+            Mon => 0,
+            Tue => 1,
+            Wed => 2,
+            Thu => 3,
+            Fri => 4,
+            Sat => 5,
+            Sun => 6,
+        }
+    }
+
+    pub fn num_days_from_sunday(&self) -> u32 {
+        use Weekday::*;
+        match *self {
+            Sun => 0,
+            Mon => 1,
+            Tue => 2,
+            Wed => 3,
+            Thu => 4,
+            Fri => 5,
+            Sat => 6,
+        }
+    }
+}
+
+/// Wrapper for zero-sized closures.
+// HACK(eddyb) Only needed because closures can't implement Copy.
+struct Fn0<F>(std::marker::PhantomData<F>);
+
+impl<F> Copy for Fn0<F> {}
+impl<F> Clone for Fn0<F> {
+    fn clone(&self) -> Self { *self }
+}
+
+impl<F: FnOnce<A>, A> FnOnce<A> for Fn0<F> {
+    type Output = F::Output;
+
+    extern "rust-call" fn call_once(self, args: A) -> Self::Output {
+        let f = unsafe { std::mem::uninitialized::<F>() };
+        f.call_once(args)
+    }
+}
+
+impl<F: FnMut<A>, A> FnMut<A> for Fn0<F> {
+    extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output {
+        let mut f = unsafe { std::mem::uninitialized::<F>() };
+        f.call_mut(args)
+    }
+}
+
+trait AsFn0<A>: Sized {
+    fn copyable(self) -> Fn0<Self>;
+}
+
+impl<F: FnMut<A>, A> AsFn0<A> for F {
+    fn copyable(self) -> Fn0<Self> {
+        assert_eq!(std::mem::size_of::<F>(), 0);
+        Fn0(std::marker::PhantomData)
+    }
+}
+
+/// GroupBy implementation.
+struct GroupBy<It: Iterator, F> {
+    it: std::iter::Peekable<It>,
+    f: F,
+}
+
+impl<It, F> Clone for GroupBy<It, F>
+where It: Iterator + Clone, It::Item: Clone, F: Clone {
+    fn clone(&self) -> GroupBy<It, F> {
+        GroupBy {
+            it: self.it.clone(),
+            f: self.f.clone()
+        }
+    }
+}
+
+impl<'a, G, It: 'a, F: 'a> Iterator for GroupBy<It, F>
+where It: Iterator + Clone,
+      It::Item: Clone,
+      F: Clone + FnMut(&It::Item) -> G,
+      G: Eq + Clone
+{
+    type Item = (G, InGroup<std::iter::Peekable<It>, F, G>);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.it.peek().map(&mut self.f).map(|key| {
+            let start = self.it.clone();
+            while let Some(k) = self.it.peek().map(&mut self.f) {
+                if key != k {
+                    break;
+                }
+                self.it.next();
+            }
+
+            (key.clone(), InGroup {
+                it: start,
+                f: self.f.clone(),
+                g: key
+            })
+        })
+    }
+}
+
+#[derive(Copy, Clone)]
+struct InGroup<It, F, G> {
+    it: It,
+    f: F,
+    g: G
+}
+
+impl<It: Iterator, F: FnMut(&It::Item) -> G, G: Eq> Iterator for InGroup<It, F, G> {
+    type Item = It::Item;
+
+    fn next(&mut self) -> Option<It::Item> {
+        self.it.next().and_then(|x| {
+            if (self.f)(&x) == self.g { Some(x) } else { None }
+        })
+    }
+}
+
+trait IteratorExt: Iterator + Sized {
+    fn group_by<G, F>(self, f: F) -> GroupBy<Self, Fn0<F>>
+    where F: FnMut(&Self::Item) -> G,
+          G: Eq
+    {
+        GroupBy {
+            it: self.peekable(),
+            f: f.copyable(),
+        }
+    }
+
+    fn join(mut self, sep: &str) -> String
+    where Self::Item: std::fmt::Display {
+        let mut s = String::new();
+        if let Some(e) = self.next() {
+            write!(s, "{}", e);
+            for e in self {
+                s.push_str(sep);
+                write!(s, "{}", e);
+            }
+        }
+        s
+    }
+
+    // HACK(eddyb) Only needed because `impl Trait` can't be
+    // used with trait methods: `.foo()` becomes `.__(foo)`.
+    fn __<F, R>(self, f: F) -> R
+    where F: FnOnce(Self) -> R {
+        f(self)
+    }
+}
+
+impl<It> IteratorExt for It where It: Iterator {}
+
+///
+/// Generates an iterator that yields exactly n spaces.
+///
+fn spaces(n: usize) -> std::iter::Take<std::iter::Repeat<char>> {
+    std::iter::repeat(' ').take(n)
+}
+
+fn test_spaces() {
+    assert_eq!(spaces(0).collect::<String>(), "");
+    assert_eq!(spaces(10).collect::<String>(), "          ")
+}
+
+///
+/// Returns an iterator of dates in a given year.
+///
+fn dates_in_year(year: i32) -> impl Iterator<Item=NaiveDate>+Clone {
+    InGroup {
+        it: NaiveDate::from_ymd(year, 1, 1)..,
+        f: (|d: &NaiveDate| d.year()).copyable(),
+        g: year
+    }
+}
+
+fn test_dates_in_year() {
+    {
+        let mut dates = dates_in_year(2013);
+        assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 1)));
+
+        // Check increment
+        assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 2)));
+
+        // Check monthly rollover
+        for _ in 3..31 {
+            assert!(dates.next() != None);
+        }
+
+        assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 1, 31)));
+        assert_eq!(dates.next(), Some(NaiveDate::from_ymd(2013, 2, 1)));
+    }
+
+    {
+        // Check length of year
+        let mut dates = dates_in_year(2013);
+        for _ in 0..365 {
+            assert!(dates.next() != None);
+        }
+        assert_eq!(dates.next(), None);
+    }
+
+    {
+        // Check length of leap year
+        let mut dates = dates_in_year(1984);
+        for _ in 0..366 {
+            assert!(dates.next() != None);
+        }
+        assert_eq!(dates.next(), None);
+    }
+}
+
+///
+/// Convenience trait for verifying that a given type iterates over
+/// `NaiveDate`s.
+///
+trait DateIterator: Iterator<Item=NaiveDate> + Clone {}
+impl<It> DateIterator for It where It: Iterator<Item=NaiveDate> + Clone {}
+
+fn test_group_by() {
+    let input = [
+        [1, 1],
+        [1, 1],
+        [1, 2],
+        [2, 2],
+        [2, 3],
+        [2, 3],
+        [3, 3]
+    ];
+
+    let by_x = input.iter().cloned().group_by(|a| a[0]);
+    let expected_1: &[&[[i32; 2]]] = &[
+        &[[1, 1], [1, 1], [1, 2]],
+        &[[2, 2], [2, 3], [2, 3]],
+        &[[3, 3]]
+    ];
+    for ((_, a), b) in by_x.zip(expected_1.iter().cloned()) {
+        assert_eq!(&a.collect::<Vec<_>>()[..], b);
+    }
+
+    let by_y = input.iter().cloned().group_by(|a| a[1]);
+    let expected_2: &[&[[i32; 2]]] = &[
+        &[[1, 1], [1, 1]],
+        &[[1, 2], [2, 2]],
+        &[[2, 3], [2, 3], [3, 3]]
+    ];
+    for ((_, a), b) in by_y.zip(expected_2.iter().cloned()) {
+        assert_eq!(&a.collect::<Vec<_>>()[..], b);
+    }
+}
+
+///
+/// Groups an iterator of dates by month.
+///
+fn by_month<It>(it: It)
+                ->  impl Iterator<Item=(u32, impl Iterator<Item=NaiveDate> + Clone)> + Clone
+where It: Iterator<Item=NaiveDate> + Clone {
+    it.group_by(|d| d.month())
+}
+
+fn test_by_month() {
+    let mut months = dates_in_year(2013).__(by_month);
+    for (month, (_, mut date)) in (1..13).zip(&mut months) {
+        assert_eq!(date.nth(0).unwrap(), NaiveDate::from_ymd(2013, month, 1));
+    }
+    assert!(months.next().is_none());
+}
+
+///
+/// Groups an iterator of dates by week.
+///
+fn by_week<It>(it: It)
+               -> impl Iterator<Item=(u32, impl DateIterator)> + Clone
+where It: DateIterator {
+    // We go forward one day because `isoweekdate` considers the week to start on a Monday.
+    it.group_by(|d| d.succ().isoweekdate().1)
+}
+
+fn test_isoweekdate() {
+    fn weeks_uniq(year: i32) -> Vec<((i32, u32), u32)> {
+        let mut weeks = dates_in_year(year).map(|d| d.isoweekdate())
+            .map(|(y,w,_)| (y,w));
+        let mut result = vec![];
+        let mut accum = (weeks.next().unwrap(), 1);
+        for yw in weeks {
+            if accum.0 == yw {
+                accum.1 += 1;
+            } else {
+                result.push(accum);
+                accum = (yw, 1);
+            }
+        }
+        result.push(accum);
+        result
+    }
+
+    let wu_1984 = weeks_uniq(1984);
+    assert_eq!(&wu_1984[..2], &[((1983, 52), 1), ((1984, 1), 7)]);
+    assert_eq!(&wu_1984[wu_1984.len()-2..], &[((1984, 52), 7), ((1985, 1), 1)]);
+
+    let wu_2013 = weeks_uniq(2013);
+    assert_eq!(&wu_2013[..2], &[((2013, 1), 6), ((2013, 2), 7)]);
+    assert_eq!(&wu_2013[wu_2013.len()-2..], &[((2013, 52), 7), ((2014, 1), 2)]);
+
+    let wu_2015 = weeks_uniq(2015);
+    assert_eq!(&wu_2015[..2], &[((2015, 1), 4), ((2015, 2), 7)]);
+    assert_eq!(&wu_2015[wu_2015.len()-2..], &[((2015, 52), 7), ((2015, 53), 4)]);
+}
+
+fn test_by_week() {
+    let mut weeks = dates_in_year(2013).__(by_week);
+    assert_eq!(
+        &*weeks.next().unwrap().1.collect::<Vec<_>>(),
+        &[
+            NaiveDate::from_ymd(2013, 1, 1),
+            NaiveDate::from_ymd(2013, 1, 2),
+            NaiveDate::from_ymd(2013, 1, 3),
+            NaiveDate::from_ymd(2013, 1, 4),
+            NaiveDate::from_ymd(2013, 1, 5),
+        ]
+    );
+    assert_eq!(
+        &*weeks.next().unwrap().1.collect::<Vec<_>>(),
+        &[
+            NaiveDate::from_ymd(2013, 1, 6),
+            NaiveDate::from_ymd(2013, 1, 7),
+            NaiveDate::from_ymd(2013, 1, 8),
+            NaiveDate::from_ymd(2013, 1, 9),
+            NaiveDate::from_ymd(2013, 1, 10),
+            NaiveDate::from_ymd(2013, 1, 11),
+            NaiveDate::from_ymd(2013, 1, 12),
+        ]
+    );
+    assert_eq!(weeks.next().unwrap().1.nth(0).unwrap(), NaiveDate::from_ymd(2013, 1, 13));
+}
+
+/// The number of columns per day in the formatted output.
+const COLS_PER_DAY: u32 = 3;
+
+/// The number of columns per week in the formatted output.
+const COLS_PER_WEEK: u32 = 7 * COLS_PER_DAY;
+
+///
+/// Formats an iterator of weeks into an iterator of strings.
+///
+fn format_weeks<It>(it: It) -> impl Iterator<Item=String>
+where It: Iterator, It::Item: DateIterator {
+    it.map(|week| {
+        let mut buf = String::with_capacity((COLS_PER_DAY * COLS_PER_WEEK + 2) as usize);
+
+        // Format each day into its own cell and append to target string.
+        let mut last_day = 0;
+        let mut first = true;
+        for d in week {
+            last_day = d.weekday().num_days_from_sunday();
+
+            // Insert enough filler to align the first day with its respective day-of-week.
+            if first {
+                buf.extend(spaces((COLS_PER_DAY * last_day) as usize));
+                first = false;
+            }
+
+            write!(buf, " {:>2}", d.day());
+        }
+
+        // Insert more filler at the end to fill up the remainder of the week,
+        // if its a short week (e.g. at the end of the month).
+        buf.extend(spaces((COLS_PER_DAY * (6 - last_day)) as usize));
+        buf
+    })
+}
+
+fn test_format_weeks() {
+    let jan_2013 = dates_in_year(2013)
+        .__(by_month).next() // pick January 2013 for testing purposes
+        // NOTE: This `map` is because `next` returns an `Option<_>`.
+        .map(|(_, month)|
+            month.__(by_week)
+                 .map(|(_, weeks)| weeks)
+                 .__(format_weeks)
+                 .join("\n"));
+
+    assert_eq!(
+        jan_2013.as_ref().map(|s| &**s),
+        Some("        1  2  3  4  5\n\
+           \x20 6  7  8  9 10 11 12\n\
+           \x2013 14 15 16 17 18 19\n\
+           \x2020 21 22 23 24 25 26\n\
+           \x2027 28 29 30 31      ")
+    );
+}
+
+///
+/// Formats the name of a month, centered on COLS_PER_WEEK.
+///
+fn month_title(month: u32) -> String {
+    const MONTH_NAMES: &'static [&'static str] = &[
+        "January", "February", "March", "April", "May", "June",
+        "July", "August", "September", "October", "November", "December"
+    ];
+    assert_eq!(MONTH_NAMES.len(), 12);
+
+    // Determine how many spaces before and after the month name
+    // we need to center it over the formatted weeks in the month.
+    let name = MONTH_NAMES[(month - 1) as usize];
+    assert!(name.len() < COLS_PER_WEEK as usize);
+    let before = (COLS_PER_WEEK as usize - name.len()) / 2;
+    let after = COLS_PER_WEEK as usize - name.len() - before;
+
+    // NOTE: Being slightly more verbose to avoid extra allocations.
+    let mut result = String::with_capacity(COLS_PER_WEEK as usize);
+    result.extend(spaces(before));
+    result.push_str(name);
+    result.extend(spaces(after));
+    result
+}
+
+fn test_month_title() {
+    assert_eq!(month_title(1).len(), COLS_PER_WEEK as usize);
+}
+
+///
+/// Formats a month.
+///
+fn format_month<It: DateIterator>(it: It) -> impl Iterator<Item=String> {
+    let mut month_days = it.peekable();
+    let title = month_title(month_days.peek().unwrap().month());
+
+    Some(title).into_iter()
+        .chain(month_days.__(by_week)
+            .map(|(_, week)| week)
+            .__(format_weeks))
+}
+
+fn test_format_month() {
+    let month_fmt = dates_in_year(2013)
+        .__(by_month).next() // Pick January as a test case
+        .map(|(_, days)| days.into_iter()
+            .__(format_month)
+            .join("\n"));
+
+    assert_eq!(
+        month_fmt.as_ref().map(|s| &**s),
+        Some("       January       \n\
+           \x20       1  2  3  4  5\n\
+           \x20 6  7  8  9 10 11 12\n\
+           \x2013 14 15 16 17 18 19\n\
+           \x2020 21 22 23 24 25 26\n\
+           \x2027 28 29 30 31      ")
+    );
+}
+
+
+///
+/// Formats an iterator of months.
+///
+fn format_months<It>(it: It) -> impl Iterator<Item=impl Iterator<Item=String>>
+where It: Iterator, It::Item: DateIterator {
+    it.map(format_month)
+}
+
+///
+/// Takes an iterator of iterators of strings; the sub-iterators are consumed
+/// in lock-step, with their elements joined together.
+///
+trait PasteBlocks: Iterator + Sized
+where Self::Item: Iterator<Item=String> {
+    fn paste_blocks(self, sep_width: usize) -> PasteBlocksIter<Self::Item> {
+        PasteBlocksIter {
+            iters: self.collect(),
+            cache: vec![],
+            col_widths: None,
+            sep_width: sep_width,
+        }
+    }
+}
+
+impl<It> PasteBlocks for It where It: Iterator, It::Item: Iterator<Item=String> {}
+
+struct PasteBlocksIter<StrIt>
+where StrIt: Iterator<Item=String> {
+    iters: Vec<StrIt>,
+    cache: Vec<Option<String>>,
+    col_widths: Option<Vec<usize>>,
+    sep_width: usize,
+}
+
+impl<StrIt> Iterator for PasteBlocksIter<StrIt>
+where StrIt: Iterator<Item=String> {
+    type Item = String;
+
+    fn next(&mut self) -> Option<String> {
+        self.cache.clear();
+
+        // `cache` is now the next line from each iterator.
+        self.cache.extend(self.iters.iter_mut().map(|it| it.next()));
+
+        // If every line in `cache` is `None`, we have nothing further to do.
+        if self.cache.iter().all(|e| e.is_none()) { return None }
+
+        // Get the column widths if we haven't already.
+        let col_widths = match self.col_widths {
+            Some(ref v) => &**v,
+            None => {
+                self.col_widths = Some(self.cache.iter()
+                    .map(|ms| ms.as_ref().map(|s| s.len()).unwrap_or(0))
+                    .collect());
+                &**self.col_widths.as_ref().unwrap()
+            }
+        };
+
+        // Fill in any `None`s with spaces.
+        let mut parts = col_widths.iter().cloned().zip(self.cache.iter_mut())
+            .map(|(w,ms)| ms.take().unwrap_or_else(|| spaces(w).collect()));
+
+        // Join them all together.
+        let first = parts.next().unwrap_or(String::new());
+        let sep_width = self.sep_width;
+        Some(parts.fold(first, |mut accum, next| {
+            accum.extend(spaces(sep_width));
+            accum.push_str(&next);
+            accum
+        }))
+    }
+}
+
+fn test_paste_blocks() {
+    let row = dates_in_year(2013)
+        .__(by_month).map(|(_, days)| days)
+        .take(3)
+        .__(format_months)
+        .paste_blocks(1)
+        .join("\n");
+    assert_eq!(
+        &*row,
+        "       January              February                March        \n\
+      \x20       1  2  3  4  5                  1  2                  1  2\n\
+      \x20 6  7  8  9 10 11 12   3  4  5  6  7  8  9   3  4  5  6  7  8  9\n\
+      \x2013 14 15 16 17 18 19  10 11 12 13 14 15 16  10 11 12 13 14 15 16\n\
+      \x2020 21 22 23 24 25 26  17 18 19 20 21 22 23  17 18 19 20 21 22 23\n\
+      \x2027 28 29 30 31        24 25 26 27 28        24 25 26 27 28 29 30\n\
+      \x20                                            31                  "
+    );
+}
+
+///
+/// Produces an iterator that yields `n` elements at a time.
+///
+trait Chunks: Iterator + Sized {
+    fn chunks(self, n: usize) -> ChunksIter<Self> {
+        assert!(n > 0);
+        ChunksIter {
+            it: self,
+            n: n,
+        }
+    }
+}
+
+impl<It> Chunks for It where It: Iterator {}
+
+struct ChunksIter<It>
+where It: Iterator {
+    it: It,
+    n: usize,
+}
+
+// NOTE: `chunks` in Rust is more-or-less impossible without overhead of some kind.
+// Aliasing rules mean you need to add dynamic borrow checking, and the design of
+// `Iterator` means that you need to have the iterator's state kept in an allocation
+// that is jointly owned by the iterator itself and the sub-iterator.
+// As such, I've chosen to cop-out and just heap-allocate each chunk.
+
+impl<It> Iterator for ChunksIter<It>
+where It: Iterator {
+    type Item = Vec<It::Item>;
+
+    fn next(&mut self) -> Option<Vec<It::Item>> {
+        let first = match self.it.next() {
+            Some(e) => e,
+            None => return None
+        };
+
+        let mut result = Vec::with_capacity(self.n);
+        result.push(first);
+
+        Some((&mut self.it).take(self.n-1)
+            .fold(result, |mut acc, next| { acc.push(next); acc }))
+    }
+}
+
+fn test_chunks() {
+    let r = &[1, 2, 3, 4, 5, 6, 7];
+    let c = r.iter().cloned().chunks(3).collect::<Vec<_>>();
+    assert_eq!(&*c, &[vec![1, 2, 3], vec![4, 5, 6], vec![7]]);
+}
+
+///
+/// Formats a year.
+///
+fn format_year(year: i32, months_per_row: usize) -> String {
+    const COL_SPACING: usize = 1;
+
+    // Start by generating all dates for the given year.
+    dates_in_year(year)
+
+        // Group them by month and throw away month number.
+        .__(by_month).map(|(_, days)| days)
+
+        // Group the months into horizontal rows.
+        .chunks(months_per_row)
+
+        // Format each row
+        .map(|r| r.into_iter()
+            // By formatting each month
+            .__(format_months)
+
+            // Horizontally pasting each respective month's lines together.
+            .paste_blocks(COL_SPACING)
+            .join("\n")
+        )
+
+        // Insert a blank line between each row
+        .join("\n\n")
+}
+
+fn test_format_year() {
+    const MONTHS_PER_ROW: usize = 3;
+
+    macro_rules! assert_eq_cal {
+        ($lhs:expr, $rhs:expr) => {
+            if $lhs != $rhs {
+                println!("got:\n```\n{}\n```\n", $lhs.replace(" ", "."));
+                println!("expected:\n```\n{}\n```", $rhs.replace(" ", "."));
+                panic!("calendars didn't match!");
+            }
+        }
+    }
+
+    assert_eq_cal!(&format_year(1984, MONTHS_PER_ROW), "\
+\x20      January              February                March        \n\
+\x20 1  2  3  4  5  6  7            1  2  3  4               1  2  3\n\
+\x20 8  9 10 11 12 13 14   5  6  7  8  9 10 11   4  5  6  7  8  9 10\n\
+\x2015 16 17 18 19 20 21  12 13 14 15 16 17 18  11 12 13 14 15 16 17\n\
+\x2022 23 24 25 26 27 28  19 20 21 22 23 24 25  18 19 20 21 22 23 24\n\
+\x2029 30 31              26 27 28 29           25 26 27 28 29 30 31\n\
+\n\
+\x20       April                  May                  June         \n\
+\x20 1  2  3  4  5  6  7         1  2  3  4  5                  1  2\n\
+\x20 8  9 10 11 12 13 14   6  7  8  9 10 11 12   3  4  5  6  7  8  9\n\
+\x2015 16 17 18 19 20 21  13 14 15 16 17 18 19  10 11 12 13 14 15 16\n\
+\x2022 23 24 25 26 27 28  20 21 22 23 24 25 26  17 18 19 20 21 22 23\n\
+\x2029 30                 27 28 29 30 31        24 25 26 27 28 29 30\n\
+\n\
+\x20       July                 August               September      \n\
+\x20 1  2  3  4  5  6  7            1  2  3  4                     1\n\
+\x20 8  9 10 11 12 13 14   5  6  7  8  9 10 11   2  3  4  5  6  7  8\n\
+\x2015 16 17 18 19 20 21  12 13 14 15 16 17 18   9 10 11 12 13 14 15\n\
+\x2022 23 24 25 26 27 28  19 20 21 22 23 24 25  16 17 18 19 20 21 22\n\
+\x2029 30 31              26 27 28 29 30 31     23 24 25 26 27 28 29\n\
+\x20                                            30                  \n\
+\n\
+\x20      October              November              December       \n\
+\x20    1  2  3  4  5  6               1  2  3                     1\n\
+\x20 7  8  9 10 11 12 13   4  5  6  7  8  9 10   2  3  4  5  6  7  8\n\
+\x2014 15 16 17 18 19 20  11 12 13 14 15 16 17   9 10 11 12 13 14 15\n\
+\x2021 22 23 24 25 26 27  18 19 20 21 22 23 24  16 17 18 19 20 21 22\n\
+\x2028 29 30 31           25 26 27 28 29 30     23 24 25 26 27 28 29\n\
+\x20                                            30 31               ");
+
+    assert_eq_cal!(&format_year(2015, MONTHS_PER_ROW), "\
+\x20      January              February                March        \n\
+\x20             1  2  3   1  2  3  4  5  6  7   1  2  3  4  5  6  7\n\
+\x20 4  5  6  7  8  9 10   8  9 10 11 12 13 14   8  9 10 11 12 13 14\n\
+\x2011 12 13 14 15 16 17  15 16 17 18 19 20 21  15 16 17 18 19 20 21\n\
+\x2018 19 20 21 22 23 24  22 23 24 25 26 27 28  22 23 24 25 26 27 28\n\
+\x2025 26 27 28 29 30 31                        29 30 31            \n\
+\n\
+\x20       April                  May                  June         \n\
+\x20          1  2  3  4                  1  2      1  2  3  4  5  6\n\
+\x20 5  6  7  8  9 10 11   3  4  5  6  7  8  9   7  8  9 10 11 12 13\n\
+\x2012 13 14 15 16 17 18  10 11 12 13 14 15 16  14 15 16 17 18 19 20\n\
+\x2019 20 21 22 23 24 25  17 18 19 20 21 22 23  21 22 23 24 25 26 27\n\
+\x2026 27 28 29 30        24 25 26 27 28 29 30  28 29 30            \n\
+\x20                      31                                        \n\
+\n\
+\x20       July                 August               September      \n\
+\x20          1  2  3  4                     1         1  2  3  4  5\n\
+\x20 5  6  7  8  9 10 11   2  3  4  5  6  7  8   6  7  8  9 10 11 12\n\
+\x2012 13 14 15 16 17 18   9 10 11 12 13 14 15  13 14 15 16 17 18 19\n\
+\x2019 20 21 22 23 24 25  16 17 18 19 20 21 22  20 21 22 23 24 25 26\n\
+\x2026 27 28 29 30 31     23 24 25 26 27 28 29  27 28 29 30         \n\
+\x20                      30 31                                     \n\
+\n\
+\x20      October              November              December       \n\
+\x20             1  2  3   1  2  3  4  5  6  7         1  2  3  4  5\n\
+\x20 4  5  6  7  8  9 10   8  9 10 11 12 13 14   6  7  8  9 10 11 12\n\
+\x2011 12 13 14 15 16 17  15 16 17 18 19 20 21  13 14 15 16 17 18 19\n\
+\x2018 19 20 21 22 23 24  22 23 24 25 26 27 28  20 21 22 23 24 25 26\n\
+\x2025 26 27 28 29 30 31  29 30                 27 28 29 30 31      ");
+}
+
+fn main() {
+    // Run tests.
+    test_spaces();
+    test_dates_in_year();
+    test_group_by();
+    test_by_month();
+    test_isoweekdate();
+    test_by_week();
+    test_format_weeks();
+    test_month_title();
+    test_format_month();
+    test_paste_blocks();
+    test_chunks();
+    test_format_year();
+}
diff --git a/src/test/run-pass/impl-trait/example-st.rs b/src/test/run-pass/impl-trait/example-st.rs
new file mode 100644 (file)
index 0000000..461d4cf
--- /dev/null
@@ -0,0 +1,40 @@
+// 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(conservative_impl_trait, question_mark)]
+
+struct State;
+type Error = ();
+
+trait Bind<F> {
+    type Output;
+    fn bind(self, f: F) -> Self::Output;
+}
+
+fn bind<T, U, A, B, F>(mut a: A, mut f: F)
+                       -> impl FnMut(&mut State) -> Result<U, Error>
+where F: FnMut(T) -> B,
+      A: FnMut(&mut State) -> Result<T, Error>,
+      B: FnMut(&mut State) -> Result<U, Error>
+{
+    move |state | {
+        let r = a(state)?;
+        f(r)(state)
+    }
+}
+
+fn atom<T>(x: T) -> impl FnMut(&mut State) -> Result<T, Error> {
+    let mut x = Some(x);
+    move |_| x.take().map_or(Err(()), Ok)
+}
+
+fn main() {
+    assert_eq!(bind(atom(5), |x| atom(x > 4))(&mut State), Ok(true));
+}
diff --git a/src/test/run-pass/issue-22894.rs b/src/test/run-pass/issue-22894.rs
new file mode 100644 (file)
index 0000000..8acd88d
--- /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.
+
+#[allow(dead_code)]
+static X: &'static str = &*"";
+fn main() {}
diff --git a/src/test/run-pass/issue-29053.rs b/src/test/run-pass/issue-29053.rs
new file mode 100644 (file)
index 0000000..7265507
--- /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.
+
+fn main() {
+    let x: &'static str = "x";
+
+    {
+        let y = "y".to_string();
+        let ref mut x = &*x;
+        *x = &*y;
+    }
+
+    assert_eq!(x, "x");
+}
index a12e569df2bc925625ec8094a0085f60d2509521..0f1f6290a2573a54862a91f66ca7a1609faab498 100644 (file)
@@ -45,7 +45,7 @@ trait Tr1 {
 
 mod m1 {
     fn f() {
-        struct Z {
+        pub struct Z {
             pub field: u8
         }
 
diff --git a/src/test/run-pass/issue-33498.rs b/src/test/run-pass/issue-33498.rs
new file mode 100644 (file)
index 0000000..9b4e191
--- /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.
+
+pub fn main() {
+    let x = (0, 2);
+
+    match x {
+        (0, ref y) => {}
+        (y, 0) => {}
+        _ => (),
+    }
+}
diff --git a/src/test/run-pass/numeric-fields.rs b/src/test/run-pass/numeric-fields.rs
new file mode 100644 (file)
index 0000000..25e5a2a
--- /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.
+
+#![feature(relaxed_adts)]
+
+struct S(u8, u16);
+
+fn main() {
+    let s = S{1: 10, 0: 11};
+    match s {
+        S{0: a, 1: b, ..} => {
+            assert_eq!(a, 11);
+            assert_eq!(b, 10);
+        }
+    }
+}
diff --git a/src/test/run-pass/transmute-specialization.rs b/src/test/run-pass/transmute-specialization.rs
new file mode 100644 (file)
index 0000000..823def3
--- /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.
+
+#![feature(specialization)]
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+    default type Output = u16;
+}
+
+fn main() {
+    unsafe {
+        std::mem::transmute::<u16, <() as Specializable>::Output>(0);
+    }
+}
index 7d6b448df43fd417ec53329cc1562a6c09ab895b..abcfb9396f4c882f5594543996334bb679b8966d 100644 (file)
@@ -8,5 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern crate issue_28927_2 as inner2;
-pub use inner2 as bar;
+mod detail {
+    pub extern crate issue_28927_2 as inner2;
+}
+pub use detail::inner2 as bar;
diff --git a/src/test/rustdoc/private-type-alias.rs b/src/test/rustdoc/private-type-alias.rs
new file mode 100644 (file)
index 0000000..6371908
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.
+
+type MyResultPriv<T> = Result<T, u16>;
+pub type MyResultPub<T> = Result<T, u64>;
+
+// @has private_type_alias/fn.get_result_priv.html '//pre' 'Result<u8, u16>'
+pub fn get_result_priv() -> MyResultPriv<u8> {
+    panic!();
+}
+
+// @has private_type_alias/fn.get_result_pub.html '//pre' 'MyResultPub<u32>'
+pub fn get_result_pub() -> MyResultPub<u32> {
+    panic!();
+}
+
+pub type PubRecursive = u16;
+type PrivRecursive3 = u8;
+type PrivRecursive2 = PubRecursive;
+type PrivRecursive1 = PrivRecursive3;
+
+// PrivRecursive1 is expanded twice and stops at u8
+// PrivRecursive2 is expanded once and stops at public type alias PubRecursive
+// @has private_type_alias/fn.get_result_recursive.html '//pre' '(u8, PubRecursive)'
+pub fn get_result_recursive() -> (PrivRecursive1, PrivRecursive2) {
+    panic!();
+}
+
+type MyLifetimePriv<'a> = &'a isize;
+
+// @has private_type_alias/fn.get_lifetime_priv.html '//pre' "&'static isize"
+pub fn get_lifetime_priv() -> MyLifetimePriv<'static> {
+    panic!();
+}
diff --git a/src/test/ui/span/pub-struct-field.rs b/src/test/ui/span/pub-struct-field.rs
new file mode 100644 (file)
index 0000000..9f8f871
--- /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.
+
+// Regression test for issue #26083 and #35435
+// Test that span for public struct fields start at `pub`
+
+#![feature(pub_restricted)]
+
+struct Foo {
+    bar: u8,
+    pub bar: u8,
+    pub(crate) bar: u8,
+}
+
+fn main() {}
diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr
new file mode 100644 (file)
index 0000000..2c002c3
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0124]: field `bar` is already declared
+  --> $DIR/pub-struct-field.rs:18:5
+   |
+17 |     bar: u8,
+   |     ------- `bar` first declared here
+18 |     pub bar: u8,
+   |     ^^^^^^^^^^^ field already declared
+
+error[E0124]: field `bar` is already declared
+  --> $DIR/pub-struct-field.rs:19:5
+   |
+17 |     bar: u8,
+   |     ------- `bar` first declared here
+18 |     pub bar: u8,
+19 |     pub(crate) bar: u8,
+   |     ^^^^^^^^^^^^^^^^^^ field already declared
+
+error: aborting due to 2 previous errors
+
index 72df09b7669f686ed4303f3fab6f0d93bc564fa9..acf12dab16aff4d86b8a940cf84f7af88464cc2d 100644 (file)
@@ -24,7 +24,7 @@ struct Test {
 const TEST_REPOS: &'static [Test] = &[Test {
                                           name: "cargo",
                                           repo: "https://github.com/rust-lang/cargo",
-                                          sha: "fd90fd642d404d8c66505ca8db742c664ea352f2",
+                                          sha: "2d85908217f99a30aa5f68e05a8980704bb71fad",
                                           lock: None,
                                       },
                                       Test {
index 2a35fab9676a71b9f45bea98a44a6409553df18a..6090cb4f52725784789fb5904c7ffc850e334ef1 100644 (file)
@@ -36,22 +36,22 @@ impl FromStr for Mode {
     type Err = ();
     fn from_str(s: &str) -> Result<Mode, ()> {
         match s {
-          "compile-fail" => Ok(CompileFail),
-          "parse-fail" => Ok(ParseFail),
-          "run-fail" => Ok(RunFail),
-          "run-pass" => Ok(RunPass),
-          "run-pass-valgrind" => Ok(RunPassValgrind),
-          "pretty" => Ok(Pretty),
-          "debuginfo-lldb" => Ok(DebugInfoLldb),
-          "debuginfo-gdb" => Ok(DebugInfoGdb),
-          "codegen" => Ok(Codegen),
-          "rustdoc" => Ok(Rustdoc),
-          "codegen-units" => Ok(CodegenUnits),
-          "incremental" => Ok(Incremental),
-          "run-make" => Ok(RunMake),
-          "ui" => Ok(Ui),
-          "mir-opt" => Ok(MirOpt),
-          _ => Err(()),
+            "compile-fail" => Ok(CompileFail),
+            "parse-fail" => Ok(ParseFail),
+            "run-fail" => Ok(RunFail),
+            "run-pass" => Ok(RunPass),
+            "run-pass-valgrind" => Ok(RunPassValgrind),
+            "pretty" => Ok(Pretty),
+            "debuginfo-lldb" => Ok(DebugInfoLldb),
+            "debuginfo-gdb" => Ok(DebugInfoGdb),
+            "codegen" => Ok(Codegen),
+            "rustdoc" => Ok(Rustdoc),
+            "codegen-units" => Ok(CodegenUnits),
+            "incremental" => Ok(Incremental),
+            "run-make" => Ok(RunMake),
+            "ui" => Ok(Ui),
+            "mir-opt" => Ok(MirOpt),
+            _ => Err(()),
         }
     }
 }
@@ -59,22 +59,23 @@ fn from_str(s: &str) -> Result<Mode, ()> {
 impl fmt::Display for Mode {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(match *self {
-            CompileFail => "compile-fail",
-            ParseFail => "parse-fail",
-            RunFail => "run-fail",
-            RunPass => "run-pass",
-            RunPassValgrind => "run-pass-valgrind",
-            Pretty => "pretty",
-            DebugInfoGdb => "debuginfo-gdb",
-            DebugInfoLldb => "debuginfo-lldb",
-            Codegen => "codegen",
-            Rustdoc => "rustdoc",
-            CodegenUnits => "codegen-units",
-            Incremental => "incremental",
-            RunMake => "run-make",
-            Ui => "ui",
-            MirOpt => "mir-opt",
-        }, f)
+                              CompileFail => "compile-fail",
+                              ParseFail => "parse-fail",
+                              RunFail => "run-fail",
+                              RunPass => "run-pass",
+                              RunPassValgrind => "run-pass-valgrind",
+                              Pretty => "pretty",
+                              DebugInfoGdb => "debuginfo-gdb",
+                              DebugInfoLldb => "debuginfo-lldb",
+                              Codegen => "codegen",
+                              Rustdoc => "rustdoc",
+                              CodegenUnits => "codegen-units",
+                              Incremental => "incremental",
+                              RunMake => "run-make",
+                              Ui => "ui",
+                              MirOpt => "mir-opt",
+                          },
+                          f)
     }
 }
 
index c3da891933f6df1bb7fcf054063a6afa036d1032..29ca54fda8db9521eeb68b74686094bf84770a1b 100644 (file)
@@ -64,7 +64,11 @@ pub struct Error {
 }
 
 #[derive(PartialEq, Debug)]
-enum WhichLine { ThisLine, FollowPrevious(usize), AdjustBackward(usize) }
+enum WhichLine {
+    ThisLine,
+    FollowPrevious(usize),
+    AdjustBackward(usize),
+}
 
 /// Looks for either "//~| KIND MESSAGE" or "//~^^... KIND MESSAGE"
 /// The former is a "follow" that inherits its target from the preceding line;
@@ -91,25 +95,22 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
 
     let tag = match cfg {
         Some(rev) => format!("//[{}]~", rev),
-        None => format!("//~")
+        None => format!("//~"),
     };
 
     rdr.lines()
-       .enumerate()
-       .filter_map(|(line_num, line)| {
-           parse_expected(last_nonfollow_error,
-                          line_num + 1,
-                          &line.unwrap(),
-                          &tag)
-               .map(|(which, error)| {
-                   match which {
-                       FollowPrevious(_) => {}
-                       _ => last_nonfollow_error = Some(error.line_num),
-                   }
-                   error
-               })
-       })
-       .collect()
+        .enumerate()
+        .filter_map(|(line_num, line)| {
+            parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), &tag)
+                .map(|(which, error)| {
+                    match which {
+                        FollowPrevious(_) => {}
+                        _ => last_nonfollow_error = Some(error.line_num),
+                    }
+                    error
+                })
+        })
+        .collect()
 }
 
 fn parse_expected(last_nonfollow_error: Option<usize>,
@@ -117,7 +118,10 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
                   line: &str,
                   tag: &str)
                   -> Option<(WhichLine, Error)> {
-    let start = match line.find(tag) { Some(i) => i, None => return None };
+    let start = match line.find(tag) {
+        Some(i) => i,
+        None => return None,
+    };
     let (follow, adjusts) = if line[start + tag.len()..].chars().next().unwrap() == '|' {
         (true, 0)
     } else {
@@ -125,26 +129,25 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
     };
     let kind_start = start + tag.len() + adjusts + (follow as usize);
     let (kind, msg);
-    match
-        line[kind_start..].split_whitespace()
-                          .next()
-                          .expect("Encountered unexpected empty comment")
-                          .parse::<ErrorKind>()
-    {
+    match line[kind_start..]
+        .split_whitespace()
+        .next()
+        .expect("Encountered unexpected empty comment")
+        .parse::<ErrorKind>() {
         Ok(k) => {
             // If we find `//~ ERROR foo` or something like that:
             kind = Some(k);
             let letters = line[kind_start..].chars();
             msg = letters.skip_while(|c| c.is_whitespace())
-                         .skip_while(|c| !c.is_whitespace())
-                         .collect::<String>();
+                .skip_while(|c| !c.is_whitespace())
+                .collect::<String>();
         }
         Err(_) => {
             // Otherwise we found `//~ foo`:
             kind = None;
             let letters = line[kind_start..].chars();
             msg = letters.skip_while(|c| c.is_whitespace())
-                         .collect::<String>();
+                .collect::<String>();
         }
     }
     let msg = msg.trim().to_owned();
@@ -155,15 +158,25 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
                                                     preceding //~^ line.");
         (FollowPrevious(line_num), line_num)
     } else {
-        let which =
-            if adjusts > 0 { AdjustBackward(adjusts) } else { ThisLine };
+        let which = if adjusts > 0 {
+            AdjustBackward(adjusts)
+        } else {
+            ThisLine
+        };
         let line_num = line_num - adjusts;
         (which, line_num)
     };
 
     debug!("line={} tag={:?} which={:?} kind={:?} msg={:?}",
-           line_num, tag, which, kind, msg);
-    Some((which, Error { line_num: line_num,
-                         kind: kind,
-                         msg: msg, }))
+           line_num,
+           tag,
+           which,
+           kind,
+           msg);
+    Some((which,
+          Error {
+        line_num: line_num,
+        kind: kind,
+        msg: msg,
+    }))
 }
index 7593033ffe3991f9c9791aedae294056a9f335bf..af33d76be1b0db0f430b4dcc5a4ee774a2c0d08d 100644 (file)
@@ -32,24 +32,21 @@ pub fn from_file(config: &Config, testfile: &Path) -> Self {
             should_fail: false,
         };
 
-        iter_header(testfile, None, &mut |ln| {
+        iter_header(testfile,
+                    None,
+                    &mut |ln| {
             props.ignore =
-                props.ignore ||
-                parse_name_directive(ln, "ignore-test") ||
+                props.ignore || parse_name_directive(ln, "ignore-test") ||
                 parse_name_directive(ln, &ignore_target(config)) ||
                 parse_name_directive(ln, &ignore_architecture(config)) ||
                 parse_name_directive(ln, &ignore_stage(config)) ||
                 parse_name_directive(ln, &ignore_env(config)) ||
-                (config.mode == common::Pretty &&
-                 parse_name_directive(ln, "ignore-pretty")) ||
+                (config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) ||
                 (config.target != config.host &&
                  parse_name_directive(ln, "ignore-cross-compile")) ||
-                ignore_gdb(config, ln) ||
-                ignore_lldb(config, ln);
+                ignore_gdb(config, ln) || ignore_lldb(config, ln);
 
-            props.should_fail =
-                props.should_fail ||
-                parse_name_directive(ln, "should-fail");
+            props.should_fail = props.should_fail || parse_name_directive(ln, "should-fail");
         });
 
         return props;
@@ -61,11 +58,11 @@ fn ignore_architecture(config: &Config) -> String {
             format!("ignore-{}", util::get_arch(&config.target))
         }
         fn ignore_stage(config: &Config) -> String {
-            format!("ignore-{}",
-                    config.stage_id.split('-').next().unwrap())
+            format!("ignore-{}", config.stage_id.split('-').next().unwrap())
         }
         fn ignore_env(config: &Config) -> String {
-            format!("ignore-{}", util::get_env(&config.target).unwrap_or("<unknown>"))
+            format!("ignore-{}",
+                    util::get_env(&config.target).unwrap_or("<unknown>"))
         }
         fn ignore_gdb(config: &Config, line: &str) -> bool {
             if config.mode != common::DebugInfoGdb {
@@ -79,13 +76,12 @@ fn ignore_gdb(config: &Config, line: &str) -> bool {
             if let Some(ref actual_version) = config.gdb_version {
                 if line.contains("min-gdb-version") {
                     let min_version = line.trim()
-                                          .split(' ')
-                                          .last()
-                                          .expect("Malformed GDB version directive");
+                        .split(' ')
+                        .last()
+                        .expect("Malformed GDB version directive");
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    gdb_version_to_int(actual_version) <
-                        gdb_version_to_int(min_version)
+                    gdb_version_to_int(actual_version) < gdb_version_to_int(min_version)
                 } else {
                     false
                 }
@@ -106,13 +102,12 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
             if let Some(ref actual_version) = config.lldb_version {
                 if line.contains("min-lldb-version") {
                     let min_version = line.trim()
-                                          .split(' ')
-                                          .last()
-                                          .expect("Malformed lldb version directive");
+                        .split(' ')
+                        .last()
+                        .expect("Malformed lldb version directive");
                     // Ignore if actual version is smaller the minimum required
                     // version
-                    lldb_version_to_int(actual_version) <
-                        lldb_version_to_int(min_version)
+                    lldb_version_to_int(actual_version) < lldb_version_to_int(min_version)
                 } else {
                     false
                 }
@@ -126,7 +121,7 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
 #[derive(Clone, Debug)]
 pub struct TestProps {
     // Lines that should be expected, in order, on standard out
-    pub error_patterns: Vec<String> ,
+    pub error_patterns: Vec<String>,
     // Extra flags to pass to the compiler
     pub compile_flags: Vec<String>,
     // Extra flags to pass when the compiled code is run (such as --bench)
@@ -137,13 +132,13 @@ pub struct TestProps {
     // Other crates that should be compiled (typically from the same
     // directory as the test, but for backwards compatibility reasons
     // we also check the auxiliary directory)
-    pub aux_builds: Vec<String> ,
+    pub aux_builds: Vec<String>,
     // Environment settings to use for compiling
-    pub rustc_env: Vec<(String,String)> ,
+    pub rustc_env: Vec<(String, String)>,
     // Environment settings to use during execution
-    pub exec_env: Vec<(String,String)> ,
+    pub exec_env: Vec<(String, String)>,
     // Lines to check if they appear in the expected debugger output
-    pub check_lines: Vec<String> ,
+    pub check_lines: Vec<String>,
     // Build documentation for all specified aux-builds as well
     pub build_aux_docs: bool,
     // Flag to force a crate to be built with the host architecture
@@ -226,17 +221,17 @@ pub fn from_file(testfile: &Path) -> Self {
     /// tied to a particular revision `foo` (indicated by writing
     /// `//[foo]`), then the property is ignored unless `cfg` is
     /// `Some("foo")`.
-    pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>)  {
-        iter_header(testfile, cfg, &mut |ln| {
+    pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>) {
+        iter_header(testfile,
+                    cfg,
+                    &mut |ln| {
             if let Some(ep) = parse_error_pattern(ln) {
                 self.error_patterns.push(ep);
             }
 
             if let Some(flags) = parse_compile_flags(ln) {
-                self.compile_flags.extend(
-                    flags
-                        .split_whitespace()
-                        .map(|s| s.to_owned()));
+                self.compile_flags.extend(flags.split_whitespace()
+                    .map(|s| s.to_owned()));
             }
 
             if let Some(r) = parse_revisions(ln) {
@@ -279,7 +274,7 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>)  {
                 self.pretty_compare_only = parse_pretty_compare_only(ln);
             }
 
-            if let  Some(ab) = parse_aux_build(ln) {
+            if let Some(ab) = parse_aux_build(ln) {
                 self.aux_builds.push(ab);
             }
 
@@ -291,7 +286,7 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>)  {
                 self.rustc_env.push(ee);
             }
 
-            if let Some(cl) =  parse_check_line(ln) {
+            if let Some(cl) = parse_check_line(ln) {
                 self.check_lines.push(cl);
             }
 
@@ -302,21 +297,20 @@ pub fn load_from(&mut self, testfile: &Path, cfg: Option<&str>)  {
 
         for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
             match env::var(key) {
-                Ok(val) =>
+                Ok(val) => {
                     if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() {
                         self.exec_env.push((key.to_owned(), val))
-                    },
+                    }
+                }
                 Err(..) => {}
             }
         }
     }
 }
 
-fn iter_header(testfile: &Path,
-               cfg: Option<&str>,
-               it: &mut FnMut(&str)) {
+fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
     if testfile.is_dir() {
-        return
+        return;
     }
     let rdr = BufReader::new(File::open(testfile).unwrap());
     for ln in rdr.lines() {
@@ -336,7 +330,7 @@ fn iter_header(testfile: &Path,
                     None => false,
                 };
                 if matches {
-                    it(&ln[close_brace+1..]);
+                    it(&ln[close_brace + 1..]);
                 }
             } else {
                 panic!("malformed condition directive: expected `//[foo]`, found `{}`",
@@ -409,18 +403,17 @@ fn parse_pretty_compare_only(line: &str) -> bool {
 fn parse_env(line: &str, name: &str) -> Option<(String, String)> {
     parse_name_value_directive(line, name).map(|nv| {
         // nv is either FOO or FOO=BAR
-        let mut strs: Vec<String> = nv
-                                      .splitn(2, '=')
-                                      .map(str::to_owned)
-                                      .collect();
+        let mut strs: Vec<String> = nv.splitn(2, '=')
+            .map(str::to_owned)
+            .collect();
 
         match strs.len() {
-          1 => (strs.pop().unwrap(), "".to_owned()),
-          2 => {
-              let end = strs.pop().unwrap();
-              (strs.pop().unwrap(), end)
-          }
-          n => panic!("Expected 1 or 2 strings, not {}", n)
+            1 => (strs.pop().unwrap(), "".to_owned()),
+            2 => {
+                let end = strs.pop().unwrap();
+                (strs.pop().unwrap(), end)
+            }
+            n => panic!("Expected 1 or 2 strings, not {}", n),
         }
     })
 }
@@ -442,11 +435,10 @@ fn parse_name_directive(line: &str, directive: &str) -> bool {
     line.contains(directive) && !line.contains(&("no-".to_owned() + directive))
 }
 
-pub fn parse_name_value_directive(line: &str, directive: &str)
-                                  -> Option<String> {
+pub fn parse_name_value_directive(line: &str, directive: &str) -> Option<String> {
     let keycolon = format!("{}:", directive);
     if let Some(colon) = line.find(&keycolon) {
-        let value = line[(colon + keycolon.len()) .. line.len()].to_owned();
+        let value = line[(colon + keycolon.len())..line.len()].to_owned();
         debug!("{}: {}", directive, value);
         Some(value)
     } else {
@@ -455,9 +447,8 @@ pub fn parse_name_value_directive(line: &str, directive: &str)
 }
 
 pub fn gdb_version_to_int(version_string: &str) -> isize {
-    let error_string = format!(
-        "Encountered GDB version string with unexpected format: {}",
-        version_string);
+    let error_string = format!("Encountered GDB version string with unexpected format: {}",
+                               version_string);
     let error_string = error_string;
 
     let components: Vec<&str> = version_string.trim().split('.').collect();
@@ -473,9 +464,8 @@ pub fn gdb_version_to_int(version_string: &str) -> isize {
 }
 
 pub fn lldb_version_to_int(version_string: &str) -> isize {
-    let error_string = format!(
-        "Encountered LLDB version string with unexpected format: {}",
-        version_string);
+    let error_string = format!("Encountered LLDB version string with unexpected format: {}",
+                               version_string);
     let error_string = error_string;
     let major: isize = version_string.parse().ok().expect(&error_string);
     return major;
index e5b628bb0029545022dab31220dc8e89ef668470..d9da1bdc3485837d8024036f23ff5be81f5e7c71 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_serialize::json;
 use std::str::FromStr;
 use std::path::Path;
-use runtest::{ProcRes};
+use runtest::ProcRes;
 
 // These structs are a subset of the ones found in
 // `syntax::json`.
@@ -58,8 +58,8 @@ struct DiagnosticCode {
 
 pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
     output.lines()
-          .flat_map(|line| parse_line(file_name, line, output, proc_res))
-          .collect()
+        .flat_map(|line| parse_line(file_name, line, output, proc_res))
+        .collect()
 }
 
 fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
@@ -73,9 +73,11 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
                 expected_errors
             }
             Err(error) => {
-                proc_res.fatal(Some(&format!(
-                    "failed to decode compiler output as json: `{}`\noutput: {}\nline: {}",
-                    error, line, output)));
+                proc_res.fatal(Some(&format!("failed to decode compiler output as json: \
+                                              `{}`\noutput: {}\nline: {}",
+                                             error,
+                                             line,
+                                             output)));
             }
         }
     } else {
@@ -87,16 +89,15 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
                         diagnostic: &Diagnostic,
                         default_spans: &[&DiagnosticSpan],
                         file_name: &str) {
-    let spans_in_this_file: Vec<_> =
-        diagnostic.spans.iter()
-                        .filter(|span| Path::new(&span.file_name) == Path::new(&file_name))
-                        .collect();
-
-    let primary_spans: Vec<_> =
-        spans_in_this_file.iter()
-                          .cloned()
-                          .filter(|span| span.is_primary)
-                          .collect();
+    let spans_in_this_file: Vec<_> = diagnostic.spans
+        .iter()
+        .filter(|span| Path::new(&span.file_name) == Path::new(&file_name))
+        .collect();
+
+    let primary_spans: Vec<_> = spans_in_this_file.iter()
+        .cloned()
+        .filter(|span| span.is_primary)
+        .collect();
     let primary_spans = if primary_spans.is_empty() {
         // subdiagnostics often don't have a span of their own;
         // inherit the span from the parent in that case
@@ -144,24 +145,20 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
         for span in primary_spans {
             let msg = with_code(span, first_line);
             let kind = ErrorKind::from_str(&diagnostic.level).ok();
-            expected_errors.push(
-                Error {
-                    line_num: span.line_start,
-                    kind: kind,
-                    msg: msg,
-                }
-            );
+            expected_errors.push(Error {
+                line_num: span.line_start,
+                kind: kind,
+                msg: msg,
+            });
         }
     }
     for next_line in message_lines {
         for span in primary_spans {
-            expected_errors.push(
-                Error {
-                    line_num: span.line_start,
-                    kind: None,
-                    msg: with_code(span, next_line),
-                }
-            );
+            expected_errors.push(Error {
+                line_num: span.line_start,
+                kind: None,
+                msg: with_code(span, next_line),
+            });
         }
     }
 
@@ -170,33 +167,28 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
         let start_line = primary_spans.iter().map(|s| s.line_start).min().expect("\
             every suggestion should have at least one span");
         for (index, line) in rendered.lines().enumerate() {
-            expected_errors.push(
-                Error {
-                    line_num: start_line + index,
-                    kind: Some(ErrorKind::Suggestion),
-                    msg: line.to_string()
-                }
-            );
+            expected_errors.push(Error {
+                line_num: start_line + index,
+                kind: Some(ErrorKind::Suggestion),
+                msg: line.to_string(),
+            });
         }
     }
 
     // Add notes for the backtrace
     for span in primary_spans {
         for frame in &span.expansion {
-            push_backtrace(expected_errors,
-                           frame,
-                           file_name);
+            push_backtrace(expected_errors, frame, file_name);
         }
     }
 
     // Add notes for any labels that appear in the message.
     for span in spans_in_this_file.iter()
-                                  .filter(|span| span.label.is_some())
-    {
+        .filter(|span| span.label.is_some()) {
         expected_errors.push(Error {
             line_num: span.line_start,
             kind: Some(ErrorKind::Note),
-            msg: span.label.clone().unwrap()
+            msg: span.label.clone().unwrap(),
         });
     }
 
@@ -210,13 +202,11 @@ fn push_backtrace(expected_errors: &mut Vec<Error>,
                   expansion: &DiagnosticSpanMacroExpansion,
                   file_name: &str) {
     if Path::new(&expansion.span.file_name) == Path::new(&file_name) {
-        expected_errors.push(
-            Error {
-                line_num: expansion.span.line_start,
-                kind: Some(ErrorKind::Note),
-                msg: format!("in this expansion of {}", expansion.macro_decl_name),
-            }
-        );
+        expected_errors.push(Error {
+            line_num: expansion.span.line_start,
+            kind: Some(ErrorKind::Note),
+            msg: format!("in this expansion of {}", expansion.macro_decl_name),
+        });
     }
 
     for previous_expansion in &expansion.span.expansion {
index cefcc11486fe230c8659e989e3575d0233e7c47c..90641b5c476d7bbd93412d4eeb878fa0f7295e52 100644 (file)
@@ -310,6 +310,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
             Err(_) => false
         },
         color: test::AutoColor,
+        test_threads: None,
     }
 }
 
index 53b7cd059be275f8ccd64db3811a422ec8dd5ab6..ed690c08a1ed27e08dc0c6e3ae334d933012fe0b 100644 (file)
@@ -12,7 +12,7 @@
 use std::ffi::OsString;
 use std::io::prelude::*;
 use std::path::PathBuf;
-use std::process::{ExitStatus, Command, Child, Output, Stdio};
+use std::process::{Child, Command, ExitStatus, Output, Stdio};
 
 pub fn dylib_env_var() -> &'static str {
     if cfg!(windows) {
@@ -29,7 +29,7 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
     // search path for the child.
     let var = dylib_env_var();
     let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
-                       .collect::<Vec<_>>();
+        .collect::<Vec<_>>();
     if let Some(p) = aux_path {
         path.insert(0, PathBuf::from(p))
     }
@@ -40,20 +40,25 @@ fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
     cmd.env(var, newpath);
 }
 
-pub struct Result {pub status: ExitStatus, pub out: String, pub err: String}
+pub struct Result {
+    pub status: ExitStatus,
+    pub out: String,
+    pub err: String,
+}
 
 pub fn run(lib_path: &str,
            prog: &str,
            aux_path: Option<&str>,
            args: &[String],
-           env: Vec<(String, String)> ,
-           input: Option<String>) -> Option<Result> {
+           env: Vec<(String, String)>,
+           input: Option<String>)
+           -> Option<Result> {
 
     let mut cmd = Command::new(prog);
     cmd.args(args)
-       .stdin(Stdio::piped())
-       .stdout(Stdio::piped())
-       .stderr(Stdio::piped());
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .stderr(Stdio::piped());
     add_target_env(&mut cmd, lib_path, aux_path);
     for (key, val) in env {
         cmd.env(&key, &val);
@@ -64,31 +69,31 @@ pub fn run(lib_path: &str,
             if let Some(input) = input {
                 process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
             }
-            let Output { status, stdout, stderr } =
-                process.wait_with_output().unwrap();
+            let Output { status, stdout, stderr } = process.wait_with_output().unwrap();
 
             Some(Result {
                 status: status,
                 out: String::from_utf8(stdout).unwrap(),
-                err: String::from_utf8(stderr).unwrap()
+                err: String::from_utf8(stderr).unwrap(),
             })
-        },
-        Err(..) => None
+        }
+        Err(..) => None,
     }
 }
 
 pub fn run_background(lib_path: &str,
-           prog: &str,
-           aux_path: Option<&str>,
-           args: &[String],
-           env: Vec<(String, String)> ,
-           input: Option<String>) -> Option<Child> {
+                      prog: &str,
+                      aux_path: Option<&str>,
+                      args: &[String],
+                      env: Vec<(String, String)>,
+                      input: Option<String>)
+                      -> Option<Child> {
 
     let mut cmd = Command::new(prog);
     cmd.args(args)
-       .stdin(Stdio::piped())
-       .stdout(Stdio::piped())
-       .stderr(Stdio::piped());
+        .stdin(Stdio::piped())
+        .stdout(Stdio::piped())
+        .stderr(Stdio::piped());
     add_target_env(&mut cmd, lib_path, aux_path);
     for (key, val) in env {
         cmd.env(&key, &val);
@@ -101,7 +106,7 @@ pub fn run_background(lib_path: &str,
             }
 
             Some(process)
-        },
-        Err(..) => None
+        }
+        Err(..) => None,
     }
 }
index 0cf90ec95f38e3c838e40e08ce6e2f57580cb080..e2629ffd8f54a3e122b373462ed6b711cbb27661 100644 (file)
@@ -34,14 +34,21 @@ pub unsafe fn raise_fd_limit() {
     let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
     let mut maxfiles: libc::c_int = 0;
     let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
-    if libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size,
-              null_mut(), 0) != 0 {
+    if libc::sysctl(&mut mib[0],
+                    2,
+                    &mut maxfiles as *mut _ as *mut _,
+                    &mut size,
+                    null_mut(),
+                    0) != 0 {
         let err = io::Error::last_os_error();
         panic!("raise_fd_limit: error calling sysctl: {}", err);
     }
 
     // Fetch the current resource limits
-    let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0};
+    let mut rlim = libc::rlimit {
+        rlim_cur: 0,
+        rlim_max: 0,
+    };
     if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 {
         let err = io::Error::last_os_error();
         panic!("raise_fd_limit: error calling getrlimit: {}", err);
index 6647a1a0a933d41046dc22ad79e0709a52393967..ae8e82e4e2f60e36639358d9fa062381431fbe75 100644 (file)
@@ -1330,9 +1330,7 @@ fn make_compile_args(&self,
                 // patterns still match the raw compiler output.
                 if self.props.error_patterns.is_empty() {
                     args.extend(["--error-format",
-                                 "json",
-                                 "-Z",
-                                 "unstable-options"]
+                                 "json"]
                                 .iter()
                                 .map(|s| s.to_string()));
                 }
index 66573393971c4c6692ce2549017f28e7680b19db..fca01029c44652ba87d542ed43e478f5a2d6313a 100644 (file)
 
 pub fn diff_lines(actual: &str, expected: &str) -> Vec<String> {
     // mega simplistic diff algorithm that just prints the things added/removed
-    zip_all(actual.lines(), expected.lines()).enumerate().filter_map(|(i, (a,e))| {
-        match (a, e) {
-            (Some(a), Some(e)) => {
-                if lines_match(e, a) {
-                    None
-                } else {
-                    Some(format!("{:3} - |{}|\n    + |{}|\n", i, e, a))
+    zip_all(actual.lines(), expected.lines())
+        .enumerate()
+        .filter_map(|(i, (a, e))| {
+            match (a, e) {
+                (Some(a), Some(e)) => {
+                    if lines_match(e, a) {
+                        None
+                    } else {
+                        Some(format!("{:3} - |{}|\n    + |{}|\n", i, e, a))
+                    }
                 }
-            },
-            (Some(a), None) => {
-                Some(format!("{:3} -\n    + |{}|\n", i, a))
-            },
-            (None, Some(e)) => {
-                Some(format!("{:3} - |{}|\n    +\n", i, e))
-            },
-            (None, None) => panic!("Cannot get here")
-        }
-    }).collect()
+                (Some(a), None) => Some(format!("{:3} -\n    + |{}|\n", i, a)),
+                (None, Some(e)) => Some(format!("{:3} - |{}|\n    +\n", i, e)),
+                (None, None) => panic!("Cannot get here"),
+            }
+        })
+        .collect()
 }
 
 fn lines_match(expected: &str, mut actual: &str) -> bool {
@@ -38,13 +37,11 @@ fn lines_match(expected: &str, mut actual: &str) -> bool {
         match actual.find(part) {
             Some(j) => {
                 if i == 0 && j != 0 {
-                    return false
+                    return false;
                 }
                 actual = &actual[j + part.len()..];
             }
-            None => {
-                return false
-            }
+            None => return false,
         }
     }
     actual.is_empty() || expected.ends_with("[..]")
@@ -55,7 +52,7 @@ struct ZipAll<I1: Iterator, I2: Iterator> {
     second: I2,
 }
 
-impl<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>> Iterator for ZipAll<I1, I2> {
+impl<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Iterator for ZipAll<I1, I2> {
     type Item = (Option<T>, Option<T>);
     fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
         let first = self.first.next();
@@ -63,12 +60,12 @@ fn next(&mut self) -> Option<(Option<T>, Option<T>)> {
 
         match (first, second) {
             (None, None) => None,
-            (a, b) => Some((a, b))
+            (a, b) => Some((a, b)),
         }
     }
 }
 
-fn zip_all<T, I1: Iterator<Item=T>, I2: Iterator<Item=T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
+fn zip_all<T, I1: Iterator<Item = T>, I2: Iterator<Item = T>>(a: I1, b: I2) -> ZipAll<I1, I2> {
     ZipAll {
         first: a,
         second: b,
index 69b839c5b7d9d0e94cdf58623574ef3ecd8e9dc3..d2872a0a2b7caa18ef6d42a7c879a4297fde8018 100644 (file)
 use common::Config;
 
 /// Conversion table from triple OS name to Rust SYSNAME
-const OS_TABLE: &'static [(&'static str, &'static str)] = &[
-    ("android", "android"),
-    ("bitrig", "bitrig"),
-    ("darwin", "macos"),
-    ("dragonfly", "dragonfly"),
-    ("freebsd", "freebsd"),
-    ("ios", "ios"),
-    ("linux", "linux"),
-    ("mingw32", "windows"),
-    ("netbsd", "netbsd"),
-    ("openbsd", "openbsd"),
-    ("win32", "windows"),
-    ("windows", "windows"),
-    ("solaris", "solaris"),
-    ("emscripten", "emscripten"),
-];
+const OS_TABLE: &'static [(&'static str, &'static str)] = &[("android", "android"),
+                                                            ("bitrig", "bitrig"),
+                                                            ("darwin", "macos"),
+                                                            ("dragonfly", "dragonfly"),
+                                                            ("freebsd", "freebsd"),
+                                                            ("ios", "ios"),
+                                                            ("linux", "linux"),
+                                                            ("mingw32", "windows"),
+                                                            ("netbsd", "netbsd"),
+                                                            ("openbsd", "openbsd"),
+                                                            ("win32", "windows"),
+                                                            ("windows", "windows"),
+                                                            ("solaris", "solaris"),
+                                                            ("emscripten", "emscripten")];
 
-const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
-    ("aarch64", "aarch64"),
-    ("amd64", "x86_64"),
-    ("arm", "arm"),
-    ("arm64", "aarch64"),
-    ("hexagon", "hexagon"),
-    ("i386", "x86"),
-    ("i686", "x86"),
-    ("mips", "mips"),
-    ("msp430", "msp430"),
-    ("powerpc", "powerpc"),
-    ("powerpc64", "powerpc64"),
-    ("s390x", "systemz"),
-    ("sparc", "sparc"),
-    ("x86_64", "x86_64"),
-    ("xcore", "xcore"),
-    ("asmjs", "asmjs"),
-];
+const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[("aarch64", "aarch64"),
+                                                              ("amd64", "x86_64"),
+                                                              ("arm", "arm"),
+                                                              ("arm64", "aarch64"),
+                                                              ("hexagon", "hexagon"),
+                                                              ("i386", "x86"),
+                                                              ("i686", "x86"),
+                                                              ("mips", "mips"),
+                                                              ("msp430", "msp430"),
+                                                              ("powerpc", "powerpc"),
+                                                              ("powerpc64", "powerpc64"),
+                                                              ("s390x", "systemz"),
+                                                              ("sparc", "sparc"),
+                                                              ("x86_64", "x86_64"),
+                                                              ("xcore", "xcore"),
+                                                              ("asmjs", "asmjs")];
 
 pub fn get_os(triple: &str) -> &'static str {
     for &(triple_os, os) in OS_TABLE {
         if triple.contains(triple_os) {
-            return os
+            return os;
         }
     }
     panic!("Cannot determine OS from triple");
@@ -59,7 +55,7 @@ pub fn get_os(triple: &str) -> &'static str {
 pub fn get_arch(triple: &str) -> &'static str {
     for &(triple_arch, arch) in ARCH_TABLE {
         if triple.contains(triple_arch) {
-            return arch
+            return arch;
         }
     }
     panic!("Cannot determine Architecture from triple");
@@ -74,17 +70,21 @@ pub fn make_new_path(path: &str) -> String {
     // Windows just uses PATH as the library search path, so we have to
     // maintain the current value while adding our own
     match env::var(lib_path_env_var()) {
-        Ok(curr) => {
-            format!("{}{}{}", path, path_div(), curr)
-        }
-        Err(..) => path.to_owned()
+        Ok(curr) => format!("{}{}{}", path, path_div(), curr),
+        Err(..) => path.to_owned(),
     }
 }
 
-pub fn lib_path_env_var() -> &'static str { "PATH" }
-fn path_div() -> &'static str { ";" }
+pub fn lib_path_env_var() -> &'static str {
+    "PATH"
+}
+fn path_div() -> &'static str {
+    ";"
+}
 
 pub fn logv(config: &Config, s: String) {
     debug!("{}", s);
-    if config.verbose { println!("{}", s); }
+    if config.verbose {
+        println!("{}", s);
+    }
 }