]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #35596 - crypto-universe:E0254_style_and_tests, r=jonathandturner
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Sun, 14 Aug 2016 17:29:50 +0000 (20:29 +0300)
committerGitHub <noreply@github.com>
Sun, 14 Aug 2016 17:29:50 +0000 (20:29 +0300)
Add label to E0254

This issue #35513 is a part of #35233.
r? @jonathandturner

317 files changed:
.gitignore
configure
man/rustc.1
mk/cfg/i586-unknown-linux-gnu.mk
mk/cfg/i686-unknown-linux-musl.mk
mk/rustllvm.mk
src/bootstrap/compile.rs
src/bootstrap/lib.rs
src/bootstrap/sanity.rs
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/libcore/sync/atomic.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/freshen.rs
src/librustc/infer/mod.rs
src/librustc/lint/builtin.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/mir/repr.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/session/config.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/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_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.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/def_key.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/tydecode.rs
src/librustc_metadata/tyencode.rs
src/librustc_mir/mir_map.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/loops.rs
src/librustc_passes/rvalues.rs
src/librustc_privacy/diagnostics.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/_match.rs
src/librustc_trans/back/write.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/context.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/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/html/format.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/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/thread.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/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/tokenstream.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/libunwind/libunwind.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/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/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/E0138.rs
src/test/compile-fail/E0253.rs
src/test/compile-fail/E0263.rs
src/test/compile-fail/E0267.rs
src/test/compile-fail/E0268.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/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/mir-opt/deaggregator_test_enum.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs
src/test/run-pass-fulldeps/linkage-visibility.rs
src/test/run-pass-fulldeps/logging-enabled.rs
src/test/run-pass-fulldeps/logging-separate-lines.rs
src/test/run-pass/auxiliary/empty-struct.rs
src/test/run-pass/backtrace-debuginfo.rs
src/test/run-pass/backtrace.rs
src/test/run-pass/command-before-exec.rs
src/test/run-pass/command-exec.rs
src/test/run-pass/drop-flag-sanity-check.rs
src/test/run-pass/drop-trait-enum.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/env-args-reverse-iterator.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/exec-env.rs
src/test/run-pass/hashmap-memory.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/intrinsic-alignment.rs
src/test/run-pass/issue-10626.rs
src/test/run-pass/issue-12133-3.rs
src/test/run-pass/issue-13304.rs
src/test/run-pass/issue-14456.rs
src/test/run-pass/issue-14940.rs
src/test/run-pass/issue-16272.rs
src/test/run-pass/issue-20091.rs
src/test/run-pass/issue-2190-1.rs
src/test/run-pass/issue-22894.rs [new file with mode: 0644]
src/test/run-pass/issue-24313.rs
src/test/run-pass/issue-28950.rs
src/test/run-pass/issue-29053.rs [new file with mode: 0644]
src/test/run-pass/issue-29485.rs
src/test/run-pass/issue-30490.rs
src/test/run-pass/issue-31776.rs
src/test/run-pass/issue-33770.rs
src/test/run-pass/linkage1.rs
src/test/run-pass/multi-panic.rs
src/test/run-pass/no-stdio.rs
src/test/run-pass/numeric-fields.rs [new file with mode: 0644]
src/test/run-pass/panic-handler-chain.rs
src/test/run-pass/process-exit.rs
src/test/run-pass/process-remove-from-env.rs
src/test/run-pass/process-spawn-with-unicode-params.rs
src/test/run-pass/rec-align-u64.rs
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/segfault-no-out-of-stack.rs
src/test/run-pass/signal-exit-status.rs
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/sleep.rs
src/test/run-pass/transmute-specialization.rs [new file with mode: 0644]
src/test/run-pass/wait-forked-but-failed-child.rs
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/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/uidiff.rs
src/tools/compiletest/src/util.rs

index 5e8c40d03fbeff96ea8c04fe9f9717056b285663..6de43f471d8860229cb72c236b260d9303de1553 100644 (file)
@@ -57,6 +57,7 @@ __pycache__/
 .project
 .settings/
 .valgrindrc
+.vscode/
 /*-*-*-*/
 /*-*-*/
 /Makefile
index 29f16da058129f917ae7e667a346a6020b5e0334..18dc99dd6c34c0a46106f403596b34084e8843b7 100755 (executable)
--- a/configure
+++ b/configure
@@ -1013,7 +1013,7 @@ then
     LLVM_VERSION=$($LLVM_CONFIG --version)
 
     case $LLVM_VERSION in
-        (3.[7-8]*)
+        (3.[7-9]*)
             msg "found ok version of LLVM: $LLVM_VERSION"
             ;;
         (*)
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 14b9ebfdba66851f8c8d8031afc2eb006c526359..fa2909196dcf184e5761ffb4e83dbb435c30c56e 100644 (file)
@@ -7,8 +7,8 @@ CFG_LIB_NAME_i586-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_i586-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium
-CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu :=  -g -fPIC -m32 $(CFLAGS) -march=pentium
+CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium -Wa,-mrelax-relocations=no
+CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu :=  -g -fPIC -m32 $(CFLAGS) -march=pentium -Wa,-mrelax-relocations=no
 CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -march=pentium
 CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index 80918728316a665f6c110c6aa940cfde8796962b..d6c1ce8967a20f66fc5823346ee7d64a116dc5d3 100644 (file)
@@ -7,8 +7,8 @@ CFG_INSTALL_ONLY_RLIB_i686-unknown-linux-musl = 1
 CFG_LIB_NAME_i686-unknown-linux-musl=lib$(1).so
 CFG_STATIC_LIB_NAME_i686-unknown-linux-musl=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
-CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386
-CFG_GCCISH_CFLAGS_i686-unknown-linux-musl :=  -g -fPIC -m32 -Wl,-melf_i386
+CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386 -Wa,-mrelax-relocations=no
+CFG_GCCISH_CFLAGS_i686-unknown-linux-musl :=  -g -fPIC -m32 -Wl,-melf_i386 -Wa,-mrelax-relocations=no
 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-musl :=
 CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-musl :=
 CFG_GCCISH_DEF_FLAG_i686-unknown-linux-musl :=
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..0f14487c3b9efd310789720445b975c8d9b14143 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
@@ -858,8 +868,13 @@ fn cflags(&self, target: &str) -> Vec<String> {
         // This is a hack, because newer binutils broke things on some vms/distros
         // (i.e., linking against unknown relocs disabled by the following flag)
         // See: https://github.com/rust-lang/rust/issues/34978
-        if target == "x86_64-unknown-linux-musl" {
-            base.push("-Wa,-mrelax-relocations=no".into());
+        match target {
+            "i586-unknown-linux-gnu" |
+            "i686-unknown-linux-musl" |
+            "x86_64-unknown-linux-musl" => {
+                base.push("-Wa,-mrelax-relocations=no".into());
+            },
+            _ => {},
         }
         return base
     }
index 09f96782e7184a9af4a9564430164224fcfb6fb2..d6ac3ef6c9c5024d8c1be674518fa221bfdf41bc 100644 (file)
@@ -98,7 +98,8 @@ pub fn check(build: &mut Build) {
         if target.contains("rumprun") ||
            target.contains("bitrig") ||
            target.contains("openbsd") ||
-           target.contains("msvc") {
+           target.contains("msvc") ||
+           target.contains("emscripten") {
             build.config.use_jemalloc = false;
         }
 
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 2a7a0b62329362b626d01f5d3d78f96a0d471cae..5701a89d8bc42aa0484e37c8f5d4e3597b09a039 100644 (file)
@@ -32,7 +32,7 @@
 //! atomically-reference-counted shared pointer).
 //!
 //! Most atomic types may be stored in static variables, initialized using
-//! the provided static initializers like `INIT_ATOMIC_BOOL`. Atomic statics
+//! the provided static initializers like `ATOMIC_BOOL_INIT`. Atomic statics
 //! are often used for lazy global initialization.
 //!
 //!
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 789b70ccfa412998157b36c220c0715baafc33e3..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."),
             },
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 58bbd8add26d96e660b1164e9e02675185c210b0..752b0e9a253dd9a7ee1cf41cd922c1f8467ce1c2 100644 (file)
@@ -268,6 +268,9 @@ 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);
     }
 
@@ -428,6 +431,9 @@ 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);
     }
 
index e3425d7fa61f5f73d9270f4ed5f4163e49efc59c..901a489728eeca0aca5c4ff7d9e26b23985047af 100644 (file)
@@ -215,6 +215,8 @@ pub enum DefPathData {
     Initializer,
     /// Pattern binding
     Binding(InternedString),
+    /// An `impl Trait` type node.
+    ImplTrait
 }
 
 impl Definitions {
@@ -369,6 +371,10 @@ pub fn as_interned_str(&self) -> InternedString {
             Initializer => {
                 InternedString::new("{{initializer}}")
             }
+
+            ImplTrait => {
+                InternedString::new("{{impl-Trait}}")
+            }
         }
     }
 
index 86d29a6fc717fea971bcbd5d5b27c653cd188116..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),
@@ -257,6 +262,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                     EntryVariant(p, _) |
                     EntryExpr(p, _) |
                     EntryStmt(p, _) |
+                EntryTy(p, _) |
                     EntryLocal(p, _) |
                     EntryPat(p, _) |
                     EntryBlock(p, _) |
@@ -297,6 +303,7 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
                     EntryVariant(p, _) |
                     EntryExpr(p, _) |
                     EntryStmt(p, _) |
+                    EntryTy(p, _) |
                     EntryLocal(p, _) |
                     EntryPat(p, _) |
                     EntryBlock(p, _) |
@@ -680,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,
@@ -971,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),
@@ -1059,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 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 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 0a363fddd53124f6d9cc7218e88d552b94e1469b..11bde922f47f2815047425593dc93e0caf220b41 100644 (file)
@@ -132,8 +132,13 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((item.id, item.span));
             } else {
-                span_err!(ctxt.session, item.span, E0138,
-                          "multiple 'start' functions");
+                struct_span_err!(
+                    ctxt.session, item.span, E0138,
+                    "multiple 'start' functions")
+                    .span_label(ctxt.start_fn.unwrap().1,
+                                &format!("previous `start` function here"))
+                    .span_label(item.span, &format!("multiple `start` functions"))
+                    .emit();
             }
         },
         EntryPointType::None => ()
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 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 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 3984d2b3d008b676680afc8d57e0091913ab63ed..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,
@@ -1024,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"),
@@ -1238,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));
@@ -1315,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 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 a816d26edadf36678d254f83b15f8932e5b4bdc9..13401e91265eb9ac8db3f4ae39490b01ec67d0fd 100644 (file)
@@ -1016,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());
@@ -1355,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 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 a7c534198923b7a1183bb7f9b7f0a0d65dcd24bf..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);
@@ -1885,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 904cffac6b3cd88e06b21391382e9f198f3a22b1..e0cbd972bd37f9f3c62fc9d65e26b18bb47915af 100644 (file)
@@ -760,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 366b58e06c4768050a0763d6f1d05b2b7e919b3e..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);
         },
         _ => ()
     }
@@ -1115,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");
@@ -1132,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));
                     }
@@ -1148,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 9c9453ae3d3145019af640b0fb16d909fd9be910..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;
@@ -1055,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());
@@ -1073,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 7f50522b2032b0e10f51d9cdb38f20efe7a9a182..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
     });
 
index 80f1910906b4c99c72654862f5eaac0e6d4ed45b..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};
@@ -654,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;
index 2b0bd14d83fa0bb35ff36d65a6dace4442b3c223..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;
@@ -141,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 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 2444d669f7f32345c8c95ec007130f17123a091f..285ca2e4d4d4de2367259410dd9f09a3e291e73c 100644 (file)
@@ -41,6 +41,7 @@ pub enum DefPathData {
     StructCtor,
     Initializer,
     Binding,
+    ImplTrait,
 }
 
 pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey {
@@ -72,6 +73,7 @@ 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,
     }
 }
 
@@ -103,5 +105,6 @@ fn recover_def_path_data(data: DefPathData, name: Option<InternedString>) -> hir
         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 4e754abe2aec04b19341c5f564caa482ecc4b115..cc1d07b33c7e830b6840e2d4b79045210db44f99 100644 (file)
@@ -1390,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 42a643b8af6fa167933e2d7eddb14b77fb7fa029..5e92a057da38280a46c8ca1ef21353e1bad1ef64 100644 (file)
@@ -27,7 +27,7 @@
 
 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::hir;
@@ -103,7 +103,7 @@ fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> {
         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
         }
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 b16ee9577463bc53958219e406fe1c0e45e0c219..7ebc72bcc5fca36875d7dc631774151219194300 100644 (file)
@@ -21,7 +21,7 @@
 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::*;
@@ -486,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 {
@@ -506,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);
                         }
 
@@ -592,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 []
@@ -617,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 {
@@ -652,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) {
@@ -670,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);
@@ -702,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,
@@ -724,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 &&
@@ -804,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);
 
@@ -991,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 26a907920e8dbf528389165d8c70a88d4e9f17cf..934357c9e1da2f4deb3d6019e30ae50bcdb3b972 100644 (file)
@@ -12,9 +12,9 @@
 #![allow(unreachable_code)]
 
 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};
@@ -79,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);
         }
     }
@@ -178,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)
@@ -353,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);
+                };
             }
         }
     }
@@ -388,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);
@@ -397,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 => {}
                     _ => {
@@ -406,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);
@@ -419,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()
@@ -431,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,
@@ -451,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)
                     }
                 }
@@ -479,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 ({:?} <- {:?}): {:?}",
@@ -505,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);
@@ -552,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,
             _ => {
@@ -695,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);
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 4e251793f6917ae645fc6c14c7581aa26c3f658d..eab16bd5bd1b5b2dda58b05943bf960e9242de6e 100644 (file)
@@ -77,10 +77,14 @@ fn require_loop(&self, name: &str, span: Span) {
         match self.cx {
             Loop => {}
             Closure => {
-                span_err!(self.sess, span, E0267, "`{}` inside of a closure", name);
+                struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
+                .span_label(span, &format!("cannot break inside of a closure"))
+                .emit();
             }
             Normal => {
-                span_err!(self.sess, span, E0268, "`{}` outside of loop", name);
+                struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
+                .span_label(span, &format!("cannot break outside of a loop"))
+                .emit();
             }
         }
     }
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 896b4a1847de982b29022a7cf370ee419866dff5..962509be324de363aa44c8e3bce6f87c3033b804 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,
@@ -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 6986f99926e1e43d9dd07874d5d25b29a9d4d6df..1e40aa7d1876620d276d7eb1bc9f99ea63cabc49 100644 (file)
@@ -505,7 +505,9 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResul
                 }
                 Success(binding) if !binding.is_importable() => {
                     let msg = format!("`{}` is not directly importable", target);
-                    span_err!(self.session, directive.span, E0253, "{}", &msg);
+                    struct_span_err!(self.session, directive.span, E0253, "{}", &msg)
+                        .span_label(directive.span, &format!("cannot be imported directly"))
+                        .emit();
                     // Do not import this illegal binding. Import a dummy binding and pretend
                     // everything is fine
                     self.import_dummy_binding(module, directive);
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 7025de523c378c4a68097bf17b08d64002fcdb12..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
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 b3729cc23f60fd3582253c9dbec04d102637ce67..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();
index 97b03312d7963a5c27330ddc075213ee4d6fe312..65eea1bbb6337cba32e1737be9da86b04a3f6d19 100644 (file)
@@ -337,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!();
         }
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 d0e00a6d593a5edf18742ebdae8156e467ac9ea0..187ffe353fdcb5f596bd87dbfb0994feaa8e8c79 100644 (file)
@@ -536,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 07595c5dbe1144cb987de5165a121575e420234a..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};
 
@@ -634,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)
             }
         }
     }
@@ -664,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,
@@ -678,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 => {
@@ -1702,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.
@@ -1745,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);
@@ -1809,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
@@ -1876,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 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 648d1f42fb5208322843c8a3d41791ae357ef2aa..99f1b13d4e4ab422a6c218dd0c202da6812b037e 100644 (file)
@@ -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 f11bb3175dab0855793a01103f551254589b39e5..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,
@@ -4640,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 7a923cd29d0fb9cde009f0a63416fe959fab9cb1..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!(
@@ -399,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>| {
@@ -536,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 f0ce4f6d2ec4225f9a022543cb8ca9ff6959cf6d..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()
@@ -1460,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 }
         }
@@ -1474,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 }
         }
@@ -1694,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();
 
@@ -1775,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());
@@ -1903,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
             }
@@ -2035,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
@@ -2095,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,
@@ -2108,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,
@@ -2191,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,
@@ -2206,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 5e733389e24c8b8e520eb61e5319e871d907d76a..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;
 
@@ -150,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
@@ -178,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();
     }
 }
 
@@ -188,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
@@ -326,7 +333,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
         ast_ty_to_ty_cache: RefCell::new(NodeMap()),
         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 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 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 1c25c8f77c196f444489178e37a471c67cdb3947..23687e10e476d40de9750064d09ded52a0624369 100644 (file)
@@ -83,11 +83,11 @@ fn oom_handler() -> ! {
         }
     }
 
-    #[cfg(not(target_os = "nacl"))]
+    #[cfg(not(any(target_os = "nacl", target_os = "emscripten")))]
     unsafe fn reset_sigpipe() {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
     }
-    #[cfg(target_os = "nacl")]
+    #[cfg(any(target_os = "nacl", target_os = "emscripten"))]
     unsafe fn reset_sigpipe() {}
 }
 
index 9c57f25dfcce8eb65585d51fa42d06459f114f94..c29e87f91c9a7e247471f2c4749e3264e663d572 100644 (file)
@@ -551,11 +551,13 @@ pub fn home_dir() -> Option<PathBuf> {
 
     #[cfg(any(target_os = "android",
               target_os = "ios",
-              target_os = "nacl"))]
+              target_os = "nacl",
+              target_os = "emscripten"))]
     unsafe fn fallback() -> Option<OsString> { None }
     #[cfg(not(any(target_os = "android",
                   target_os = "ios",
-                  target_os = "nacl")))]
+                  target_os = "nacl",
+                  target_os = "emscripten")))]
     unsafe fn fallback() -> Option<OsString> {
         #[cfg(not(target_os = "solaris"))]
         unsafe fn getpwduid_r(me: libc::uid_t, passwd: &mut libc::passwd,
index 1061ca87f6470894dda944ed69fb36d5e5ac75dc..75e10d2585308cecb85d17e374fff32c0842509f 100644 (file)
@@ -81,8 +81,7 @@ pub fn yield_now() {
     }
 
     #[cfg(any(target_os = "linux",
-              target_os = "android",
-              target_os = "emscripten"))]
+              target_os = "android"))]
     pub fn set_name(name: &CStr) {
         const PR_SET_NAME: libc::c_int = 15;
         // pthread wrapper only appeared in glibc 2.12, so we use syscall
@@ -118,9 +117,9 @@ pub fn set_name(name: &CStr) {
                                      name.as_ptr() as *mut libc::c_void);
         }
     }
-    #[cfg(any(target_env = "newlib", target_os = "solaris"))]
+    #[cfg(any(target_env = "newlib", target_os = "solaris", target_os = "emscripten"))]
     pub fn set_name(_name: &CStr) {
-        // Newlib and Illumos has no way to set a thread name.
+        // Newlib, Illumos and Emscripten have no way to set a thread name.
     }
 
     pub fn sleep(dur: Duration) {
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 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 64515b900d5b188e5b364319ecdd2d40ebd2ce90..850127d9f29505f72f0998f50e584346fd026dbd 100644 (file)
@@ -303,6 +303,7 @@ pub struct TestOpts {
     pub nocapture: bool,
     pub color: ColorConfig,
     pub quiet: bool,
+    pub test_threads: Option<usize>,
 }
 
 impl TestOpts {
@@ -317,6 +318,7 @@ fn new() -> TestOpts {
             nocapture: false,
             color: AutoColor,
             quiet: false,
+            test_threads: None,
         }
     }
 }
@@ -334,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);
@@ -349,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
@@ -408,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,
@@ -429,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))
@@ -871,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();
index 5e242db0a888db8c1dbd41c6aafb58ef9d27c196..680ad3ecd64a6c156cb65fce6d67a90e08be4d8e 100644 (file)
@@ -60,7 +60,6 @@ pub enum _Unwind_Reason_Code {
 pub const unwinder_private_data_size: usize = 2;
 
 #[cfg(target_arch = "asmjs")]
-// FIXME: Copied from arm. Need to confirm.
 pub const unwinder_private_data_size: usize = 20;
 
 #[repr(C)]
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 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 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 97d85e5e71e0898e10840cd33109da3cb4fe7b69..d4630d7c2effbe7bd7ee96ce6f1ca538656f03c0 100644 (file)
@@ -12,6 +12,9 @@
 
 #[start]
 fn foo(argc: isize, argv: *const *const u8) -> isize {}
+//~^ NOTE previous `start` function here
 
 #[start]
-fn f(argc: isize, argv: *const *const u8) -> isize {} //~ ERROR E0138
+fn f(argc: isize, argv: *const *const u8) -> isize {}
+//~^ ERROR E0138
+//~| NOTE multiple `start` functions
index 28fcf4452b3e85766629dd1a5f4f7789ffbf099b..5a06c01241b4bf7477b5738a59c41ae14c692091 100644 (file)
@@ -14,6 +14,8 @@ pub trait MyTrait {
     }
 }
 
-use foo::MyTrait::do_something; //~ ERROR E0253
+use foo::MyTrait::do_something;
+    //~^ ERROR E0253
+    //~|NOTE cannot be imported directly
 
 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() {}
index 6287256e866c9e948cc79d1291188979c932f372..b58fbce8bc648c2a92b4c2705b18605a34a153de 100644 (file)
@@ -10,4 +10,5 @@
 
 fn main() {
     let w = || { break; }; //~ ERROR E0267
+            //~| NOTE cannot break inside of a closure
 }
index 41e88e2f492a9c77a8441ddcaaa368dc07c1faff..3313e07667a1ca2d6f0a93cce945fa4a13c584f2 100644 (file)
@@ -10,4 +10,5 @@
 
 fn main() {
     break; //~ ERROR E0268
+    //~| NOTE cannot break outside of a loop
 }
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 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);
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 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 e6eaefb0490806e7c4c653cc5472c8f5ac10ef8d..f884bb2098eb192d560334cfafd13605ae51b665 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-android: FIXME(#10356)
 // ignore-windows: std::dynamic_lib does not work on Windows well
 // ignore-musl
+// ignore-emscripten no dynamic linking
 
 extern crate linkage_visibility as foo;
 
index 2975835a27149552df9eb98b674928b4a71bb8a2..26261348020f894dd832840396cd0348952255a5 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // exec-env:RUST_LOG=logging_enabled=info
+// ignore-emscripten: FIXME(#31622)
 
 
 #![feature(rustc_private)]
index 09759326afd911c69b942cddefb49a87c02332bc..183a522bba749290fc1cae429d3ebef7fe6c4f4e 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-windows
 // exec-env:RUST_LOG=debug
 // compile-flags:-C debug-assertions=y
+// ignore-emscripten: FIXME(#31622)
 
 #![feature(rustc_private)]
 
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(),
 }
index f42a6ab162b707437134a231725c21505e172e28..838005cbc91194ad8c05eea3ec3f2d1320ef390e 100644 (file)
@@ -17,6 +17,7 @@
 
 // compile-flags:-g -Cllvm-args=-enable-tail-merge=0
 // ignore-pretty as this critically relies on line numbers
+// ignore-emscripten spawning processes is not supported
 
 use std::io;
 use std::io::prelude::*;
index f1ce17c0736b687cecb72b6761ff08d89ef7b2bb..f26706d1754e018715d6af38de71dd730460367e 100644 (file)
@@ -10,6 +10,7 @@
 
 // no-pretty-expanded FIXME #15189
 // ignore-android FIXME #17520
+// ignore-emscripten spawning processes is not supported
 // compile-flags:-g
 
 use std::env;
index 72f952fb6c0df389fc5e54e15bdb1270938177b8..5b83ce48e5daddd793c9a948de233e06b20bc70e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows - this is a unix-specific test
+// ignore-emscripten
 
 #![feature(process_exec, libc)]
 
index 039245bfd08ba9eceb748a625d4298901f9802fe..130526e72b19cadf6623bbd7859085256df9c83b 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows - this is a unix-specific test
+// ignore-emscripten
 // ignore-pretty
 
 #![feature(process_exec)]
index f9e1b651a4933edcbb9493ff9e37d1a854038dc7..a8014768d78470c14b7196c26d3410a031ba66a1 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -Z force-dropflag-checks=on
+// ignore-emscripten
 
 // Quick-and-dirty test to ensure -Z force-dropflag-checks=on works as
 // expected. Note that the inlined drop-flag is slated for removal
index ce675547a68192cc379681cafa6701490be0d011..912cb4c5e877500055966d9e39931e9ed4b0fa8a 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten no threads support
+
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
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() {
index d22fa6494f03631ddc74a243778122a01dc20d4a..89af1db7c78f1f85d273958c416c9546d0ac76ea 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 use std::env::args;
 use std::process::Command;
 
index 2110f0b3bf9d607caef7cae98c8532033e41340d..bcb0c62d9fef4cc968976f9b2d8b24a02755a961 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 #![feature(path)]
 
index d17056e6d799d3c6fd3c39a69130cb81bca4f477..a96d189afaa8698d80d8ee5d81292ea9646f0f4a 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // exec-env:TEST_EXEC_ENV=22
-
+// ignore-emscripten FIXME: issue #31622
 
 use std::env;
 
index 3f6f1aa6b5fe394ebff4694c4f4e63ea9c90c840..8efc4cb1b17257debcd8204525c4905614560cab 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten No support for threads
+
 #![allow(unknown_features)]
 #![feature(std_misc)]
 
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));
+}
index f1e4f8dfa8c83e60201e52ed07247c19d6afe195..cfae9903a95e5ecd5204d7254228ee7f245319a7 100644 (file)
@@ -24,7 +24,8 @@ mod rusti {
           target_os = "dragonfly",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "emscripten"))]
 mod m {
     #[main]
     #[cfg(target_arch = "x86")]
index c81e16ebb7c60f3c62b4303112783fec5c03efc1..b350bd1a4ccbf84526ab3be5e21bd42204b83c9d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 // Make sure that if a process doesn't have its stdio/stderr descriptors set up
 // that we don't die in a large ball of fire
index 66201ff901f309ce702e706b0e312be280919d48..8f455c2fe4e1e73cac07ffc38e92cc6cd30ccf49 100644 (file)
@@ -12,6 +12,7 @@
 // aux-build:issue-12133-dylib.rs
 // aux-build:issue-12133-dylib2.rs
 // ignore-musl
+// ignore-emscripten no dylib support
 
 // pretty-expanded FIXME #23616
 
index c260aa95b57f1d556bdf83f77826ba120ab0ea7c..e1c2c5684fb5f18f34abf436c5de8245f2668f38 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-aarch64
+// ignore-emscripten
 #![feature(io, process_capture)]
 
 use std::env;
index 7e24c8f73ab701f6cfc730c688f72bc6ed6988c7..513ab91489c8d98ea96e970c8f29a4a1341ddea0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 #![feature(io, process_capture)]
 
index ba6815d5b7c6973e0a8588be3ffcb10177bb1c4b..ffe6b646794e14da62dfa83ec2afdf0385b3276d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 use std::env;
 use std::process::Command;
index 9562d113ada7059e5d7c487e4225ddb938ea74f0..d4f3d15b320d7987a3fa2172137372f406006fc6 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-aarch64
+// ignore-emscripten
 
 use std::process::Command;
 use std::env;
index 1fe443484665bc059d7dccc1ad9c88dc99b029a3..52c7911075ae9d3d51542e043286dea6c3328d72 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-aarch64
+// ignore-emscripten
 #![feature(std_misc, os)]
 
 #[cfg(unix)]
index 844826c45db92b41a816618684f9343923559ae9..393757035141d6e4137ff3c27ece14d55b4467e6 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // pretty-expanded FIXME #23616
+// ignore-emscripten
 
 use std::thread::Builder;
 
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() {}
index 9acfb04d781e0847db017dc524659079408ccee7..9b2b474351df6f4ec14da92d4445c28d570d4ad5 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 use std::thread;
 use std::env;
 use std::process::Command;
index efce148ea51d487f851e4bdab84c4dd1d45eca52..a905727afff4fcfd22d6ae1afd75b6880a45bceb 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 // compile-flags: -Z orbit=off
 // (blows the stack with MIR trans and no optimizations)
 
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 9e8f58694377a296303cb42551cb660313932730..9252762d1bdad191614920e1a1961858dd1b8d7a 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:issue-29485.rs
+// ignore-emscripten
 
 #[feature(recover)]
 
index ea603fc665ddab9722e9fe5c9bd9a10ff1ace481..035911302cf2499e1fe9d4985c55093734b2ba85 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 // Previously libstd would set stdio descriptors of a child process
 // by `dup`ing the requested descriptors to inherit directly into the
 // stdio descriptors. This, however, would incorrectly handle cases
index a12e569df2bc925625ec8094a0085f60d2509521..0f1f6290a2573a54862a91f66ca7a1609faab498 100644 (file)
@@ -45,7 +45,7 @@ trait Tr1 {
 
 mod m1 {
     fn f() {
-        struct Z {
+        pub struct Z {
             pub field: u8
         }
 
index f5635fddaf951c9514fd1b0b8c08529cfbc7eb46..76728a0d354b2c9267acccbf74561eab781d6ebf 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 use std::process::{Command, Stdio};
 use std::env;
 use std::sync::{Mutex, RwLock};
index 0794a5e0daf2f586af538cea6faac6bf810e1d61..17abf9cb1f251322b11b799fd5c449c02d2c32a8 100644 (file)
@@ -10,6 +10,7 @@
 
 // ignore-windows
 // ignore-macos
+// ignore-emscripten
 // aux-build:linkage1.rs
 
 #![feature(linkage)]
index 93e2a854ccb2a3efe0bbf5b0e544e8a94f1cd381..86fe06b176532faf6f5f90922fa581a5eac05311 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 fn check_for_no_backtrace(test: std::process::Output) {
     assert!(!test.status.success());
     let err = String::from_utf8_lossy(&test.stderr);
index 3658b6a508ab27f70dced8393300d83bd11e90a6..ad4d56ec50ac069f2973ce35953d7c35e7de7cdc 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 #![feature(libc)]
 
 extern crate libc;
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);
+        }
+    }
+}
index 7c2e3f0c91baff5774974c863736bb22470a1015..1ad43f5f17fb9b483fa35750524535b78a38f518 100644 (file)
@@ -7,6 +7,9 @@
 // <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-emscripten no threads support
+
 #![feature(panic_handler, const_fn, std_panic)]
 
 use std::sync::atomic::{AtomicUsize, Ordering};
index 9ef66ff2d713c6890dfa54dbfb1fe256a72cf826..a5d408448a033388d4da4f69a564ba474d28beaa 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 use std::env;
 use std::process::{self, Command, Stdio};
 
index 3096fe4a266c996e2551e2c994a8cccc16b5015a..cce5ef4fe17c37dd26a1628535c2f0a12e02b577 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 use std::process::Command;
 use std::env;
index a155ee396b614bc917d1923cad9fe95b2ced0c9d..d3d847127ee954430d82ee0366dd08114344ba45 100644 (file)
@@ -17,6 +17,7 @@
 // intact.
 
 // ignore-aarch64
+// ignore-emscripten
 
 use std::io::prelude::*;
 use std::io;
index 2161864f0b69654fc1de16eb4f694763f45ab239..4863979b3f6c2bdd0731cc40add9a6cdd0f416d5 100644 (file)
@@ -42,7 +42,8 @@ struct Outer {
           target_os = "dragonfly",
           target_os = "netbsd",
           target_os = "openbsd",
-          target_os = "solaris"))]
+          target_os = "solaris",
+          target_os = "emscripten"))]
 mod m {
     #[cfg(target_arch = "x86")]
     pub mod m {
index 23d5a08e216443bf5e8a5b74c04fc4e5ab969491..f81c3f2e99d3672ac8176fb41b45b83b094e807e 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
+
 #![feature(start)]
 
 use std::ffi::CStr;
index 0158c4282dae77e808f6204fa97a90c5f198f31f..df64d7140b4b5a2c6b628c249410900cc9b132b4 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten can't run commands
+
 #![feature(libc)]
 
 extern crate libc;
index 51b369092f0f4e7a2cb42703c1f22c7ef71a835c..c7759ca743bbb6e3669233f0fc75705b4af85624 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // ignore-windows
+// ignore-emscripten
 
 use std::env;
 use std::process::Command;
index 7734a2e80c3c4361bfb1cbd6d32636d85ed37fff..4eb4720e8d7be43f611dc444057d38b780d74a48 100644 (file)
@@ -12,6 +12,7 @@
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
 // ignore-aarch64
+// ignore-emscripten
 
 use std::env;
 use std::io::prelude::*;
index 8b06b02f3cba5fe791ae812c91c206d81d28011b..9acc6ff8cf08474f2ec151ba9b2b8161d499c9f6 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten no threads support
+
 use std::thread::{self, sleep};
 use std::time::Duration;
 use std::sync::{Arc, Mutex};
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 795c3f46f757941254bf62bee444625977ee405f..1d1c83cf12a15bb2eba21f7cba09a4f19ec62322 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-emscripten
 
 #![feature(libc)]
 
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 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 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);
+    }
 }