]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #31061 - brson:bib, r=steveklabnik
authorSteve Klabnik <steve@steveklabnik.com>
Sat, 23 Jan 2016 14:38:42 +0000 (09:38 -0500)
committerSteve Klabnik <steve@steveklabnik.com>
Sat, 23 Jan 2016 14:38:42 +0000 (09:38 -0500)
175 files changed:
COPYRIGHT
Makefile.in
configure
mk/crates.mk
mk/main.mk
mk/perf.mk [deleted file]
mk/platform.mk
mk/tests.mk
src/doc/book/primitive-types.md
src/doc/version_info.html.template
src/etc/cmathconsts.c [deleted file]
src/etc/libc.c [deleted file]
src/etc/mingw-fix-include/README.txt [deleted file]
src/etc/mingw-fix-include/bits/c++config.h [deleted file]
src/etc/mingw-fix-include/winbase.h [deleted file]
src/etc/mingw-fix-include/winsock2.h [deleted file]
src/etc/mklldef.py [deleted file]
src/jemalloc
src/liballoc/arc.rs
src/liballoc/rc.rs
src/libcollections/string.rs
src/libcore/cmp.rs
src/libcore/option.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/slice.rs
src/liblibc
src/librustc/dep_graph/mod.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/middle/astconv_util.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_const.rs [deleted file]
src/librustc/middle/check_loop.rs [deleted file]
src/librustc/middle/check_match.rs
src/librustc/middle/check_rvalues.rs [deleted file]
src/librustc/middle/check_static_recursion.rs [deleted file]
src/librustc/middle/const_eval.rs
src/librustc/middle/const_qualif.rs [new file with mode: 0644]
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/def.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/subst.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty/context.rs
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/util.rs
src/librustc/mir/repr.rs
src/librustc/mir/visit.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_data_structures/bitvec.rs
src/librustc_driver/driver.rs
src/librustc_front/lowering.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/astencode.rs
src/librustc_metadata/csearch.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/loader.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/pattern.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/transform/erase_regions.rs
src/librustc_passes/consts.rs [new file with mode: 0644]
src/librustc_passes/diagnostics.rs
src/librustc_passes/lib.rs
src/librustc_passes/loops.rs [new file with mode: 0644]
src/librustc_passes/rvalues.rs [new file with mode: 0644]
src/librustc_passes/static_recursion.rs [new file with mode: 0644]
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/back/msvc/mod.rs
src/librustc_trans/save/dump_csv.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/recorder.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/mir/analyze.rs
src/librustc_trans/trans/mir/did.rs
src/librustc_trans/trans/mir/mod.rs
src/librustc_trans/trans/mir/rvalue.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/libstd/collections/hash/map.rs
src/libstd/error.rs
src/libstd/ffi/c_str.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/memchr.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/ext/fs.rs
src/libstd/sys/windows/fs.rs
src/libsyntax/codemap.rs
src/test/auxiliary/issue-30535.rs [new file with mode: 0644]
src/test/auxiliary/issue_30123_aux.rs [new file with mode: 0644]
src/test/auxiliary/variant-namespacing.rs [new file with mode: 0644]
src/test/compile-fail/allocator-dylib-is-system.rs
src/test/compile-fail/allocator-rust-dylib-is-jemalloc.rs
src/test/compile-fail/dep-graph-assoc-type-trans.rs [new file with mode: 0644]
src/test/compile-fail/dep-graph-trait-impl.rs
src/test/compile-fail/empty-struct-braces-expr.rs
src/test/compile-fail/empty-struct-braces-pat-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/issue-10545.rs
src/test/compile-fail/issue-30123.rs [new file with mode: 0644]
src/test/compile-fail/issue-30535.rs [new file with mode: 0644]
src/test/compile-fail/loop-does-not-diverge.rs
src/test/compile-fail/loop-proper-liveness.rs [new file with mode: 0644]
src/test/compile-fail/loop-properly-diverging-2.rs [new file with mode: 0644]
src/test/compile-fail/loop-properly-diverging.rs [new file with mode: 0644]
src/test/compile-fail/privacy1.rs
src/test/compile-fail/struct-field-privacy.rs
src/test/compile-fail/variant-namespacing.rs [new file with mode: 0644]
src/test/compile-fail/xcrate-unit-struct.rs
src/test/run-make/c-link-to-rust-dylib/Makefile
src/test/run-make/c-link-to-rust-staticlib/Makefile
src/test/run-make/lto-smoke-c/Makefile
src/test/run-make/output-type-permutations/Makefile
src/test/run-make/static-dylib-by-default/Makefile
src/test/run-pass/allocator-default.rs
src/test/run-pass/allocator-jemalloc.rs
src/test/run-pass/associated-const-match-patterns.rs
src/test/run-pass/empty-struct-braces.rs
src/test/run-pass/mir_temp_promotions.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-binary-heap-push.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-btreemap-insert.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-linkedlist-push.rs [new file with mode: 0644]
src/test/run-pass/zero-sized-vec-push.rs [new file with mode: 0644]

index 5ab70b7120fd9e44a6b34d49595c68c5d9928cd0..c7ea3d39c5c19b1c5e60f9278bdae499336964d0 100644 (file)
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -7,7 +7,7 @@ terms.
 Longer version:
 
 The Rust Project is copyright 2016, The Rust Project
-Developers (given in the file AUTHORS.txt).
+Developers.
 
 Licensed under the Apache License, Version 2.0
 <LICENSE-APACHE or
index baa7e77394a0da49f690c804860af26e528771e7..e41ce56b9ed0c9b5d87e928cfbff73e79b1760bb 100644 (file)
@@ -220,19 +220,12 @@ endif
 # The test suite
 ifneq ($(strip $(findstring check,$(MAKECMDGOALS)) \
                $(findstring test,$(MAKECMDGOALS))  \
-               $(findstring perf,$(MAKECMDGOALS))  \
                $(findstring tidy,$(MAKECMDGOALS))),)
   CFG_INFO := $(info cfg: including test rules)
   include $(CFG_SRC_DIR)mk/tests.mk
   include $(CFG_SRC_DIR)mk/grammar.mk
 endif
 
-# Performance and benchmarking
-ifneq ($(findstring perf,$(MAKECMDGOALS)),)
-  CFG_INFO := $(info cfg: including perf rules)
-  include $(CFG_SRC_DIR)mk/perf.mk
-endif
-
 # Copy all the distributables to another directory for binary install
 ifneq ($(strip $(findstring prepare,$(MAKECMDGOALS)) \
                $(findstring dist,$(MAKECMDGOALS)) \
index 287b7b352195cdb77ec62240296da45e8d193625..7df98d1bd565dbbf2add6ab3c01c19538ddf8cf3 100755 (executable)
--- a/configure
+++ b/configure
@@ -550,7 +550,7 @@ CFG_SELF="$0"
 CFG_CONFIGURE_ARGS="$@"
 
 
-case "${CFG_SRC_DIR}" in  
+case "${CFG_SRC_DIR}" in
     *\ * )
         err "The path to the rust source directory contains spaces, which is not supported"
         ;;
@@ -892,6 +892,13 @@ then
     CFG_DISABLE_JEMALLOC=1
 fi
 
+if [ $CFG_OSTYPE = pc-windows-gnu ]
+then
+    # FIXME(#31030) - there's not a great reason to disable jemalloc here
+    step_msg "on Windows, disabling jemalloc"
+    CFG_DISABLE_JEMALLOC=1
+fi
+
 # OS X 10.9, gcc is actually clang. This can cause some confusion in the build
 # system, so if we find that gcc is clang, we should just use clang directly.
 if [ $CFG_OSTYPE = apple-darwin -a -z "$CFG_ENABLE_CLANG" ]
@@ -1354,16 +1361,22 @@ for h in $CFG_HOST
 do
     for t in $CFG_TARGET
     do
+        # host bin dir stage0
+        make_dir $h/stage0/bin
+
         # host lib dir stage0
         make_dir $h/stage0/lib
 
+        # host test dir stage0
+        make_dir $h/stage0/test
+
         # target bin dir stage0
         make_dir $h/stage0/lib/rustlib/$t/bin
 
         # target lib dir stage0
         make_dir $h/stage0/lib/rustlib/$t/lib
 
-        for i in 1 2 3
+        for i in 1 2 3
         do
             # host bin dir
             make_dir $h/stage$i/bin
index 5cc8a46878439740273abc44fc2629219da25819..f47c4857ef86132d99b4a1541430e760de71c1c6 100644 (file)
@@ -102,7 +102,7 @@ DEPS_rustc_front := std syntax log serialize
 DEPS_rustc_lint := rustc log syntax
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_rustc_metadata := rustc rustc_front syntax rbml
-DEPS_rustc_passes := syntax rustc core
+DEPS_rustc_passes := syntax rustc core rustc_front
 DEPS_rustc_mir := rustc rustc_front syntax
 DEPS_rustc_resolve := arena rustc rustc_front log syntax
 DEPS_rustc_platform_intrinsics := rustc rustc_llvm
index a478cafd6b95880e004059896a96134cb5276aa0..9d75771dc80a862833c91a6ab8a5c23c1a76c0dc 100644 (file)
@@ -13,7 +13,7 @@
 ######################################################################
 
 # The version number
-CFG_RELEASE_NUM=1.7.0
+CFG_RELEASE_NUM=1.8.0
 
 # An optional number to put after the label, e.g. '.2' -> '-beta.2'
 # NB Make sure it starts with a dot to conform to semver pre-release
@@ -522,14 +522,6 @@ STAGE$(1)_T_$(2)_H_$(3) := \
                $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
                 $$(RUSTC_FLAGS_$(2))
 
-PERF_STAGE$(1)_T_$(2)_H_$(3) := \
-       $$(Q)$$(call CFG_RUN_TARG_$(3),$(1), \
-               $$(CFG_PERF_TOOL) \
-               $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
-               --cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3)) \
-               $$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
-                $$(RUSTC_FLAGS_$(2))
-
 endef
 
 $(foreach build,$(CFG_HOST), \
diff --git a/mk/perf.mk b/mk/perf.mk
deleted file mode 100644 (file)
index 16cbaab..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-
-ifdef CFG_PERF_TOOL
-rustc-perf$(X): $(CFG_BUILD)/stage2/bin/rustc$(X_$(CFG_BUILD))
-       @$(call E, perf compile: $@)
-       $(PERF_STAGE2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
-                -o $@ $(COMPILER_CRATE) >rustc-perf.err 2>&1
-       $(Q)rm -f $(LIBRUSTC_GLOB)
-else
-rustc-perf$(X): $(CFG_BUILD)/stage2/bin/rustc$(X_$(CFG_BUILD))
-       $(Q)touch $@
-endif
-
-perf: check-stage2-perf rustc-perf$(X_$(CFG_BUILD))
-       $(Q)find $(CFG_BUILD)/test/perf -name \*.err | xargs cat
-       $(Q)cat rustc-perf.err
index 5239086a6552ca26739e280736c4e0e3b37f6cd1..9c74e657a846442979684e70b479db988915326e 100644 (file)
@@ -77,23 +77,6 @@ define DEF_GOOD_VALGRIND
 endef
 $(foreach t,$(CFG_TARGET),$(eval $(call DEF_GOOD_VALGRIND,$(t))))
 
-ifneq ($(findstring linux,$(CFG_OSTYPE)),)
-  ifdef CFG_PERF
-    ifneq ($(CFG_PERF_WITH_LOGFD),)
-        CFG_PERF_TOOL := $(CFG_PERF) stat -r 3 --log-fd 2
-    else
-        CFG_PERF_TOOL := $(CFG_PERF) stat -r 3
-    endif
-  else
-    ifdef CFG_VALGRIND
-      CFG_PERF_TOOL := \
-        $(CFG_VALGRIND) --tool=cachegrind --cache-sim=yes --branch-sim=yes
-    else
-      CFG_PERF_TOOL := /usr/bin/time --verbose
-    endif
-  endif
-endif
-
 AR := ar
 
 define SET_FROM_CFG
index 0f30ff8711e5e26fc8063e8155f69a6727c2bbc8..b3f7278ad62ccb6c45d7c31996f356d044452939 100644 (file)
@@ -50,11 +50,6 @@ ifdef CFG_VALGRIND
   CTEST_RUNTOOL = --runtool "$(CFG_VALGRIND)"
 endif
 
-# Arguments to the perf tests
-ifdef CFG_PERF_TOOL
-  CTEST_PERF_RUNTOOL = --runtool "$(CFG_PERF_TOOL)"
-endif
-
 CTEST_TESTARGS := $(TESTARGS)
 
 # --bench is only relevant for crate tests, not for the compile tests
@@ -70,12 +65,6 @@ endif
 # This prevents tests from failing with some locales (fixes #17423).
 export LC_ALL=C
 
-# If we're running perf then set this environment variable
-# to put the benchmarks into 'hard mode'
-ifeq ($(MAKECMDGOALS),perf)
-  export RUST_BENCH=1
-endif
-
 TEST_LOG_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
 TEST_OK_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).ok
 
@@ -486,10 +475,6 @@ CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
 CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
 RUSTDOCCK_RS := $(wildcard $(S)src/test/rustdoc/*.rs)
 
-# perf tests are the same as bench tests only they run under
-# a performance monitor.
-PERF_RS := $(wildcard $(S)src/test/bench/*.rs)
-
 RPASS_TESTS := $(RPASS_RS)
 RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
 RPASS_FULL_TESTS := $(RPASS_FULL_RS)
@@ -499,7 +484,6 @@ RFAIL_TESTS := $(RFAIL_RS)
 CFAIL_TESTS := $(CFAIL_RS)
 PFAIL_TESTS := $(PFAIL_RS)
 BENCH_TESTS := $(BENCH_RS)
-PERF_TESTS := $(PERF_RS)
 PRETTY_TESTS := $(PRETTY_RS)
 DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
 DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
@@ -551,11 +535,6 @@ CTEST_BUILD_BASE_bench = bench
 CTEST_MODE_bench = run-pass
 CTEST_RUNTOOL_bench = $(CTEST_RUNTOOL)
 
-CTEST_SRC_BASE_perf = bench
-CTEST_BUILD_BASE_perf = perf
-CTEST_MODE_perf = run-pass
-CTEST_RUNTOOL_perf = $(CTEST_PERF_RUNTOOL)
-
 CTEST_SRC_BASE_debuginfo-gdb = debuginfo
 CTEST_BUILD_BASE_debuginfo-gdb = debuginfo-gdb
 CTEST_MODE_debuginfo-gdb = debuginfo-gdb
@@ -625,7 +604,7 @@ TEST_SREQ$(1)_T_$(2)_H_$(3) = \
        $$(HBIN$(1)_H_$(3))/compiletest$$(X_$(3)) \
        $$(SREQ$(1)_T_$(2)_H_$(3))
 
-# Rules for the cfail/rfail/rpass/bench/perf test runner
+# Rules for the cfail/rfail/rpass/bench test runner
 
 # The tests select when to use debug configuration on their own;
 # remove directive, if present, from CFG_RUSTC_FLAGS (issue #7898).
@@ -689,7 +668,6 @@ CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
 CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
 CTEST_DEPS_pfail_$(1)-T-$(2)-H-$(3) = $$(PFAIL_TESTS)
 CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
-CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
 CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
 CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
                                                $(S)src/etc/lldb_batchmode.py \
@@ -761,7 +739,7 @@ endif
 endef
 
 CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
-       bench perf debuginfo-gdb debuginfo-lldb codegen rustdocck
+       bench debuginfo-gdb debuginfo-lldb codegen rustdocck
 
 $(foreach host,$(CFG_HOST), \
  $(eval $(foreach target,$(CFG_TARGET), \
@@ -934,7 +912,6 @@ TEST_GROUPS = \
        cfail \
        pfail \
        bench \
-       perf \
        rmake \
        rustdocck \
        debuginfo-gdb \
index cfd5372b90f91f92f19a60c84e5c972d2e349363..840609d1dd62954f00211ad1f9df1a7ae637c379 100644 (file)
@@ -164,6 +164,9 @@ copying. For example, you might want to reference only one line of a file read
 into memory. By nature, a slice is not created directly, but from an existing
 variable binding. Slices have a defined length, can be mutable or immutable.
 
+Internally, slices are represented as a pointer to the beginning of the data 
+and a length.
+
 ## Slicing syntax
 
 You can use a combo of `&` and `[]` to create a slice from various things. The
index 2fda57923cd8faf428cebe2dbb077f11125630a2..7215e4f13c9bb4d914032eda4192430e69c51a41 100644 (file)
@@ -1,5 +1,5 @@
 <div id="versioninfo">
-  <img src="https://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt><br>
+  <img src="https://www.rust-lang.org/logos/rust-logo-32x32-blk.png" width="32" height="32" alt="Rust logo"><br>
   <span class="white-sticker"><a href="https://www.rust-lang.org">Rust</a> VERSION</span><br>
   <a href="https://github.com/rust-lang/rust/commit/STAMP"
     class="hash white-sticker">SHORT_HASH</a>
diff --git a/src/etc/cmathconsts.c b/src/etc/cmathconsts.c
deleted file mode 100644 (file)
index f523b4c..0000000
+++ /dev/null
@@ -1,103 +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.
-//
-//
-// This is a helper C program for generating required math constants
-//
-// Should only be required when porting to a different target architecture
-// (or c compiler/libmath)
-//
-// Call with <rust machine type of c_float> <rust machine type of c_double>
-// and ensure that libcore/cmath.rs complies to the output
-//
-// Requires a printf that supports "%a" specifiers
-//
-
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-
-// must match std::ctypes
-
-#define C_FLT(x) (float)x
-#define C_DBL(x) (double)x
-
-int main(int argc, char** argv) {
-  if (argc != 3) {
-    fprintf(stderr, "%s <ctypes::c_float> <ctypes::c_double>\n", argv[0]);
-    return 1;
-  }
-  char* c_flt = argv[1];
-  char* c_dbl = argv[2];
-
-  printf("mod c_float_math_consts {\n");
-  printf("    const pi: c_float = %a_%s;\n", C_FLT(M_PI), c_flt);
-  printf("    const div_1_pi: c_float = %a_%s;\n", C_FLT(M_1_PI), c_flt);
-  printf("    const div_2_pi: c_float = %a_%s;\n", C_FLT(M_2_PI), c_flt);
-  printf("    const div_pi_2: c_float = %a_%s;\n", C_FLT(M_PI_2), c_flt);
-  printf("    const div_pi_4: c_float = %a_%s;\n", C_FLT(M_PI_4), c_flt);
-  printf("    const div_2_sqrtpi: c_float = %a_%s;\n",
-         C_FLT(M_2_SQRTPI), c_flt);
-  printf("    const e: c_float = %a_%s;\n", C_FLT(M_E), c_flt);
-  printf("    const log2_e: c_float = %a_%s;\n", C_FLT(M_LOG2E), c_flt);
-  printf("    const log10_e: c_float = %a_%s;\n", C_FLT(M_LOG10E), c_flt);
-  printf("    const ln_2: c_float = %a_%s;\n",  C_FLT(M_LN2), c_flt);
-  printf("    const ln_10: c_float = %a_%s;\n",  C_FLT(M_LN10), c_flt);
-  printf("    const sqrt2: c_float = %a_%s;\n",  C_FLT(M_SQRT2), c_flt);
-  printf("    const div_1_sqrt2: c_float = %a_%s;\n",
-         C_FLT(M_SQRT1_2), c_flt);
-  printf("}\n\n");
-
-  printf("mod c_double_math_consts {\n");
-  printf("    const pi: c_double = %a_%s;\n", C_DBL(M_PI), c_dbl);
-  printf("    const div_1_pi: c_double = %a_%s;\n", C_DBL(M_1_PI), c_dbl);
-  printf("    const div_2_pi: c_double = %a_%s;\n", C_DBL(M_2_PI), c_dbl);
-  printf("    const div_pi_2: c_double = %a_%s;\n", C_DBL(M_PI_2), c_dbl);
-  printf("    const div_pi_4: c_double = %a_%s;\n", C_DBL(M_PI_4), c_dbl);
-  printf("    const div_2_sqrtpi: c_double = %a_%s;\n",
-         C_DBL(M_2_SQRTPI), c_dbl);
-  printf("    const e: c_double = %a_%s;\n", C_DBL(M_E), c_dbl);
-  printf("    const log2_e: c_double = %a_%s;\n", C_DBL(M_LOG2E), c_dbl);
-  printf("    const log10_e: c_double = %a_%s;\n", C_DBL(M_LOG10E), c_dbl);
-  printf("    const ln_2: c_double = %a_%s;\n", C_DBL(M_LN2), c_dbl);
-  printf("    const ln_10: c_double = %a_%s;\n", C_DBL(M_LN10), c_dbl);
-  printf("    const sqrt2: c_double = %a_%s;\n", C_DBL(M_SQRT2), c_dbl);
-  printf("    const div_1_sqrt2: c_double = %a_%s;\n",
-         C_DBL(M_SQRT1_2), c_dbl);
-  printf("}\n\n");
-
-  printf("mod c_float_targ_consts {\n");
-  printf("    const radix: uint = %uu;\n", FLT_RADIX);
-  printf("    const mantissa_digits: uint = %uu;\n", FLT_MANT_DIG);
-  printf("    const digits: uint = %uu;\n", FLT_DIG);
-  printf("    const min_exp: int = %i;\n", FLT_MIN_EXP);
-  printf("    const max_exp: int = %i;\n", FLT_MAX_EXP);
-  printf("    const min_10_exp: int = %i;\n", FLT_MIN_10_EXP);
-  printf("    const max_10_exp: int = %i;\n", FLT_MAX_10_EXP);
-  printf("    const min_value: c_float = %a_%s;\n", C_FLT(FLT_MIN), c_flt);
-  printf("    const max_value: c_float = %a_%s;\n", C_FLT(FLT_MAX), c_flt);
-  printf("    const epsilon: c_float = %a_%s;\n", C_FLT(FLT_EPSILON), c_flt);
-  printf("}\n\n");
-
-  printf("mod c_double_targ_consts {\n");
-  printf("    const radix: uint = %uu;\n", FLT_RADIX);
-  printf("    const mantissa_digits: uint = %uu;\n", DBL_MANT_DIG);
-  printf("    const digits: uint = %uu;\n", DBL_DIG);
-  printf("    const min_exp: int = %i;\n", DBL_MIN_EXP);
-  printf("    const max_exp: int = %i;\n", DBL_MAX_EXP);
-  printf("    const min_10_exp: int = %i;\n", DBL_MIN_10_EXP);
-  printf("    const max_10_exp: int = %i;\n", DBL_MAX_10_EXP);
-  printf("    const min_value: c_double = %a_%s;\n", C_DBL(DBL_MIN), c_dbl);
-  printf("    const max_value: c_double = %a_%s;\n", C_DBL(DBL_MAX), c_dbl);
-  printf("    const epsilon: c_double = %a_%s;\n", C_DBL(DBL_EPSILON), c_dbl);
-  printf("}\n");
-
-  return 0;
-}
diff --git a/src/etc/libc.c b/src/etc/libc.c
deleted file mode 100644 (file)
index 249b5d2..0000000
+++ /dev/null
@@ -1,266 +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.
-
-/*
- * This calculates the platform-variable portion of the libc module.
- * Move code in here only as you discover it is platform-variable.
- *
- */
-
- /* c95 */
-#include <stddef.h>
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <wchar.h>
-
-/* c99 */
-#include <inttypes.h>
-
-/* posix */
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#define S(T) ((((T)-1)<0) ? 'i' : 'u')
-#define B(T) (((int)sizeof(T)) * CHAR_BIT)
-#define put_type(N,T) \
-        printf("        type %s = %c%d;\n", N, S(T), B(T))
-
-#define put_ftype(N,T) \
-        printf("        type %s = f%d;\n", N, B(T))
-
-#define CT(T) ((((T)-1)<0) ? "int" : "uint")
-#define CS(T) ((((T)-1)<0) ? "" : "_u")
-#define put_const(N,T)                            \
-        printf("        const %s : %s = %d%s;\n", \
-               #N, CT(T), N, CS(T))
-
-void c95_types() {
-  printf("    mod c95 {\n");
-
-  put_type("c_char", char);
-  put_type("c_schar", signed char);
-  put_type("c_uchar", unsigned char);
-
-  put_type("c_short", short);
-  put_type("c_ushort", unsigned short);
-
-  put_type("c_int", int);
-  put_type("c_uint", unsigned int);
-
-  put_type("c_long", long);
-  put_type("c_ulong", unsigned long);
-
-  put_ftype("c_float", float);
-  put_ftype("c_double", double);
-
-  put_type("size_t", size_t);
-  put_type("ptrdiff_t", ptrdiff_t);
-
-  put_type("clock_t", clock_t);
-  put_type("time_t", time_t);
-
-  put_type("wchar_t", wchar_t);
-
-  printf("    }\n");
-}
-
-void c99_types() {
-  printf("    mod c99 {\n");
-
-  put_type("c_longlong", long long);
-  put_type("c_ulonglong", unsigned long long);
-
-  put_type("intptr_t", intptr_t);
-  put_type("uintptr_t", uintptr_t);
-
-  printf("    }\n");
-}
-
-void posix88_types() {
-  printf("    mod posix88 {\n");
-
-  put_type("off_t", off_t);
-  put_type("dev_t", dev_t);
-  put_type("ino_t", ino_t);
-  put_type("pid_t", pid_t);
-#ifndef __WIN32__
-  put_type("uid_t", uid_t);
-  put_type("gid_t", gid_t);
-#endif
-  put_type("useconds_t", useconds_t);
-  put_type("mode_t", mode_t);
-
-  put_type("ssize_t", ssize_t);
-
-  printf("    }\n");
-}
-
-void extra_types() {
-  printf("    mod extra {\n");
-  printf("    }\n");
-}
-
-
-void c95_consts() {
-  printf("    mod c95 {\n");
-
-  put_const(EXIT_FAILURE, int);
-  put_const(EXIT_SUCCESS, int);
-  put_const(RAND_MAX, int);
-
-  put_const(EOF, int);
-  put_const(SEEK_SET, int);
-  put_const(SEEK_CUR, int);
-  put_const(SEEK_END, int);
-
-  put_const(_IOFBF, int);
-  put_const(_IONBF, int);
-  put_const(_IOLBF, int);
-
-  put_const(BUFSIZ, size_t);
-  put_const(FOPEN_MAX, size_t);
-  put_const(FILENAME_MAX, size_t);
-  put_const(L_tmpnam, size_t);
-  put_const(TMP_MAX, size_t);
-
-  printf("    }\n");
-}
-
-
-void posix88_consts() {
-  printf("    mod posix88 {\n");
-  put_const(O_RDONLY, int);
-  put_const(O_WRONLY, int);
-  put_const(O_RDWR, int);
-  put_const(O_APPEND, int);
-  put_const(O_CREAT, int);
-  put_const(O_EXCL, int);
-  put_const(O_TRUNC, int);
-
-  put_const(S_IFIFO, int);
-  put_const(S_IFCHR, int);
-  put_const(S_IFBLK, int);
-  put_const(S_IFDIR, int);
-  put_const(S_IFREG, int);
-  put_const(S_IFLNK, int);
-  put_const(S_IFMT, int);
-
-  put_const(S_IEXEC, int);
-  put_const(S_IWRITE, int);
-  put_const(S_IREAD, int);
-
-  put_const(S_IRWXU, int);
-  put_const(S_IXUSR, int);
-  put_const(S_IWUSR, int);
-  put_const(S_IRUSR, int);
-
-  put_const(S_IRWXG, int);
-  put_const(S_IXGRP, int);
-  put_const(S_IWGRP, int);
-  put_const(S_IRGRP, int);
-
-  put_const(S_IRWXO, int);
-  put_const(S_IXOTH, int);
-  put_const(S_IWOTH, int);
-  put_const(S_IROTH, int);
-
-#ifdef F_OK
-  put_const(F_OK, int);
-#endif
-#ifdef R_OK
-  put_const(R_OK, int);
-#endif
-#ifdef W_OK
-  put_const(W_OK, int);
-#endif
-#ifdef X_OK
-  put_const(X_OK, int);
-#endif
-
-#ifdef STDIN_FILENO
-  put_const(STDIN_FILENO, int);
-#endif
-#ifdef STDOUT_FILENO
-  put_const(STDOUT_FILENO, int);
-#endif
-#ifdef STDERR_FILENO
-  put_const(STDERR_FILENO, int);
-#endif
-
-#ifdef F_LOCK
-  put_const(F_LOCK, int);
-#endif
-
-#ifdef F_TEST
-  put_const(F_TEST, int);
-#endif
-
-#ifdef F_TLOCK
-  put_const(F_TLOCK, int);
-#endif
-
-#ifdef F_ULOCK
-  put_const(F_ULOCK, int);
-#endif
-
-  printf("    }\n");
-}
-
-void extra_consts() {
-  printf("    mod extra {\n");
-#ifdef O_RSYNC
-  put_const(O_RSYNC, int);
-#endif
-
-#ifdef O_DSYNC
-  put_const(O_DSYNC, int);
-#endif
-
-#ifdef O_SYNC
-  put_const(O_SYNC, int);
-#endif
-
-#ifdef O_TEXT
-  put_const(O_TEXT, int);
-#endif
-
-#ifdef O_BINARY
-  put_const(O_BINARY, int);
-#endif
-
-#ifdef O_IRUSR
-  put_const(O_IRUSR, int);
-#endif
-
-#ifdef O_IWUSR
-  put_const(O_IWUSR, int);
-#endif
-
-  printf("    }\n");
-}
-
-int main() {
-  printf("mod types {");
-  c95_types();
-  c99_types();
-  posix88_types();
-  extra_types();
-  printf("}\n");
-
-  printf("mod consts {\n");
-  c95_consts();
-  posix88_consts();
-  extra_consts();
-  printf("}\n");
-}
diff --git a/src/etc/mingw-fix-include/README.txt b/src/etc/mingw-fix-include/README.txt
deleted file mode 100644 (file)
index e36e6ab..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-The purpose of these headers is to fix issues with mingw v4.0, as described in #9246.
-
-This works by adding this directory to GCC include search path before mingw system headers directories,
-so we can intercept their inclusions and add missing definitions without having to modify files in mingw/include.
-
-Once mingw fixes all 3 issues mentioned in #9246, this directory and all references to it from rust/mk/* may be removed.
diff --git a/src/etc/mingw-fix-include/bits/c++config.h b/src/etc/mingw-fix-include/bits/c++config.h
deleted file mode 100644 (file)
index 57533ef..0000000
+++ /dev/null
@@ -1,18 +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.
-
-#ifndef _FIX_CXXCONFIG_H
-#define _FIX_CXXCONFIG_H 1
-
-#define _GLIBCXX_HAVE_FENV_H 1
-
-#include_next <bits/c++config.h>
-
-#endif
diff --git a/src/etc/mingw-fix-include/winbase.h b/src/etc/mingw-fix-include/winbase.h
deleted file mode 100644 (file)
index b1674f5..0000000
+++ /dev/null
@@ -1,18 +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.
-
-#ifndef _FIX_WINBASE_H
-#define _FIX_WINBASE_H 1
-
-#define NTDDK_VERSION NTDDI_VERSION
-
-#include_next <winbase.h>
-
-#endif
diff --git a/src/etc/mingw-fix-include/winsock2.h b/src/etc/mingw-fix-include/winsock2.h
deleted file mode 100644 (file)
index 5096c2f..0000000
+++ /dev/null
@@ -1,27 +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.
-
-#ifndef _FIX_WINSOCK2_H
-#define _FIX_WINSOCK2_H 1
-
-#include_next <winsock2.h>
-
-// mingw 4.0.x has broken headers (#9246) but mingw-w64 does not.
-#if defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION == 4
-
-typedef struct pollfd {
-  SOCKET fd;
-  short  events;
-  short  revents;
-} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
-
-#endif
-
-#endif // _FIX_WINSOCK2_H
diff --git a/src/etc/mklldef.py b/src/etc/mklldef.py
deleted file mode 100644 (file)
index d2f8ee4..0000000
+++ /dev/null
@@ -1,25 +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.
-
-import sys
-
-input_file = sys.argv[1]
-output_file = sys.argv[2]
-name = sys.argv[3]
-
-with open(input_file, 'r') as f:
-    with open(output_file, 'w') as g:
-        print >> g, 'LIBRARY ' + name
-        print >> g, 'EXPORTS'
-        for x in f:
-            x = str(x)
-            if not x.startswith('    pub fn LLVM'): continue
-            name = x[11:x.find('(')]
-            print >> g, '  ' + name
index f84e30927284b0c500ed3eaf09e8e159da20ddaf..e24a1a025a1f214e40eedafe3b9c7b1d69937922 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f84e30927284b0c500ed3eaf09e8e159da20ddaf
+Subproject commit e24a1a025a1f214e40eedafe3b9c7b1d69937922
index 169634a7c82555cb1bf4d2c71f444f0897215978..424a689bcb0b9cfbb575b5a5c07d0c8c00d60be9 100644 (file)
@@ -149,15 +149,15 @@ pub struct Weak<T: ?Sized> {
     _ptr: Shared<ArcInner<T>>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
@@ -681,7 +681,7 @@ fn clone(&self) -> Weak<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "arc_weak", since = "1.4.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
index 2c45e88bb24e802d904875583ce6ddfebe7e04e7..3c4bea95ba1674f55debe08a9cd8e826fafbdcc5 100644 (file)
@@ -715,9 +715,9 @@ pub struct Weak<T: ?Sized> {
     _ptr: Shared<RcBox<T>>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> !marker::Send for Weak<T> {}
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
@@ -753,7 +753,7 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
@@ -819,7 +819,7 @@ fn clone(&self) -> Weak<T> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[stable(feature = "rc_weak", since = "1.4.0")]
 impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "(Weak)")
index ad9c770a5a5cafa037fbbe2e29a6a214b9bc342b..d9cbc4488fca75bbc3472c5e10783780d7df2ab7 100644 (file)
@@ -1692,6 +1692,13 @@ fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[stable(feature = "str_parse_error2", since = "1.8.0")]
+impl fmt::Display for ParseError {
+    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+        match *self {}
+    }
+}
+
 #[stable(feature = "str_parse_error", since = "1.5.0")]
 impl PartialEq for ParseError {
     fn eq(&self, _: &ParseError) -> bool {
index 3ac4ffb22364f3a777c5149d1729163ae7906c0c..b8bf54628ac5e0dba95a6470d16211ded96f9e8c 100644 (file)
@@ -19,7 +19,6 @@
 
 use self::Ordering::*;
 
-use mem;
 use marker::Sized;
 use option::Option::{self, Some};
 
@@ -119,10 +118,6 @@ pub enum Ordering {
 }
 
 impl Ordering {
-    unsafe fn from_i8_unchecked(v: i8) -> Ordering {
-        mem::transmute(v)
-    }
-
     /// Reverse the `Ordering`.
     ///
     /// * `Less` becomes `Greater`.
@@ -155,14 +150,10 @@ unsafe fn from_i8_unchecked(v: i8) -> Ordering {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn reverse(self) -> Ordering {
-        unsafe {
-            // this compiles really nicely (to a single instruction);
-            // an explicit match has a pile of branches and
-            // comparisons.
-            //
-            // NB. it is safe because of the explicit discriminants
-            // given above.
-            Ordering::from_i8_unchecked(-(self as i8))
+        match self {
+            Less => Greater,
+            Equal => Equal,
+            Greater => Less,
         }
     }
 }
index 8d40faf3bc6ff24b6a8a4f5b2e9eb463938656e9..eeb0c173b9b7b8238f872abdc042402b572f9a74 100644 (file)
@@ -295,7 +295,7 @@ pub fn as_mut(&mut self) -> Option<&mut T> {
     pub fn expect(self, msg: &str) -> T {
         match self {
             Some(val) => val,
-            None => panic!("{}", msg),
+            None => expect_failed(msg),
         }
     }
 
@@ -697,6 +697,14 @@ pub fn unwrap_or_default(self) -> T {
     }
 }
 
+// This is a separate function to reduce the code size of .expect() itself.
+#[inline(never)]
+#[cold]
+fn expect_failed(msg: &str) -> ! {
+    panic!("{}", msg)
+}
+
+
 /////////////////////////////////////////////////////////////////////////////
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
index 6ec76c821b30d0172c23b6b1489b7b2dd4707a4c..9bd6ed12798a5efc58703e91519ce5696e5c26f5 100644 (file)
@@ -684,8 +684,7 @@ impl<T, E: fmt::Debug> Result<T, E> {
     pub fn unwrap(self) -> T {
         match self {
             Ok(t) => t,
-            Err(e) =>
-                panic!("called `Result::unwrap()` on an `Err` value: {:?}", e)
+            Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", e),
         }
     }
 
@@ -706,7 +705,7 @@ pub fn unwrap(self) -> T {
     pub fn expect(self, msg: &str) -> T {
         match self {
             Ok(t) => t,
-            Err(e) => panic!("{}: {:?}", msg, e),
+            Err(e) => unwrap_failed(msg, e),
         }
     }
 }
@@ -734,13 +733,19 @@ impl<T: fmt::Debug, E> Result<T, E> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unwrap_err(self) -> E {
         match self {
-            Ok(t) =>
-                panic!("called `Result::unwrap_err()` on an `Ok` value: {:?}", t),
-            Err(e) => e
+            Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", t),
+            Err(e) => e,
         }
     }
 }
 
+// This is a separate function to reduce the code size of the methods
+#[inline(never)]
+#[cold]
+fn unwrap_failed<E: fmt::Debug>(msg: &str, error: E) -> ! {
+    panic!("{}: {:?}", msg, error)
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
index 6107564b4aeff7344cdda938226e8e9904ff8d5b..40041c748e7ffcd41dbb5ca4078995702ac2c3ff 100644 (file)
@@ -294,22 +294,23 @@ fn as_ptr(&self) -> *const T {
     fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize> where
         F: FnMut(&T) -> Ordering
     {
-        let mut base : usize = 0;
-        let mut lim : usize = self.len();
+        let mut base = 0usize;
+        let mut s = self;
 
-        while lim != 0 {
-            let ix = base + (lim >> 1);
-            match f(&self[ix]) {
-                Equal => return Ok(ix),
+        loop {
+            let (head, tail) = s.split_at(s.len() >> 1);
+            if tail.is_empty() {
+                return Err(base)
+            }
+            match f(&tail[0]) {
                 Less => {
-                    base = ix + 1;
-                    lim -= 1;
+                    base += head.len() + 1;
+                    s = &tail[1..];
                 }
-                Greater => ()
+                Greater => s = head,
+                Equal => return Ok(base + head.len()),
             }
-            lim >>= 1;
         }
-        Err(base)
     }
 
     #[inline]
index dd111981f0e57814064d77754150b802347d74db..3892455395f76eeb9d78532049d9929daa006688 100644 (file)
@@ -244,6 +244,34 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     Ok(unsafe { from_utf8_unchecked(v) })
 }
 
+/// Forms a str from a pointer and a length.
+///
+/// The `len` argument is the number of bytes in the string.
+///
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `len` bytes, nor whether the lifetime inferred is a suitable
+/// lifetime for the returned str.
+///
+/// The data must be valid UTF-8
+///
+/// `p` must be non-null, even for zero-length str.
+///
+/// # Caveat
+///
+/// The lifetime for the returned str is inferred from its usage. To
+/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
+/// source lifetime is safe in the context, such as by providing a helper
+/// function taking the lifetime of a host value for the str, or by explicit
+/// annotation.
+/// Performs the same functionality as `from_raw_parts`, except that a mutable
+/// str is returned.
+///
+unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
+    mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
+}
+
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
 ///
@@ -1843,10 +1871,10 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
             let len = self.len();
+            let ptr = self.as_ptr() as *mut u8;
             unsafe {
-                let self2: &mut str = mem::transmute_copy(&self);
-                (self.slice_mut_unchecked(0, mid),
-                 self2.slice_mut_unchecked(mid, len))
+                (from_raw_parts_mut(ptr, mid),
+                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
             }
         } else {
             slice_error_fail(self, 0, mid)
index d60eeb76ccd4ad10ccc8b9b6b3a69675772fb8ee..f82ab44adad00b8d762635d75e0fc1d16c9677f5 100644 (file)
 use core::result::Result::{Ok, Err};
 
 #[test]
-fn binary_search_not_found() {
+fn test_binary_search() {
     let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
-    let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
     let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
     let b = [1, 2, 4, 5, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
-    let b = [1, 2, 4, 5, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
     let b = [1, 2, 4, 5, 6, 8];
     assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
index 9aa6600bd8f4e4f370a7d2fb76c4b3efc669cadf..af77843345ec6fc7e51113bfd692138d89024bc0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9aa6600bd8f4e4f370a7d2fb76c4b3efc669cadf
+Subproject commit af77843345ec6fc7e51113bfd692138d89024bc0
index 9bf0a79115e78f4ebe8cd388ca272c209064ae1d..3bb73ecca2c43aad946075dbd1ae41c8b4f8f6c2 100644 (file)
@@ -11,7 +11,6 @@
 use self::thread::{DepGraphThreadData, DepMessage};
 use middle::def_id::DefId;
 use middle::ty;
-use middle::ty::fast_reject::SimplifiedType;
 use rustc_front::hir;
 use rustc_front::intravisit::Visitor;
 use std::rc::Rc;
@@ -102,7 +101,7 @@ pub enum DepNode {
     // which would yield an overly conservative dep-graph.
     TraitItems(DefId),
     ReprHints(DefId),
-    TraitSelect(DefId, Option<SimplifiedType>),
+    TraitSelect(DefId),
 }
 
 #[derive(Clone)]
index aa2f60f71f979765af701a1a13826d3533480432..e5942e64a9e409dab00e72c6cc4fa7ec4bd12d4a 100644 (file)
@@ -215,187 +215,6 @@ struct X { x: (), }
 ```
 "##,
 
-E0010: r##"
-The value of statics and constants must be known at compile time, and they live
-for the entire lifetime of a program. Creating a boxed value allocates memory on
-the heap at runtime, and therefore cannot be done at compile time. Erroneous
-code example:
-
-```
-#![feature(box_syntax)]
-
-const CON : Box<i32> = box 0;
-```
-"##,
-
-E0011: r##"
-Initializers for constants and statics are evaluated at compile time.
-User-defined operators rely on user-defined functions, which cannot be evaluated
-at compile time.
-
-Bad example:
-
-```
-use std::ops::Index;
-
-struct Foo { a: u8 }
-
-impl Index<u8> for Foo {
-    type Output = u8;
-
-    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
-}
-
-const a: Foo = Foo { a: 0u8 };
-const b: u8 = a[0]; // Index trait is defined by the user, bad!
-```
-
-Only operators on builtin types are allowed.
-
-Example:
-
-```
-const a: &'static [i32] = &[1, 2, 3];
-const b: i32 = a[0]; // Good!
-```
-"##,
-
-E0013: r##"
-Static and const variables can refer to other const variables. But a const
-variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
-here:
-
-```
-static X: i32 = 42;
-const Y: i32 = X;
-```
-
-To fix this, the value can be extracted as a const and then used:
-
-```
-const A: i32 = 42;
-static X: i32 = A;
-const Y: i32 = A;
-```
-"##,
-
-E0014: r##"
-Constants can only be initialized by a constant value or, in a future
-version of Rust, a call to a const function. This error indicates the use
-of a path (like a::b, or x) denoting something other than one of these
-allowed items. Example:
-
-```
-const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
-```
-
-To avoid it, you have to replace the non-constant value:
-
-```
-const FOO: i32 = { const X : i32 = 0; X };
-// or even:
-const FOO: i32 = { 0 }; // but brackets are useless here
-```
-"##,
-
-// FIXME(#24111) Change the language here when const fn stabilizes
-E0015: r##"
-The only functions that can be called in static or constant expressions are
-`const` functions, and struct/enum constructors. `const` functions are only
-available on a nightly compiler. Rust currently does not support more general
-compile-time function execution.
-
-```
-const FOO: Option<u8> = Some(1); // enum constructor
-struct Bar {x: u8}
-const BAR: Bar = Bar {x: 1}; // struct constructor
-```
-
-See [RFC 911] for more details on the design of `const fn`s.
-
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
-"##,
-
-E0017: r##"
-References in statics and constants may only refer to immutable values. Example:
-
-```
-static X: i32 = 1;
-const C: i32 = 2;
-
-// these three are not allowed:
-const CR: &'static mut i32 = &mut C;
-static STATIC_REF: &'static mut i32 = &mut X;
-static CONST_REF: &'static mut i32 = &mut C;
-```
-
-Statics are shared everywhere, and if they refer to mutable data one might
-violate memory safety since holding multiple mutable references to shared data
-is not allowed.
-
-If you really want global mutable state, try using `static mut` or a global
-`UnsafeCell`.
-"##,
-
-E0018: r##"
-The value of static and const variables must be known at compile time. You
-can't cast a pointer as an integer because we can't know what value the
-address will take.
-
-However, pointers to other constants' addresses are allowed in constants,
-example:
-
-```
-const X: u32 = 50;
-const Y: *const u32 = &X;
-```
-
-Therefore, casting one of these non-constant pointers to an integer results
-in a non-constant integer which lead to this error. Example:
-
-```
-const X: u32 = 1;
-const Y: usize = &X as *const u32 as usize;
-println!("{}", Y);
-```
-"##,
-
-E0019: r##"
-A function call isn't allowed in the const's initialization expression
-because the expression's value must be known at compile-time. Example of
-erroneous code:
-
-```
-enum Test {
-    V1
-}
-
-impl Test {
-    fn test(&self) -> i32 {
-        12
-    }
-}
-
-fn main() {
-    const FOO: Test = Test::V1;
-
-    const A: i32 = FOO.test(); // You can't call Test::func() here !
-}
-```
-
-Remember: you can't use a function call inside a const's initialization
-expression! However, you can totally use it anywhere else:
-
-```
-fn main() {
-    const FOO: Test = Test::V1;
-
-    FOO.func(); // here is good
-    let x = FOO.func(); // or even here!
-}
-```
-"##,
-
 E0020: r##"
 This error indicates that an attempt was made to divide by zero (or take the
 remainder of a zero divisor) in a static or constant expression. Erroneous
@@ -407,24 +226,6 @@ fn main() {
 ```
 "##,
 
-E0030: r##"
-When matching against a range, the compiler verifies that the range is
-non-empty.  Range patterns include both end-points, so this is equivalent to
-requiring the start of the range to be less than or equal to the end of the
-range.
-
-For example:
-
-```
-match 5u32 {
-    // This range is ok, albeit pointless.
-    1 ... 1 => ...
-    // This range is empty, and the compiler can tell.
-    1000 ... 5 => ...
-}
-```
-"##,
-
 E0038: r####"
 Trait objects like `Box<Trait>` can only be constructed when certain
 requirements are satisfied by the trait in question.
@@ -902,14 +703,6 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
 ```
 "##,
 
-E0161: r##"
-In Rust, you can only move a value when its size is known at compile time.
-
-To work around this restriction, consider "hiding" the value behind a reference:
-either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
-it around as usual.
-"##,
-
 E0162: r##"
 An if-let pattern attempts to match the pattern, and enters the body if the
 match was successful. If the match is irrefutable (when it cannot fail to
@@ -1101,67 +894,6 @@ fn foo<'a, 'b, 'a>(x: &'a str, y: &'b str) { }
 ```
 "##,
 
-E0265: r##"
-This error indicates that a static or constant references itself.
-All statics and constants need to resolve to a value in an acyclic manner.
-
-For example, neither of the following can be sensibly compiled:
-
-```
-const X: u32 = X;
-```
-
-```
-const X: u32 = Y;
-const Y: u32 = X;
-```
-"##,
-
-E0267: r##"
-This error indicates the use of a loop keyword (`break` or `continue`) inside a
-closure but outside of any loop. Erroneous code example:
-
-```
-let w = || { break; }; // error: `break` inside of a closure
-```
-
-`break` and `continue` keywords can be used as normal inside closures as long as
-they are also contained within a loop. To halt the execution of a closure you
-should instead use a return statement. Example:
-
-```
-let w = || {
-    for _ in 0..10 {
-        break;
-    }
-};
-
-w();
-```
-"##,
-
-E0268: r##"
-This error indicates the use of a loop keyword (`break` or `continue`) outside
-of a loop. Without a loop to break out of or continue in, no sensible action can
-be taken. Erroneous code example:
-
-```
-fn some_func() {
-    break; // error: `break` outside of loop
-}
-```
-
-Please verify that you are using `break` and `continue` only in loops. Example:
-
-```
-fn some_func() {
-    for _ in 0..10 {
-        break; // ok!
-    }
-}
-```
-"##,
-
 E0269: r##"
 Functions must eventually return a value of their return type. For example, in
 the following function
@@ -1892,104 +1624,6 @@ struct Foo<T: 'static> {
 ```
 "##,
 
-E0378: r##"
-Method calls that aren't calls to inherent `const` methods are disallowed
-in statics, constants, and constant functions.
-
-For example:
-
-```
-const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
-
-struct Foo(i32);
-
-impl Foo {
-    const fn foo(&self) -> i32 {
-        self.bar() // error, `bar` isn't `const`
-    }
-
-    fn bar(&self) -> i32 { self.0 }
-}
-```
-
-For more information about `const fn`'s, see [RFC 911].
-
-[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
-"##,
-
-E0394: r##"
-From [RFC 246]:
-
- > It is invalid for a static to reference another static by value. It is
- > required that all references be borrowed.
-
-[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
-"##,
-
-E0395: r##"
-The value assigned to a constant expression must be known at compile time,
-which is not the case when comparing raw pointers. Erroneous code example:
-
-```
-static foo: i32 = 42;
-static bar: i32 = 43;
-
-static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
-// error: raw pointers cannot be compared in statics!
-```
-
-Please check that the result of the comparison can be determined at compile time
-or isn't assigned to a constant expression. Example:
-
-```
-static foo: i32 = 42;
-static bar: i32 = 43;
-
-let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
-// baz isn't a constant expression so it's ok
-```
-"##,
-
-E0396: r##"
-The value assigned to a constant expression must be known at compile time,
-which is not the case when dereferencing raw pointers. Erroneous code
-example:
-
-```
-const foo: i32 = 42;
-const baz: *const i32 = (&foo as *const i32);
-
-const deref: i32 = *baz;
-// error: raw pointers cannot be dereferenced in constants
-```
-
-To fix this error, please do not assign this value to a constant expression.
-Example:
-
-```
-const foo: i32 = 42;
-const baz: *const i32 = (&foo as *const i32);
-
-unsafe { let deref: i32 = *baz; }
-// baz isn't a constant expression so it's ok
-```
-
-You'll also note that this assignment must be done in an unsafe block!
-"##,
-
-E0397: r##"
-It is not allowed for a mutable static to allocate or have destructors. For
-example:
-
-```
-// error: mutable statics are not allowed to have boxes
-static mut FOO: Option<Box<usize>> = None;
-
-// error: mutable statics are not allowed to have destructors
-static mut BAR: Option<Vec<i32>> = None;
-```
-"##,
-
 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
@@ -2026,50 +1660,6 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
 [1]: https://github.com/rust-lang/rfcs/pull/1156
 "##,
 
-E0400: r##"
-A user-defined dereference was attempted in an invalid context. Erroneous
-code example:
-
-```
-use std::ops::Deref;
-
-struct A;
-
-impl Deref for A {
-    type Target = str;
-
-    fn deref(&self)-> &str { "foo" }
-}
-
-const S: &'static str = &A;
-// error: user-defined dereference operators are not allowed in constants
-
-fn main() {
-    let foo = S;
-}
-```
-
-You cannot directly use a dereference operation whilst initializing a constant
-or a static. To fix this error, restructure your code to avoid this dereference,
-perhaps moving it inline:
-
-```
-use std::ops::Deref;
-
-struct A;
-
-impl Deref for A {
-    type Target = str;
-
-    fn deref(&self)-> &str { "foo" }
-}
-
-fn main() {
-    let foo : &str = &A;
-}
-```
-"##,
-
 E0452: r##"
 An invalid lint attribute has been given. Erroneous code example:
 
@@ -2087,136 +1677,6 @@ fn main() {
 ```
 "##,
 
-E0492: r##"
-A borrow of a constant containing interior mutability was attempted. Erroneous
-code example:
-
-```
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
-
-const A: AtomicUsize = ATOMIC_USIZE_INIT;
-static B: &'static AtomicUsize = &A;
-// error: cannot borrow a constant which contains interior mutability, create a
-//        static instead
-```
-
-A `const` represents a constant value that should never change. If one takes
-a `&` reference to the constant, then one is taking a pointer to some memory
-location containing the value. Normally this is perfectly fine: most values
-can't be changed via a shared `&` pointer, but interior mutability would allow
-it. That is, a constant value could be mutated. On the other hand, a `static` is
-explicitly a single memory location, which can be mutated at will.
-
-So, in order to solve this error, either use statics which are `Sync`:
-
-```
-use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
-
-static A: AtomicUsize = ATOMIC_USIZE_INIT;
-static B: &'static AtomicUsize = &A; // ok!
-```
-
-You can also have this error while using a cell type:
-
-```
-#![feature(const_fn)]
-
-use std::cell::Cell;
-
-const A: Cell<usize> = Cell::new(1);
-const B: &'static Cell<usize> = &A;
-// error: cannot borrow a constant which contains interior mutability, create
-//        a static instead
-
-// or:
-struct C { a: Cell<usize> }
-
-const D: C = C { a: Cell::new(1) };
-const E: &'static Cell<usize> = &D.a; // error
-
-// or:
-const F: &'static C = &D; // error
-```
-
-This is because cell types do operations that are not thread-safe. Due to this,
-they don't implement Sync and thus can't be placed in statics. In this
-case, `StaticMutex` would work just fine, but it isn't stable yet:
-https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
-
-However, if you still wish to use these types, you can achieve this by an unsafe
-wrapper:
-
-```
-#![feature(const_fn)]
-
-use std::cell::Cell;
-use std::marker::Sync;
-
-struct NotThreadSafe<T> {
-    value: Cell<T>,
-}
-
-unsafe impl<T> Sync for NotThreadSafe<T> {}
-
-static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
-static B: &'static NotThreadSafe<usize> = &A; // ok!
-```
-
-Remember this solution is unsafe! You will have to ensure that accesses to the
-cell are synchronized.
-"##,
-
-E0493: r##"
-A type with a destructor was assigned to an invalid type of variable. Erroneous
-code example:
-
-```
-struct Foo {
-    a: u32
-}
-
-impl Drop for Foo {
-    fn drop(&mut self) {}
-}
-
-const F : Foo = Foo { a : 0 };
-// error: constants are not allowed to have destructors
-static S : Foo = Foo { a : 0 };
-// error: statics are not allowed to have destructors
-```
-
-To solve this issue, please use a type which does allow the usage of type with
-destructors.
-"##,
-
-E0494: r##"
-A reference of an interior static was assigned to another const/static.
-Erroneous code example:
-
-```
-struct Foo {
-    a: u32
-}
-
-static S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a;
-// error: cannot refer to the interior of another static, use a
-//        constant instead
-```
-
-The "base" variable has to be a const if you want another static/const variable
-to refer to one of its fields. Example:
-
-```
-struct Foo {
-    a: u32
-}
-
-const S : Foo = Foo { a : 0 };
-static A : &'static u32 = &S.a; // ok!
-```
-"##,
-
 E0496: r##"
 A lifetime name is shadowing another lifetime name. Erroneous code example:
 
index 501a03f128664ad3ebd0e9bb81700ebb29ed0975..4d772de7835941b1c65cd1564908624739f1db19 100644 (file)
@@ -94,12 +94,9 @@ pub mod middle {
     pub mod astconv_util;
     pub mod expr_use_visitor; // STAGE0: increase glitch immunity
     pub mod cfg;
-    pub mod check_const;
-    pub mod check_static_recursion;
-    pub mod check_loop;
     pub mod check_match;
-    pub mod check_rvalues;
     pub mod const_eval;
+    pub mod const_qualif;
     pub mod cstore;
     pub mod dataflow;
     pub mod dead;
index 2bf749d93cec471c63cdc31b47dc39f4f74cc950..8b1bdc31beb01bf916aed85ab623a9907edd9cc5 100644 (file)
@@ -14,7 +14,7 @@
  * Almost certainly this could (and should) be refactored out of existence.
  */
 
-use middle::def;
+use middle::def::Def;
 use middle::ty::{self, Ty};
 
 use syntax::codemap::Span;
@@ -72,7 +72,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
             }
             Some(d) => d.full_def()
         };
-        if let def::DefPrimTy(nty) = def {
+        if let Def::PrimTy(nty) = def {
             Some(prim_ty_to_ty(tcx, &path.segments, nty))
         } else {
             None
index abe85125215708f38abd8038f0295e6efb8df76b..a6bcf70925ca3eed134366574d61435b12e5d8de 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc_data_structures::graph;
 use middle::cfg::*;
-use middle::def;
+use middle::def::Def;
 use middle::pat_util;
 use middle::ty;
 use syntax::ast;
@@ -591,7 +591,7 @@ fn find_scope(&self,
         }
 
         match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
-            Some(def::DefLabel(loop_id)) => {
+            Some(Def::Label(loop_id)) => {
                 for l in &self.loop_scopes {
                     if l.loop_id == loop_id {
                         return *l;
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
deleted file mode 100644 (file)
index 5822b3d..0000000
+++ /dev/null
@@ -1,949 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Verifies that the types and values of const and static items
-// are safe. The rules enforced by this module are:
-//
-// - For each *mutable* static item, it checks that its **type**:
-//     - doesn't have a destructor
-//     - doesn't own a box
-//
-// - For each *immutable* static item, it checks that its **value**:
-//       - doesn't own a box
-//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
-//           - the type of the struct/enum has a dtor
-//
-// Rules Enforced Elsewhere:
-// - It's not possible to take the address of a static item with unsafe interior. This is enforced
-// by borrowck::gather_loans
-
-use dep_graph::DepNode;
-use middle::ty::cast::{CastKind};
-use middle::const_eval::{self, ConstEvalErr};
-use middle::const_eval::ErrKind::IndexOpFeatureGated;
-use middle::const_eval::EvalHint::ExprTypeChecked;
-use middle::def;
-use middle::def_id::DefId;
-use middle::expr_use_visitor as euv;
-use middle::infer;
-use middle::mem_categorization as mc;
-use middle::mem_categorization::Categorization;
-use middle::traits;
-use middle::ty::{self, Ty};
-use util::nodemap::NodeMap;
-
-use rustc_front::hir;
-use syntax::ast;
-use syntax::codemap::Span;
-use syntax::feature_gate::UnstableFeatures;
-use rustc_front::intravisit::{self, FnKind, Visitor};
-
-use std::collections::hash_map::Entry;
-use std::cmp::Ordering;
-
-// Const qualification, from partial to completely promotable.
-bitflags! {
-    #[derive(RustcEncodable, RustcDecodable)]
-    flags ConstQualif: u8 {
-        // Inner mutability (can not be placed behind a reference) or behind
-        // &mut in a non-global expression. Can be copied from static memory.
-        const MUTABLE_MEM        = 1 << 0,
-        // Constant value with a type that implements Drop. Can be copied
-        // from static memory, similar to MUTABLE_MEM.
-        const NEEDS_DROP         = 1 << 1,
-        // Even if the value can be placed in static memory, copying it from
-        // there is more expensive than in-place instantiation, and/or it may
-        // be too large. This applies to [T; N] and everything containing it.
-        // N.B.: references need to clear this flag to not end up on the stack.
-        const PREFER_IN_PLACE    = 1 << 2,
-        // May use more than 0 bytes of memory, doesn't impact the constness
-        // directly, but is not allowed to be borrowed mutably in a constant.
-        const NON_ZERO_SIZED     = 1 << 3,
-        // Actually borrowed, has to always be in static memory. Does not
-        // propagate, and requires the expression to behave like a 'static
-        // lvalue. The set of expressions with this flag is the minimum
-        // that have to be promoted.
-        const HAS_STATIC_BORROWS = 1 << 4,
-        // Invalid const for miscellaneous reasons (e.g. not implemented).
-        const NOT_CONST          = 1 << 5,
-
-        // Borrowing the expression won't produce &'static T if any of these
-        // bits are set, though the value could be copied from static memory
-        // if `NOT_CONST` isn't set.
-        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
-                                   ConstQualif::NEEDS_DROP.bits |
-                                   ConstQualif::NOT_CONST.bits
-    }
-}
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-enum Mode {
-    Const,
-    ConstFn,
-    Static,
-    StaticMut,
-
-    // An expression that occurs outside of any constant context
-    // (i.e. `const`, `static`, array lengths, etc.). The value
-    // can be variable at runtime, but will be promotable to
-    // static memory if we can prove it is actually constant.
-    Var,
-}
-
-struct CheckCrateVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    mode: Mode,
-    qualif: ConstQualif,
-    rvalue_borrows: NodeMap<hir::Mutability>
-}
-
-impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
-    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
-        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R,
-    {
-        let (old_mode, old_qualif) = (self.mode, self.qualif);
-        self.mode = mode;
-        self.qualif = ConstQualif::empty();
-        let r = f(self);
-        self.mode = old_mode;
-        self.qualif = old_qualif;
-        r
-    }
-
-    fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
-        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
-    {
-        let param_env = match item_id {
-            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
-            None => self.tcx.empty_parameter_environment()
-        };
-
-        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
-
-        f(&mut euv::ExprUseVisitor::new(self, &infcx))
-    }
-
-    fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
-        assert!(mode != Mode::Var);
-        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
-        self.with_mode(mode, |this| {
-            this.with_euv(None, |euv| euv.consume_expr(expr));
-            this.visit_expr(expr);
-            this.qualif
-        })
-    }
-
-    fn fn_like(&mut self,
-               fk: FnKind,
-               fd: &hir::FnDecl,
-               b: &hir::Block,
-               s: Span,
-               fn_id: ast::NodeId)
-               -> ConstQualif {
-        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
-            Entry::Occupied(entry) => return *entry.get(),
-            Entry::Vacant(entry) => {
-                // Prevent infinite recursion on re-entry.
-                entry.insert(ConstQualif::empty());
-            }
-        }
-
-        let mode = match fk {
-            FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
-                Mode::ConstFn
-            }
-            FnKind::Method(_, m, _) => {
-                if m.constness == hir::Constness::Const {
-                    Mode::ConstFn
-                } else {
-                    Mode::Var
-                }
-            }
-            _ => Mode::Var
-        };
-
-        let qualif = self.with_mode(mode, |this| {
-            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
-            intravisit::walk_fn(this, fk, fd, b, s);
-            this.qualif
-        });
-
-        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
-        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
-        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-
-        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
-        qualif
-    }
-
-    fn add_qualif(&mut self, qualif: ConstQualif) {
-        self.qualif = self.qualif | qualif;
-    }
-
-    /// Returns true if the call is to a const fn or method.
-    fn handle_const_fn_call(&mut self,
-                            expr: &hir::Expr,
-                            def_id: DefId,
-                            ret_ty: Ty<'tcx>)
-                            -> bool {
-        if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
-            if
-                // we are in a static/const initializer
-                self.mode != Mode::Var &&
-
-                // feature-gate is not enabled
-                !self.tcx.sess.features.borrow().const_fn &&
-
-                // this doesn't come from a macro that has #[allow_internal_unstable]
-                !self.tcx.sess.codemap().span_allows_unstable(expr.span)
-            {
-                let mut err = self.tcx.sess.struct_span_err(
-                    expr.span,
-                    "const fns are an unstable feature");
-                fileline_help!(
-                    &mut err,
-                    expr.span,
-                    "in Nightly builds, add `#![feature(const_fn)]` to the crate \
-                     attributes to enable");
-                err.emit();
-            }
-
-            let qualif = self.fn_like(fn_like.kind(),
-                                      fn_like.decl(),
-                                      fn_like.body(),
-                                      fn_like.span(),
-                                      fn_like.id());
-            self.add_qualif(qualif);
-
-            if ret_ty.type_contents(self.tcx).interior_unsafe() {
-                self.add_qualif(ConstQualif::MUTABLE_MEM);
-            }
-
-            true
-        } else {
-            false
-        }
-    }
-
-    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
-        match self.rvalue_borrows.entry(id) {
-            Entry::Occupied(mut entry) => {
-                // Merge the two borrows, taking the most demanding
-                // one, mutability-wise.
-                if mutbl == hir::MutMutable {
-                    entry.insert(mutbl);
-                }
-            }
-            Entry::Vacant(entry) => {
-                entry.insert(mutbl);
-            }
-        }
-    }
-
-    fn msg(&self) -> &'static str {
-        match self.mode {
-            Mode::Const => "constant",
-            Mode::ConstFn => "constant function",
-            Mode::StaticMut | Mode::Static => "static",
-            Mode::Var => unreachable!(),
-        }
-    }
-
-    fn check_static_mut_type(&self, e: &hir::Expr) {
-        let node_ty = self.tcx.node_id_to_type(e.id);
-        let tcontents = node_ty.type_contents(self.tcx);
-
-        let suffix = if tcontents.has_dtor() {
-            "destructors"
-        } else if tcontents.owns_owned() {
-            "boxes"
-        } else {
-            return
-        };
-
-        span_err!(self.tcx.sess, e.span, E0397,
-                 "mutable statics are not allowed to have {}", suffix);
-    }
-
-    fn check_static_type(&self, e: &hir::Expr) {
-        let ty = self.tcx.node_id_to_type(e.id);
-        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
-        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
-        let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
-        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
-        match fulfill_cx.select_all_or_error(&infcx) {
-            Ok(()) => { },
-            Err(ref errors) => {
-                traits::report_fulfillment_errors(&infcx, errors);
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &hir::Item) {
-        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
-        assert_eq!(self.mode, Mode::Var);
-        match i.node {
-            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
-                self.check_static_type(&**expr);
-                self.global_expr(Mode::Static, &**expr);
-            }
-            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
-                self.check_static_mut_type(&**expr);
-                self.global_expr(Mode::StaticMut, &**expr);
-            }
-            hir::ItemConst(_, ref expr) => {
-                self.global_expr(Mode::Const, &**expr);
-            }
-            hir::ItemEnum(ref enum_definition, _) => {
-                for var in &enum_definition.variants {
-                    if let Some(ref ex) = var.node.disr_expr {
-                        self.global_expr(Mode::Const, &**ex);
-                    }
-                }
-            }
-            _ => {
-                intravisit::walk_item(self, i);
-            }
-        }
-    }
-
-    fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
-        match t.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(ref expr) = *default {
-                    self.global_expr(Mode::Const, &*expr);
-                } else {
-                    intravisit::walk_trait_item(self, t);
-                }
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
-        }
-    }
-
-    fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
-        match i.node {
-            hir::ImplItemKind::Const(_, ref expr) => {
-                self.global_expr(Mode::Const, &*expr);
-            }
-            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
-        }
-    }
-
-    fn visit_fn(&mut self,
-                fk: FnKind<'v>,
-                fd: &'v hir::FnDecl,
-                b: &'v hir::Block,
-                s: Span,
-                fn_id: ast::NodeId) {
-        self.fn_like(fk, fd, b, s, fn_id);
-    }
-
-    fn visit_pat(&mut self, p: &hir::Pat) {
-        match p.node {
-            hir::PatLit(ref lit) => {
-                self.global_expr(Mode::Const, &**lit);
-            }
-            hir::PatRange(ref start, ref end) => {
-                self.global_expr(Mode::Const, &**start);
-                self.global_expr(Mode::Const, &**end);
-
-                match const_eval::compare_lit_exprs(self.tcx, start, end) {
-                    Some(Ordering::Less) |
-                    Some(Ordering::Equal) => {}
-                    Some(Ordering::Greater) => {
-                        span_err!(self.tcx.sess, start.span, E0030,
-                            "lower range bound must be less than or equal to upper");
-                    }
-                    None => {
-                        self.tcx.sess.delay_span_bug(start.span,
-                                                     "non-constant path in constant expr");
-                    }
-                }
-            }
-            _ => intravisit::walk_pat(self, p)
-        }
-    }
-
-    fn visit_block(&mut self, block: &hir::Block) {
-        // Check all statements in the block
-        for stmt in &block.stmts {
-            match stmt.node {
-                hir::StmtDecl(ref decl, _) => {
-                    match decl.node {
-                        hir::DeclLocal(_) => {},
-                        // Item statements are allowed
-                        hir::DeclItem(_) => continue
-                    }
-                }
-                hir::StmtExpr(_, _) => {},
-                hir::StmtSemi(_, _) => {},
-            }
-            self.add_qualif(ConstQualif::NOT_CONST);
-            // anything else should have been caught by check_const_fn
-            assert_eq!(self.mode, Mode::Var);
-        }
-        intravisit::walk_block(self, block);
-    }
-
-    fn visit_expr(&mut self, ex: &hir::Expr) {
-        let mut outer = self.qualif;
-        self.qualif = ConstQualif::empty();
-
-        let node_ty = self.tcx.node_id_to_type(ex.id);
-        check_expr(self, ex, node_ty);
-        check_adjustments(self, ex);
-
-        // Special-case some expressions to avoid certain flags bubbling up.
-        match ex.node {
-            hir::ExprCall(ref callee, ref args) => {
-                for arg in args {
-                    self.visit_expr(&**arg)
-                }
-
-                let inner = self.qualif;
-                self.visit_expr(&**callee);
-                // The callee's size doesn't count in the call.
-                let added = self.qualif - inner;
-                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
-            }
-            hir::ExprRepeat(ref element, _) => {
-                self.visit_expr(&**element);
-                // The count is checked elsewhere (typeck).
-                let count = match node_ty.sty {
-                    ty::TyArray(_, n) => n,
-                    _ => unreachable!()
-                };
-                // [element; 0] is always zero-sized.
-                if count == 0 {
-                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
-                }
-            }
-            hir::ExprMatch(ref discr, ref arms, _) => {
-                // Compute the most demanding borrow from all the arms'
-                // patterns and set that on the discriminator.
-                let mut borrow = None;
-                for pat in arms.iter().flat_map(|arm| &arm.pats) {
-                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
-                    match (borrow, pat_borrow) {
-                        (None, _) | (_, Some(hir::MutMutable)) => {
-                            borrow = pat_borrow;
-                        }
-                        _ => {}
-                    }
-                }
-                if let Some(mutbl) = borrow {
-                    self.record_borrow(discr.id, mutbl);
-                }
-                intravisit::walk_expr(self, ex);
-            }
-            // Division by zero and overflow checking.
-            hir::ExprBinary(op, _, _) => {
-                intravisit::walk_expr(self, ex);
-                let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
-                match node_ty.sty {
-                    ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
-                        if !self.qualif.intersects(ConstQualif::NOT_CONST) {
-                            match const_eval::eval_const_expr_partial(
-                                    self.tcx, ex, ExprTypeChecked, None) {
-                                Ok(_) => {}
-                                Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
-                                Err(msg) => {
-                                    self.tcx.sess.add_lint(::lint::builtin::CONST_ERR, ex.id,
-                                                           msg.span,
-                                                           msg.description().into_owned())
-                                }
-                            }
-                        }
-                    }
-                    _ => {}
-                }
-            }
-            _ => intravisit::walk_expr(self, ex)
-        }
-
-        // Handle borrows on (or inside the autorefs of) this expression.
-        match self.rvalue_borrows.remove(&ex.id) {
-            Some(hir::MutImmutable) => {
-                // Constants cannot be borrowed if they contain interior mutability as
-                // it means that our "silent insertion of statics" could change
-                // initializer values (very bad).
-                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
-                // propagated from another error, so erroring again would be just noise.
-                let tc = node_ty.type_contents(self.tcx);
-                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
-                    outer = outer | ConstQualif::NOT_CONST;
-                    if self.mode != Mode::Var {
-                        span_err!(self.tcx.sess, ex.span, E0492,
-                                  "cannot borrow a constant which contains \
-                                   interior mutability, create a static instead");
-                    }
-                }
-                // If the reference has to be 'static, avoid in-place initialization
-                // as that will end up pointing to the stack instead.
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            Some(hir::MutMutable) => {
-                // `&mut expr` means expr could be mutated, unless it's zero-sized.
-                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
-                    if self.mode == Mode::Var {
-                        outer = outer | ConstQualif::NOT_CONST;
-                        self.add_qualif(ConstQualif::MUTABLE_MEM);
-                    } else {
-                        span_err!(self.tcx.sess, ex.span, E0017,
-                            "references in {}s may only refer \
-                             to immutable values", self.msg())
-                    }
-                }
-                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
-                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
-                }
-            }
-            None => {}
-        }
-        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
-        // Don't propagate certain flags.
-        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
-    }
-}
-
-/// This function is used to enforce the constraints on
-/// const/static items. It walks through the *value*
-/// of the item walking down the expression and evaluating
-/// every nested expression. If the expression is not part
-/// of a const/static item, it is qualified for promotion
-/// instead of producing errors.
-fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
-                        e: &hir::Expr, node_ty: Ty<'tcx>) {
-    match node_ty.sty {
-        ty::TyStruct(def, _) |
-        ty::TyEnum(def, _) if def.has_dtor() => {
-            v.add_qualif(ConstQualif::NEEDS_DROP);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0493,
-                          "{}s are not allowed to have destructors",
-                          v.msg());
-            }
-        }
-        _ => {}
-    }
-
-    let method_call = ty::MethodCall::expr(e.id);
-    match e.node {
-        hir::ExprUnary(..) |
-        hir::ExprBinary(..) |
-        hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0011,
-                            "user-defined operators are not allowed in {}s", v.msg());
-            }
-        }
-        hir::ExprBox(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0010,
-                          "allocations are not allowed in {}s", v.msg());
-            }
-        }
-        hir::ExprUnary(op, ref inner) => {
-            match v.tcx.node_id_to_type(inner.id).sty {
-                ty::TyRawPtr(_) => {
-                    assert!(op == hir::UnDeref);
-
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0396,
-                                  "raw pointers cannot be dereferenced in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprBinary(op, ref lhs, _) => {
-            match v.tcx.node_id_to_type(lhs.id).sty {
-                ty::TyRawPtr(_) => {
-                    assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
-                            op.node == hir::BiLe || op.node == hir::BiLt ||
-                            op.node == hir::BiGe || op.node == hir::BiGt);
-
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0395,
-                                  "raw pointers cannot be compared in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprCast(ref from, _) => {
-            debug!("Checking const cast(id={})", from.id);
-            match v.tcx.cast_kinds.borrow().get(&from.id) {
-                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
-                Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        span_err!(v.tcx.sess, e.span, E0018,
-                                  "raw pointers cannot be cast to integers in {}s", v.msg());
-                    }
-                }
-                _ => {}
-            }
-        }
-        hir::ExprPath(..) => {
-            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
-            match def {
-                Some(def::DefVariant(_, _, _)) => {
-                    // Count the discriminator or function pointer.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
-                Some(def::DefStruct(_)) => {
-                    if let ty::TyBareFn(..) = node_ty.sty {
-                        // Count the function pointer.
-                        v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    }
-                }
-                Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
-                    // Count the function pointer.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                }
-                Some(def::DefStatic(..)) => {
-                    match v.mode {
-                        Mode::Static | Mode::StaticMut => {}
-                        Mode::Const | Mode::ConstFn => {
-                            span_err!(v.tcx.sess, e.span, E0013,
-                                "{}s cannot refer to other statics, insert \
-                                 an intermediate constant instead", v.msg());
-                        }
-                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
-                    }
-                }
-                Some(def::DefConst(did)) |
-                Some(def::DefAssociatedConst(did)) => {
-                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
-                                                                       Some(e.id),
-                                                                       None) {
-                        let inner = v.global_expr(Mode::Const, expr);
-                        v.add_qualif(inner);
-                    }
-                }
-                Some(def::DefLocal(..)) if v.mode == Mode::ConstFn => {
-                    // Sadly, we can't determine whether the types are zero-sized.
-                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
-                }
-                def => {
-                    v.add_qualif(ConstQualif::NOT_CONST);
-                    if v.mode != Mode::Var {
-                        debug!("(checking const) found bad def: {:?}", def);
-                        span_err!(v.tcx.sess, e.span, E0014,
-                                  "paths in {}s may only refer to constants \
-                                   or functions", v.msg());
-                    }
-                }
-            }
-        }
-        hir::ExprCall(ref callee, _) => {
-            let mut callee = &**callee;
-            loop {
-                callee = match callee.node {
-                    hir::ExprBlock(ref block) => match block.expr {
-                        Some(ref tail) => &**tail,
-                        None => break
-                    },
-                    _ => break
-                };
-            }
-            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
-            let is_const = match def {
-                Some(def::DefStruct(..)) => true,
-                Some(def::DefVariant(..)) => {
-                    // Count the discriminator.
-                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-                    true
-                }
-                Some(def::DefFn(did, _)) => {
-                    v.handle_const_fn_call(e, did, node_ty)
-                }
-                Some(def::DefMethod(did)) => {
-                    match v.tcx.impl_or_trait_item(did).container() {
-                        ty::ImplContainer(_) => {
-                            v.handle_const_fn_call(e, did, node_ty)
-                        }
-                        ty::TraitContainer(_) => false
-                    }
-                }
-                _ => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    // FIXME(#24111) Remove this check when const fn stabilizes
-                    let (msg, note) =
-                        if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
-                        (format!("function calls in {}s are limited to \
-                                  struct and enum constructors",
-                                 v.msg()),
-                         Some("a limited form of compile-time function \
-                               evaluation is available on a nightly \
-                               compiler via `const fn`"))
-                    } else {
-                        (format!("function calls in {}s are limited \
-                                  to constant functions, \
-                                  struct and enum constructors",
-                                 v.msg()),
-                         None)
-                    };
-                    let mut err = struct_span_err!(v.tcx.sess, e.span, E0015, "{}", msg);
-                    if let Some(note) = note {
-                        err.span_note(e.span, note);
-                    }
-                    err.emit();
-                }
-            }
-        }
-        hir::ExprMethodCall(..) => {
-            let method = v.tcx.tables.borrow().method_map[&method_call];
-            let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
-                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
-                ty::TraitContainer(_) => false
-            };
-            if !is_const {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0378,
-                              "method calls in {}s are limited to \
-                               constant inherent methods", v.msg());
-                }
-            }
-        }
-        hir::ExprStruct(..) => {
-            let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
-            if did == v.tcx.lang_items.unsafe_cell_type() {
-                v.add_qualif(ConstQualif::MUTABLE_MEM);
-            }
-        }
-
-        hir::ExprLit(_) |
-        hir::ExprAddrOf(..) => {
-            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
-        }
-
-        hir::ExprRepeat(..) => {
-            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
-        }
-
-        hir::ExprClosure(..) => {
-            // Paths in constant contexts cannot refer to local variables,
-            // as there are none, and thus closures can't have upvars there.
-            if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
-                assert!(v.mode == Mode::Var,
-                        "global closures can't capture anything");
-                v.add_qualif(ConstQualif::NOT_CONST);
-            }
-        }
-
-        hir::ExprBlock(_) |
-        hir::ExprIndex(..) |
-        hir::ExprField(..) |
-        hir::ExprTupField(..) |
-        hir::ExprVec(_) |
-        hir::ExprType(..) |
-        hir::ExprTup(..) => {}
-
-        // Conditional control flow (possible to implement).
-        hir::ExprMatch(..) |
-        hir::ExprIf(..) |
-
-        // Loops (not very meaningful in constants).
-        hir::ExprWhile(..) |
-        hir::ExprLoop(..) |
-
-        // More control flow (also not very meaningful).
-        hir::ExprBreak(_) |
-        hir::ExprAgain(_) |
-        hir::ExprRet(_) |
-
-        // Miscellaneous expressions that could be implemented.
-        hir::ExprRange(..) |
-
-        // Expressions with side-effects.
-        hir::ExprAssign(..) |
-        hir::ExprAssignOp(..) |
-        hir::ExprInlineAsm(_) => {
-            v.add_qualif(ConstQualif::NOT_CONST);
-            if v.mode != Mode::Var {
-                span_err!(v.tcx.sess, e.span, E0019,
-                          "{} contains unimplemented expression type", v.msg());
-            }
-        }
-    }
-}
-
-/// Check the adjustments of an expression
-fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
-    match v.tcx.tables.borrow().adjustments.get(&e.id) {
-        None |
-        Some(&ty::adjustment::AdjustReifyFnPointer) |
-        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
-
-        Some(&ty::adjustment::AdjustDerefRef(
-            ty::adjustment::AutoDerefRef { autoderefs, .. }
-        )) => {
-            if (0..autoderefs as u32).any(|autoderef| {
-                    v.tcx.is_overloaded_autoderef(e.id, autoderef)
-            }) {
-                v.add_qualif(ConstQualif::NOT_CONST);
-                if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0400,
-                              "user-defined dereference operators are not allowed in {}s",
-                              v.msg());
-                }
-            }
-        }
-    }
-}
-
-pub fn check_crate(tcx: &ty::ctxt) {
-    tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
-        tcx: tcx,
-        mode: Mode::Var,
-        qualif: ConstQualif::NOT_CONST,
-        rvalue_borrows: NodeMap()
-    });
-    tcx.sess.abort_if_errors();
-}
-
-impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
-    fn consume(&mut self,
-               _consume_id: ast::NodeId,
-               consume_span: Span,
-               cmt: mc::cmt,
-               _mode: euv::ConsumeMode) {
-        let mut cur = &cmt;
-        loop {
-            match cur.cat {
-                Categorization::StaticItem => {
-                    if self.mode != Mode::Var {
-                        // statics cannot be consumed by value at any time, that would imply
-                        // that they're an initializer (what a const is for) or kept in sync
-                        // over time (not feasible), so deny it outright.
-                        span_err!(self.tcx.sess, consume_span, E0394,
-                                  "cannot refer to other statics by value, use the \
-                                   address-of operator or a constant instead");
-                    }
-                    break;
-                }
-                Categorization::Deref(ref cmt, _, _) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => cur = cmt,
-
-                Categorization::Rvalue(..) |
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break
-            }
-        }
-    }
-    fn borrow(&mut self,
-              borrow_id: ast::NodeId,
-              borrow_span: Span,
-              cmt: mc::cmt<'tcx>,
-              _loan_region: ty::Region,
-              bk: ty::BorrowKind,
-              loan_cause: euv::LoanCause)
-    {
-        // Kind of hacky, but we allow Unsafe coercions in constants.
-        // These occur when we convert a &T or *T to a *U, as well as
-        // when making a thin pointer (e.g., `*T`) into a fat pointer
-        // (e.g., `*Trait`).
-        match loan_cause {
-            euv::LoanCause::AutoUnsafe => {
-                return;
-            }
-            _ => { }
-        }
-
-        let mut cur = &cmt;
-        let mut is_interior = false;
-        loop {
-            match cur.cat {
-                Categorization::Rvalue(..) => {
-                    if loan_cause == euv::MatchDiscriminant {
-                        // Ignore the dummy immutable borrow created by EUV.
-                        break;
-                    }
-                    let mutbl = bk.to_mutbl_lossy();
-                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
-                        // Mutable slices are the only `&mut` allowed in
-                        // globals, but only in `static mut`, nowhere else.
-                        // FIXME: This exception is really weird... there isn't
-                        // any fundamental reason to restrict this based on
-                        // type of the expression.  `&mut [1]` has exactly the
-                        // same representation as &mut 1.
-                        match cmt.ty.sty {
-                            ty::TyArray(_, _) | ty::TySlice(_) => break,
-                            _ => {}
-                        }
-                    }
-                    self.record_borrow(borrow_id, mutbl);
-                    break;
-                }
-                Categorization::StaticItem => {
-                    if is_interior && self.mode != Mode::Var {
-                        // Borrowed statics can specifically *only* have their address taken,
-                        // not any number of other borrows such as borrowing fields, reading
-                        // elements of an array, etc.
-                        span_err!(self.tcx.sess, borrow_span, E0494,
-                                  "cannot refer to the interior of another \
-                                   static, use a constant instead");
-                    }
-                    break;
-                }
-                Categorization::Deref(ref cmt, _, _) |
-                Categorization::Downcast(ref cmt, _) |
-                Categorization::Interior(ref cmt, _) => {
-                    is_interior = true;
-                    cur = cmt;
-                }
-
-                Categorization::Upvar(..) |
-                Categorization::Local(..) => break
-            }
-        }
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {}
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {}
-
-    fn matched_pat(&mut self,
-                   _: &hir::Pat,
-                   _: mc::cmt,
-                   _: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {}
-}
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
deleted file mode 100644 (file)
index 22e9df6..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-use self::Context::*;
-
-use session::Session;
-
-use syntax::codemap::Span;
-use rustc_front::intravisit::{self, Visitor};
-use rustc_front::hir;
-
-#[derive(Clone, Copy, PartialEq)]
-enum Context {
-    Normal, Loop, Closure
-}
-
-#[derive(Copy, Clone)]
-struct CheckLoopVisitor<'a> {
-    sess: &'a Session,
-    cx: Context
-}
-
-pub fn check_crate(sess: &Session, krate: &hir::Crate) {
-    krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
-}
-
-impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
-    fn visit_item(&mut self, i: &hir::Item) {
-        self.with_context(Normal, |v| intravisit::walk_item(v, i));
-    }
-
-    fn visit_expr(&mut self, e: &hir::Expr) {
-        match e.node {
-            hir::ExprWhile(ref e, ref b, _) => {
-                self.visit_expr(&**e);
-                self.with_context(Loop, |v| v.visit_block(&**b));
-            }
-            hir::ExprLoop(ref b, _) => {
-                self.with_context(Loop, |v| v.visit_block(&**b));
-            }
-            hir::ExprClosure(_, _, ref b) => {
-                self.with_context(Closure, |v| v.visit_block(&**b));
-            }
-            hir::ExprBreak(_) => self.require_loop("break", e.span),
-            hir::ExprAgain(_) => self.require_loop("continue", e.span),
-            _ => intravisit::walk_expr(self, e)
-        }
-    }
-}
-
-impl<'a> CheckLoopVisitor<'a> {
-    fn with_context<F>(&mut self, cx: Context, f: F) where
-        F: FnOnce(&mut CheckLoopVisitor<'a>),
-    {
-        let old_cx = self.cx;
-        self.cx = cx;
-        f(self);
-        self.cx = old_cx;
-    }
-
-    fn require_loop(&self, name: &str, span: Span) {
-        match self.cx {
-            Loop => {}
-            Closure => {
-                span_err!(self.sess, span, E0267,
-                                   "`{}` inside of a closure", name);
-            }
-            Normal => {
-                span_err!(self.sess, span, E0268,
-                                   "`{}` outside of loop", name);
-            }
-        }
-    }
-}
index 8e5c5788201cccb8e45e9928050d7dc4be9d4c29..d52089dbeab5680b1a57567eac5150d9b3e5dd95 100644 (file)
@@ -246,7 +246,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-                    if let Some(DefLocal(..)) = def {
+                    if let Some(Def::Local(..)) = def {
                         if edef.variants.iter().any(|variant|
                             variant.name == ident.node.unhygienic_name
                                 && variant.kind() == VariantKind::Unit
@@ -454,8 +454,8 @@ fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
             hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
-                    Some(DefAssociatedConst(did)) |
-                    Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did,
+                    Some(Def::AssociatedConst(did)) |
+                    Some(Def::Const(did)) => match lookup_const_by_id(self.tcx, did,
                                                                     Some(pat.id), None) {
                         Some(const_expr) => {
                             const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
@@ -757,19 +757,19 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     match pat.node {
         hir::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefStruct(_)) => vec!(Single),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Struct(..)) => vec!(Single),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!()
             },
         hir::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatQPath(..) =>
@@ -777,10 +777,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                                             been rewritten"),
         hir::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(Def::Variant(_, id)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         hir::PatLit(ref expr) =>
@@ -869,10 +869,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
+                Some(Def::Variant(_, id)) => if *constructor == Variant(id) {
                     Some(vec!())
                 } else {
                     None
@@ -884,11 +884,11 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         hir::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
-                DefConst(..) | DefAssociatedConst(..) =>
+                Def::Const(..) | Def::AssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                DefVariant(_, id, _) if *constructor != Variant(id) => None,
-                DefVariant(..) | DefStruct(..) => {
+                Def::Variant(_, id) if *constructor != Variant(id) => None,
+                Def::Variant(..) | Def::Struct(..) => {
                     Some(match args {
                         &Some(ref args) => args.iter().map(|p| &**p).collect(),
                         &None => vec![DUMMY_WILD_PAT; arity],
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
deleted file mode 100644 (file)
index 5ead8fb..0000000
+++ /dev/null
@@ -1,106 +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.
-
-// Checks that all rvalues in a crate have statically known size. check_crate
-// is the public starting point.
-
-use dep_graph::DepNode;
-use middle::expr_use_visitor as euv;
-use middle::infer;
-use middle::mem_categorization as mc;
-use middle::ty::ParameterEnvironment;
-use middle::ty;
-
-use rustc_front::hir;
-use rustc_front::intravisit;
-use syntax::ast;
-use syntax::codemap::Span;
-
-pub fn check_crate(tcx: &ty::ctxt) {
-    let mut rvcx = RvalueContext { tcx: tcx };
-    tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
-}
-
-struct RvalueContext<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-}
-
-impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
-    fn visit_fn(&mut self,
-                fk: intravisit::FnKind<'v>,
-                fd: &'v hir::FnDecl,
-                b: &'v hir::Block,
-                s: Span,
-                fn_id: ast::NodeId) {
-        {
-            // FIXME (@jroesch) change this to be an inference context
-            let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
-            let infcx = infer::new_infer_ctxt(self.tcx,
-                                              &self.tcx.tables,
-                                              Some(param_env.clone()));
-            let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
-            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
-            euv.walk_fn(fd, b);
-        }
-        intravisit::walk_fn(self, fk, fd, b, s)
-    }
-}
-
-struct RvalueContextDelegate<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    param_env: &'a ty::ParameterEnvironment<'a,'tcx>,
-}
-
-impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
-    fn consume(&mut self,
-               _: ast::NodeId,
-               span: Span,
-               cmt: mc::cmt<'tcx>,
-               _: euv::ConsumeMode) {
-        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
-        if !cmt.ty.is_sized(self.param_env, span) {
-            span_err!(self.tcx.sess, span, E0161,
-                "cannot move a value of type {0}: the size of {0} cannot be statically determined",
-                cmt.ty);
-        }
-    }
-
-    fn matched_pat(&mut self,
-                   _matched_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &hir::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {
-    }
-
-    fn borrow(&mut self,
-              _borrow_id: ast::NodeId,
-              _borrow_span: Span,
-              _cmt: mc::cmt,
-              _loan_region: ty::Region,
-              _bk: ty::BorrowKind,
-              _loan_cause: euv::LoanCause) {
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {
-    }
-
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {
-    }
-}
diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs
deleted file mode 100644 (file)
index 0882f3f..0000000
+++ /dev/null
@@ -1,290 +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.
-
-// This compiler pass detects constants that refer to themselves
-// recursively.
-
-use front::map as ast_map;
-use session::Session;
-use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefVariant, DefMap};
-use util::nodemap::NodeMap;
-
-use syntax::{ast};
-use syntax::codemap::Span;
-use syntax::feature_gate::{GateIssue, emit_feature_err};
-use rustc_front::intravisit::{self, Visitor};
-use rustc_front::hir;
-
-use std::cell::RefCell;
-
-struct CheckCrateVisitor<'a, 'ast: 'a> {
-    sess: &'a Session,
-    def_map: &'a DefMap,
-    ast_map: &'a ast_map::Map<'ast>,
-    // `discriminant_map` is a cache that associates the `NodeId`s of local
-    // variant definitions with the discriminant expression that applies to
-    // each one. If the variant uses the default values (starting from `0`),
-    // then `None` is stored.
-    discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
-}
-
-impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast hir::Item) {
-        match it.node {
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) => {
-                let mut recursion_visitor =
-                    CheckItemRecursionVisitor::new(self, &it.span);
-                recursion_visitor.visit_item(it);
-            },
-            hir::ItemEnum(ref enum_def, ref generics) => {
-                // We could process the whole enum, but handling the variants
-                // with discriminant expressions one by one gives more specific,
-                // less redundant output.
-                for variant in &enum_def.variants {
-                    if let Some(_) = variant.node.disr_expr {
-                        let mut recursion_visitor =
-                            CheckItemRecursionVisitor::new(self, &variant.span);
-                        recursion_visitor.populate_enum_discriminants(enum_def);
-                        recursion_visitor.visit_variant(variant, generics, it.id);
-                    }
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_item(self, it)
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
-        match ti.node {
-            hir::ConstTraitItem(_, ref default) => {
-                if let Some(_) = *default {
-                    let mut recursion_visitor =
-                        CheckItemRecursionVisitor::new(self, &ti.span);
-                    recursion_visitor.visit_trait_item(ti);
-                }
-            }
-            _ => {}
-        }
-        intravisit::walk_trait_item(self, ti)
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
-        match ii.node {
-            hir::ImplItemKind::Const(..) => {
-                let mut recursion_visitor =
-                    CheckItemRecursionVisitor::new(self, &ii.span);
-                recursion_visitor.visit_impl_item(ii);
-            }
-            _ => {}
-        }
-        intravisit::walk_impl_item(self, ii)
-    }
-}
-
-pub fn check_crate<'ast>(sess: &Session,
-                         krate: &'ast hir::Crate,
-                         def_map: &DefMap,
-                         ast_map: &ast_map::Map<'ast>) {
-    let mut visitor = CheckCrateVisitor {
-        sess: sess,
-        def_map: def_map,
-        ast_map: ast_map,
-        discriminant_map: RefCell::new(NodeMap()),
-    };
-    sess.abort_if_new_errors(|| {
-        krate.visit_all_items(&mut visitor);
-    });
-}
-
-struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
-    root_span: &'a Span,
-    sess: &'a Session,
-    ast_map: &'a ast_map::Map<'ast>,
-    def_map: &'a DefMap,
-    discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
-    idstack: Vec<ast::NodeId>,
-}
-
-impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
-    fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span)
-           -> CheckItemRecursionVisitor<'a, 'ast> {
-        CheckItemRecursionVisitor {
-            root_span: span,
-            sess: v.sess,
-            ast_map: v.ast_map,
-            def_map: v.def_map,
-            discriminant_map: &v.discriminant_map,
-            idstack: Vec::new(),
-        }
-    }
-    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
-          where F: Fn(&mut Self) {
-        if self.idstack.iter().any(|&x| x == id) {
-            let any_static = self.idstack.iter().any(|&x| {
-                if let ast_map::NodeItem(item) = self.ast_map.get(x) {
-                    if let hir::ItemStatic(..) = item.node {
-                        true
-                    } else {
-                        false
-                    }
-                } else {
-                    false
-                }
-            });
-            if any_static {
-                if !self.sess.features.borrow().static_recursion {
-                    emit_feature_err(&self.sess.parse_sess.span_diagnostic,
-                                     "static_recursion",
-                                     *self.root_span, GateIssue::Language, "recursive static");
-                }
-            } else {
-                span_err!(self.sess, *self.root_span, E0265, "recursive constant");
-            }
-            return;
-        }
-        self.idstack.push(id);
-        f(self);
-        self.idstack.pop();
-    }
-    // If a variant has an expression specifying its discriminant, then it needs
-    // to be checked just like a static or constant. However, if there are more
-    // variants with no explicitly specified discriminant, those variants will
-    // increment the same expression to get their values.
-    //
-    // So for every variant, we need to track whether there is an expression
-    // somewhere in the enum definition that controls its discriminant. We do
-    // this by starting from the end and searching backward.
-    fn populate_enum_discriminants(&self, enum_definition: &'ast hir::EnumDef) {
-        // Get the map, and return if we already processed this enum or if it
-        // has no variants.
-        let mut discriminant_map = self.discriminant_map.borrow_mut();
-        match enum_definition.variants.first() {
-            None => { return; }
-            Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => {
-                return;
-            }
-            _ => {}
-        }
-
-        // Go through all the variants.
-        let mut variant_stack: Vec<ast::NodeId> = Vec::new();
-        for variant in enum_definition.variants.iter().rev() {
-            variant_stack.push(variant.node.data.id());
-            // When we find an expression, every variant currently on the stack
-            // is affected by that expression.
-            if let Some(ref expr) = variant.node.disr_expr {
-                for id in &variant_stack {
-                    discriminant_map.insert(*id, Some(expr));
-                }
-                variant_stack.clear()
-            }
-        }
-        // If we are at the top, that always starts at 0, so any variant on the
-        // stack has a default value and does not need to be checked.
-        for id in &variant_stack {
-            discriminant_map.insert(*id, None);
-        }
-    }
-}
-
-impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
-    fn visit_item(&mut self, it: &'ast hir::Item) {
-        self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it));
-    }
-
-    fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
-                      generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) {
-        self.populate_enum_discriminants(enum_definition);
-        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
-    }
-
-    fn visit_variant(&mut self, variant: &'ast hir::Variant,
-                     _: &'ast hir::Generics, _: ast::NodeId) {
-        let variant_id = variant.node.data.id();
-        let maybe_expr;
-        if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
-            // This is necessary because we need to let the `discriminant_map`
-            // borrow fall out of scope, so that we can reborrow farther down.
-            maybe_expr = (*get_expr).clone();
-        } else {
-            self.sess.span_bug(variant.span,
-                               "`check_static_recursion` attempted to visit \
-                                variant with unknown discriminant")
-        }
-        // If `maybe_expr` is `None`, that's because no discriminant is
-        // specified that affects this variant. Thus, no risk of recursion.
-        if let Some(expr) = maybe_expr {
-            self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr));
-        }
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
-        self.with_item_id_pushed(ti.id, |v| intravisit::walk_trait_item(v, ti));
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
-        self.with_item_id_pushed(ii.id, |v| intravisit::walk_impl_item(v, ii));
-    }
-
-    fn visit_expr(&mut self, e: &'ast hir::Expr) {
-        match e.node {
-            hir::ExprPath(..) => {
-                match self.def_map.get(&e.id).map(|d| d.base_def) {
-                    Some(DefStatic(def_id, _)) |
-                    Some(DefAssociatedConst(def_id)) |
-                    Some(DefConst(def_id)) => {
-                        if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
-                            match self.ast_map.get(node_id) {
-                                ast_map::NodeItem(item) =>
-                                    self.visit_item(item),
-                                ast_map::NodeTraitItem(item) =>
-                                    self.visit_trait_item(item),
-                                ast_map::NodeImplItem(item) =>
-                                    self.visit_impl_item(item),
-                                ast_map::NodeForeignItem(_) => {},
-                                _ => {
-                                    self.sess.span_bug(
-                                        e.span,
-                                        &format!("expected item, found {}",
-                                                 self.ast_map.node_to_string(node_id)));
-                                }
-                            }
-                        }
-                    }
-                    // For variants, we only want to check expressions that
-                    // affect the specific variant used, but we need to check
-                    // the whole enum definition to see what expression that
-                    // might be (if any).
-                    Some(DefVariant(enum_id, variant_id, false)) => {
-                        if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) {
-                            if let hir::ItemEnum(ref enum_def, ref generics) =
-                                self.ast_map.expect_item(enum_node_id).node
-                            {
-                                self.populate_enum_discriminants(enum_def);
-                                let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap();
-                                let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap();
-                                let variant = self.ast_map.expect_variant(variant_id);
-                                self.visit_variant(variant, generics, enum_id);
-                            } else {
-                                self.sess.span_bug(e.span,
-                                                   "`check_static_recursion` found \
-                                                    non-enum in DefVariant");
-                            }
-                        }
-                    }
-                    _ => ()
-                }
-            },
-            _ => ()
-        }
-        intravisit::walk_expr(self, e);
-    }
-}
index eae2aa9cb7e736547332d177b6ea48812604bbdb..ef011067cd077c36f0784d4b3118db504aafc0cf 100644 (file)
@@ -17,7 +17,8 @@
 use front::map as ast_map;
 use front::map::blocks::FnLikeNode;
 use middle::cstore::{self, CrateStore, InlinedItem};
-use middle::{def, infer, subst, traits};
+use middle::{infer, subst, traits};
+use middle::def::Def;
 use middle::subst::Subst;
 use middle::def_id::DefId;
 use middle::pat_util::def_to_path;
@@ -331,9 +332,9 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
                entry.insert(def);
             }
             let path = match def.full_def() {
-                def::DefStruct(def_id) => def_to_path(tcx, def_id),
-                def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
-                def::DefFn(..) => return P(hir::Pat {
+                Def::Struct(def_id) => def_to_path(tcx, def_id),
+                Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
+                Def::Fn(..) => return P(hir::Pat {
                     id: expr.id,
                     node: hir::PatLit(P(expr.clone())),
                     span: span,
@@ -364,12 +365,12 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
         hir::ExprPath(_, ref path) => {
             let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
-                Some(def::DefStruct(..)) =>
+                Some(Def::Struct(..)) =>
                     hir::PatStruct(path.clone(), hir::HirVec::new(), false),
-                Some(def::DefVariant(..)) =>
+                Some(Def::Variant(..)) =>
                     hir::PatEnum(path.clone(), None),
-                Some(def::DefConst(def_id)) |
-                Some(def::DefAssociatedConst(def_id)) => {
+                Some(Def::Const(def_id)) |
+                Some(Def::AssociatedConst(def_id)) => {
                     let expr = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
                     return const_expr_to_pat(tcx, expr, span);
                 },
@@ -1002,7 +1003,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               None
           };
           let (const_expr, const_ty) = match opt_def {
-              Some(def::DefConst(def_id)) => {
+              Some(Def::Const(def_id)) => {
                   if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                       match tcx.map.find(node_id) {
                           Some(ast_map::NodeItem(it)) => match it.node {
@@ -1017,7 +1018,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
                   }
               }
-              Some(def::DefAssociatedConst(def_id)) => {
+              Some(Def::AssociatedConst(def_id)) => {
                   if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                       match tcx.impl_or_trait_item(def_id).container() {
                           ty::TraitContainer(trait_id) => match tcx.map.find(node_id) {
@@ -1052,21 +1053,21 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                       (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
                   }
               }
-              Some(def::DefVariant(enum_def, variant_def, _)) => {
+              Some(Def::Variant(enum_def, variant_def)) => {
                   (lookup_variant_by_id(tcx, enum_def, variant_def), None)
               }
-              Some(def::DefStruct(_)) => {
+              Some(Def::Struct(..)) => {
                   return Ok(ConstVal::Struct(e.id))
               }
-              Some(def::DefLocal(_, id)) => {
-                  debug!("DefLocal({:?}): {:?}", id, fn_args);
+              Some(Def::Local(_, id)) => {
+                  debug!("Def::Local({:?}): {:?}", id, fn_args);
                   if let Some(val) = fn_args.and_then(|args| args.get(&id)) {
                       return Ok(val.clone());
                   } else {
                       (None, None)
                   }
               },
-              Some(def::DefMethod(id)) | Some(def::DefFn(id, _)) => return Ok(Function(id)),
+              Some(Def::Method(id)) | Some(Def::Fn(id)) => return Ok(Function(id)),
               _ => (None, None)
           };
           let const_expr = match const_expr {
@@ -1232,20 +1233,11 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                                                 rcvr_substs: subst::Substs<'tcx>)
                                                 -> Option<&'tcx Expr>
 {
-    let subst::SeparateVecsPerParamSpace {
-        types: rcvr_type,
-        selfs: rcvr_self,
-        fns: _,
-    } = rcvr_substs.types.split();
-    let trait_substs =
-        subst::Substs::erased(subst::VecPerParamSpace::new(rcvr_type,
-                                                           rcvr_self,
-                                                           Vec::new()));
-    let trait_substs = tcx.mk_substs(trait_substs);
-    debug!("resolve_trait_associated_const: trait_substs={:?}",
-           trait_substs);
-    let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
-                                              substs: trait_substs });
+    let trait_ref = ty::Binder(
+        rcvr_substs.erase_regions().to_trait_ref(tcx, trait_id)
+    );
+    debug!("resolve_trait_associated_const: trait_ref={:?}",
+           trait_ref);
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
     let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
diff --git a/src/librustc/middle/const_qualif.rs b/src/librustc/middle/const_qualif.rs
new file mode 100644 (file)
index 0000000..ec98637
--- /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.
+
+// Const qualification, from partial to completely promotable.
+bitflags! {
+    #[derive(RustcEncodable, RustcDecodable)]
+    flags ConstQualif: u8 {
+        // Inner mutability (can not be placed behind a reference) or behind
+        // &mut in a non-global expression. Can be copied from static memory.
+        const MUTABLE_MEM        = 1 << 0,
+        // Constant value with a type that implements Drop. Can be copied
+        // from static memory, similar to MUTABLE_MEM.
+        const NEEDS_DROP         = 1 << 1,
+        // Even if the value can be placed in static memory, copying it from
+        // there is more expensive than in-place instantiation, and/or it may
+        // be too large. This applies to [T; N] and everything containing it.
+        // N.B.: references need to clear this flag to not end up on the stack.
+        const PREFER_IN_PLACE    = 1 << 2,
+        // May use more than 0 bytes of memory, doesn't impact the constness
+        // directly, but is not allowed to be borrowed mutably in a constant.
+        const NON_ZERO_SIZED     = 1 << 3,
+        // Actually borrowed, has to always be in static memory. Does not
+        // propagate, and requires the expression to behave like a 'static
+        // lvalue. The set of expressions with this flag is the minimum
+        // that have to be promoted.
+        const HAS_STATIC_BORROWS = 1 << 4,
+        // Invalid const for miscellaneous reasons (e.g. not implemented).
+        const NOT_CONST          = 1 << 5,
+
+        // Borrowing the expression won't produce &'static T if any of these
+        // bits are set, though the value could be copied from static memory
+        // if `NOT_CONST` isn't set.
+        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
+                                   ConstQualif::NEEDS_DROP.bits |
+                                   ConstQualif::NOT_CONST.bits
+    }
+}
index 380f543f969f06b4c2a77dde7c27233957032325..27745a85935abf00d8c6668ca8da7b61754c81b3 100644 (file)
@@ -24,9 +24,9 @@
 
 use back::svh::Svh;
 use front::map as hir_map;
-use middle::def;
+use middle::def::{self, Def};
 use middle::lang_items;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, VariantKind};
 use middle::def_id::{DefId, DefIndex};
 use mir::repr::Mir;
 use session::Session;
@@ -84,7 +84,7 @@ pub enum NativeLibraryKind {
 // Something that a name can resolve to.
 #[derive(Copy, Clone, Debug)]
 pub enum DefLike {
-    DlDef(def::Def),
+    DlDef(Def),
     DlImpl(DefId),
     DlField
 }
@@ -211,6 +211,8 @@ fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
 
     // resolve
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind>;
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>;
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>;
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
     fn item_children(&self, did: DefId) -> Vec<ChildItem>;
@@ -380,6 +382,9 @@ fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
 
     // resolve
     fn def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
+        { unimplemented!() }
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
         { unimplemented!() }
     fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { unimplemented!() }
index 1386ef91c70bf49e0ec7209f2252cbd9cb1bbcfa..1fa4093853b8199d10867094ac86307bc1c0609c 100644 (file)
@@ -17,7 +17,8 @@
 use rustc_front::hir;
 use rustc_front::intravisit::{self, Visitor};
 
-use middle::{def, pat_util, privacy, ty};
+use middle::{pat_util, privacy, ty};
+use middle::def::Def;
 use middle::def_id::{DefId};
 use lint;
 
@@ -94,13 +95,13 @@ fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
 
         self.tcx.def_map.borrow().get(id).map(|def| {
             match def.full_def() {
-                def::DefConst(_) | def::DefAssociatedConst(..) => {
+                Def::Const(_) | Def::AssociatedConst(..) => {
                     self.check_def_id(def.def_id());
                 }
                 _ if self.ignore_non_const_paths => (),
-                def::DefPrimTy(_) => (),
-                def::DefSelfTy(..) => (),
-                def::DefVariant(enum_id, variant_id, _) => {
+                Def::PrimTy(_) => (),
+                Def::SelfTy(..) => (),
+                Def::Variant(enum_id, variant_id) => {
                     self.check_def_id(enum_id);
                     if !self.ignore_variant_stack.contains(&variant_id) {
                         self.check_def_id(variant_id);
index 9ef2828c947aad2469d7f766ebe799b7e5830aeb..be967da2713b328b352c202d6d2cbb3f5adab7b5 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::Def::*;
-
 use middle::def_id::DefId;
 use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
 
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Def {
-    DefFn(DefId, bool /* is_ctor */),
-    DefSelfTy(Option<DefId>,                    // trait id
+    Fn(DefId),
+    SelfTy(Option<DefId>,                    // trait id
               Option<(ast::NodeId, ast::NodeId)>),   // (impl id, self type id)
-    DefMod(DefId),
-    DefForeignMod(DefId),
-    DefStatic(DefId, bool /* is_mutbl */),
-    DefConst(DefId),
-    DefAssociatedConst(DefId),
-    DefLocal(DefId, // def id of variable
+    Mod(DefId),
+    ForeignMod(DefId),
+    Static(DefId, bool /* is_mutbl */),
+    Const(DefId),
+    AssociatedConst(DefId),
+    Local(DefId, // def id of variable
              ast::NodeId), // node id of variable
-    DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
-    DefTy(DefId, bool /* is_enum */),
-    DefAssociatedTy(DefId /* trait */, DefId),
-    DefTrait(DefId),
-    DefPrimTy(hir::PrimTy),
-    DefTyParam(ParamSpace, u32, DefId, ast::Name),
-    DefUpvar(DefId,        // def id of closed over local
+    Variant(DefId /* enum */, DefId /* variant */),
+    Enum(DefId),
+    TyAlias(DefId),
+    AssociatedTy(DefId /* trait */, DefId),
+    Trait(DefId),
+    PrimTy(hir::PrimTy),
+    TyParam(ParamSpace, u32, DefId, ast::Name),
+    Upvar(DefId,        // def id of closed over local
              ast::NodeId,  // node id of closed over local
              usize,        // index in the freevars list of the closure
              ast::NodeId), // expr node that creates the closure
 
-    /// Note that if it's a tuple struct's definition, the node id of the DefId
-    /// may either refer to the item definition's id or the VariantData.ctor_id.
-    ///
-    /// The cases that I have encountered so far are (this is not exhaustive):
-    /// - If it's a ty_path referring to some tuple struct, then DefMap maps
-    ///   it to a def whose id is the item definition's id.
-    /// - If it's an ExprPath referring to some tuple struct, then DefMap maps
-    ///   it to a def whose id is the VariantData.ctor_id.
-    DefStruct(DefId),
-    DefLabel(ast::NodeId),
-    DefMethod(DefId),
-    DefErr,
+    // If Def::Struct lives in type namespace it denotes a struct item and its DefId refers
+    // to NodeId of the struct itself.
+    // If Def::Struct lives in value namespace (e.g. tuple struct, unit struct expressions)
+    // it denotes a constructor and its DefId refers to NodeId of the struct's constructor.
+    Struct(DefId),
+    Label(ast::NodeId),
+    Method(DefId),
+    Err,
 }
 
 /// The result of resolving a path.
@@ -115,16 +110,16 @@ pub struct Export {
 impl Def {
     pub fn var_id(&self) -> ast::NodeId {
         match *self {
-            DefLocal(_, id) |
-            DefUpvar(_, id, _, _) => {
+            Def::Local(_, id) |
+            Def::Upvar(_, id, _, _) => {
                 id
             }
 
-            DefFn(..) | DefMod(..) | DefForeignMod(..) | DefStatic(..) |
-            DefVariant(..) | DefTy(..) | DefAssociatedTy(..) |
-            DefTyParam(..) | DefStruct(..) | DefTrait(..) |
-            DefMethod(..) | DefConst(..) | DefAssociatedConst(..) |
-            DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) | DefErr => {
+            Def::Fn(..) | Def::Mod(..) | Def::ForeignMod(..) | Def::Static(..) |
+            Def::Variant(..) | Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
+            Def::TyParam(..) | Def::Struct(..) | Def::Trait(..) |
+            Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) |
+            Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => {
                 panic!("attempted .def_id() on invalid {:?}", self)
             }
         }
@@ -132,18 +127,18 @@ pub fn var_id(&self) -> ast::NodeId {
 
     pub fn def_id(&self) -> DefId {
         match *self {
-            DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
-            DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
-            DefTyParam(_, _, id, _) | DefStruct(id) | DefTrait(id) |
-            DefMethod(id) | DefConst(id) | DefAssociatedConst(id) |
-            DefLocal(id, _) | DefUpvar(id, _, _, _) => {
+            Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
+            Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
+            Def::TyParam(_, _, id, _) | Def::Struct(id) | Def::Trait(id) |
+            Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
+            Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
                 id
             }
 
-            DefLabel(..)  |
-            DefPrimTy(..) |
-            DefSelfTy(..) |
-            DefErr => {
+            Def::Label(..)  |
+            Def::PrimTy(..) |
+            Def::SelfTy(..) |
+            Def::Err => {
                 panic!("attempted .def_id() on invalid def: {:?}", self)
             }
         }
@@ -151,7 +146,7 @@ pub fn def_id(&self) -> DefId {
 
     pub fn variant_def_ids(&self) -> Option<(DefId, DefId)> {
         match *self {
-            DefVariant(enum_id, var_id, _) => {
+            Def::Variant(enum_id, var_id) => {
                 Some((enum_id, var_id))
             }
             _ => None
index 822faae772611f82c1a3b56385e4cf78f9f6e038..055beac5428440d3e4cd0943692de0cd8e489031 100644 (file)
@@ -12,7 +12,7 @@
 //! `unsafe`.
 use self::RootUnsafeContext::*;
 
-use middle::def;
+use middle::def::Def;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 
@@ -170,7 +170,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
             hir::ExprPath(..) => {
-                if let def::DefStatic(_, true) = self.tcx.resolve_expr(expr) {
+                if let Def::Static(_, true) = self.tcx.resolve_expr(expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
             }
index e746f3ac57914a712f61b39e935902a1219e72fe..b5baf84eef23da34faf5961af7e7c1d0755ee46c 100644 (file)
@@ -19,7 +19,8 @@
 use self::TrackMatchMode::*;
 use self::OverloadedCallType::*;
 
-use middle::{def, pat_util};
+use middle::pat_util;
+use middle::def::Def;
 use middle::def_id::{DefId};
 use middle::infer;
 use middle::mem_categorization as mc;
@@ -1077,7 +1078,7 @@ fn walk_pat(&mut self,
                             // struct or enum pattern.
                         }
 
-                        Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
+                        Some(Def::Variant(enum_did, variant_did)) => {
                             let downcast_cmt =
                                 if tcx.lookup_adt_def(enum_did).is_univariant() {
                                     cmt_pat
@@ -1093,7 +1094,7 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, downcast_cmt, match_mode);
                         }
 
-                        Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
+                        Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => {
                             // A struct (in either the value or type
                             // namespace; we encounter the former on
                             // e.g. patterns for unit structs).
@@ -1105,28 +1106,17 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, cmt_pat, match_mode);
                         }
 
-                        Some(def::DefConst(..)) |
-                        Some(def::DefAssociatedConst(..)) |
-                        Some(def::DefLocal(..)) => {
+                        Some(Def::Const(..)) |
+                        Some(Def::AssociatedConst(..)) |
+                        Some(Def::Local(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
                             // `matched_pat` call.
                         }
 
-                        Some(def @ def::DefTy(_, true)) => {
-                            // An enum's type -- should never be in a
-                            // pattern.
-
-                            if !tcx.sess.has_errors() {
-                                let msg = format!("Pattern has unexpected type: {:?} and type {:?}",
-                                                  def,
-                                                  cmt_pat.ty);
-                                tcx.sess.span_bug(pat.span, &msg)
-                            }
-                        }
-
                         Some(def) => {
-                            // Remaining cases are e.g. DefFn, to
+                            // An enum type should never be in a pattern.
+                            // Remaining cases are e.g. Def::Fn, to
                             // which identifiers within patterns
                             // should not resolve. However, we do
                             // encouter this when using the
@@ -1195,7 +1185,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr) {
     fn cat_captured_var(&mut self,
                         closure_id: ast::NodeId,
                         closure_span: Span,
-                        upvar_def: def::Def)
+                        upvar_def: Def)
                         -> mc::McResult<mc::cmt<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
index 5cc848d2ca3d1516cb0ee15825db05abce6c0820..b83cd60031d13f2736b7b1e551a2cdaa47ff46d4 100644 (file)
@@ -77,7 +77,7 @@
 use rustc_front::print::pprust;
 
 use middle::cstore::CrateStore;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer::{self, TypeOrigin};
 use middle::region;
@@ -1404,7 +1404,7 @@ fn rebuild_arg_ty_or_output(&self,
                         Some(d) => d.full_def()
                     };
                     match a_def {
-                        def::DefTy(did, _) | def::DefStruct(did) => {
+                        Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
                             let generics = self.tcx.lookup_item_type(did).generics;
 
                             let expected =
@@ -1452,7 +1452,6 @@ fn rebuild_arg_ty_or_output(&self,
                         }
                         _ => ()
                     }
-
                 }
 
                 hir::TyPtr(ref mut_ty) => {
index 69b952ca1f3fcf3ae42320e8d02d3c294cdb46cf..9afc1e366eed5793fb96d95488f074c29cc8078c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use dep_graph::DepNode;
-use middle::def::DefFn;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::subst::{Subst, Substs, EnumeratedItems};
 use middle::ty::{TransmuteRestriction, ctxt, TyBareFn};
@@ -235,7 +235,7 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
     fn visit_expr(&mut self, expr: &hir::Expr) {
         if let hir::ExprPath(..) = expr.node {
             match self.tcx.resolve_expr(expr) {
-                DefFn(did, _) if self.def_id_is_transmute(did) => {
+                Def::Fn(did) if self.def_id_is_transmute(did) => {
                     let typ = self.tcx.node_id_to_type(expr.id);
                     match typ.sty {
                         TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
index 29299f01ed36fcc2f4a4829a1906e8ef9549c321..90fa148e0084eb43bed1e683d668f2e453da86bb 100644 (file)
@@ -448,7 +448,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       hir::ExprPath(..) => {
         let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
-        if let DefLocal(..) = def {
+        if let Def::Local(..) = def {
             ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
         }
         intravisit::walk_expr(ir, expr);
@@ -465,7 +465,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         let mut call_caps = Vec::new();
         ir.tcx.with_freevars(expr.id, |freevars| {
             for fv in freevars {
-                if let DefLocal(_, rv) = fv.def {
+                if let Def::Local(_, rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
                     call_caps.push(CaptureInfo {ln: fv_ln,
                                                 var_nid: rv});
@@ -697,7 +697,7 @@ fn find_loop_scope(&self,
                 // Refers to a labeled loop. Use the results of resolve
                 // to find with one
                 match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
-                    Some(DefLabel(loop_id)) => loop_id,
+                    Some(Def::Label(loop_id)) => loop_id,
                     _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
                                                         doesn't refer to a loop")
                 }
@@ -1276,7 +1276,7 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
-          DefLocal(_, nid) => {
+          Def::Local(_, nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
                 self.init_from_succ(ln, succ);
@@ -1531,7 +1531,7 @@ fn check_ret(&self,
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
             hir::ExprPath(..) => {
-                if let DefLocal(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
+                if let Def::Local(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
                                                                       .unwrap()
                                                                       .full_def() {
                     // Assignment to an immutable variable or argument: only legal
index 1eb5efa0bda446eb88fe613d786608c88fb4359f..affd963fb79172fc2dc055ed58493e3f1fd3315f 100644 (file)
@@ -74,8 +74,8 @@
 use middle::def_id::DefId;
 use front::map as ast_map;
 use middle::infer;
-use middle::check_const;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::Def;
 use middle::ty::adjustment;
 use middle::ty::{self, Ty};
 
@@ -542,32 +542,27 @@ pub fn cat_def(&self,
                    id: ast::NodeId,
                    span: Span,
                    expr_ty: Ty<'tcx>,
-                   def: def::Def)
+                   def: Def)
                    -> McResult<cmt<'tcx>> {
         debug!("cat_def: id={} expr={:?} def={:?}",
                id, expr_ty, def);
 
         match def {
-          def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefAssociatedConst(..) | def::DefFn(..) | def::DefMethod(..) => {
+          Def::Struct(..) | Def::Variant(..) | Def::Const(..) |
+          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
-          def::DefMod(_) | def::DefForeignMod(_) |
-          def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
-          def::DefTyParam(..) |
-          def::DefLabel(_) | def::DefSelfTy(..) |
-          def::DefAssociatedTy(..) => {
-              Ok(Rc::new(cmt_ {
-                  id:id,
-                  span:span,
-                  cat:Categorization::StaticItem,
-                  mutbl: McImmutable,
-                  ty:expr_ty,
-                  note: NoteNone
-              }))
+
+          Def::Mod(_) | Def::ForeignMod(_) |
+          Def::Trait(_) | Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(_) |
+          Def::TyParam(..) |
+          Def::Label(_) | Def::SelfTy(..) |
+          Def::AssociatedTy(..) => {
+              self.tcx().sess.span_bug(span, &format!("Unexpected definition in \
+                                                       memory categorization: {:?}", def));
           }
 
-          def::DefStatic(_, mutbl) => {
+          Def::Static(_, mutbl) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
@@ -578,7 +573,7 @@ pub fn cat_def(&self,
               }))
           }
 
-          def::DefUpvar(_, var_id, _, fn_node_id) => {
+          Def::Upvar(_, var_id, _, fn_node_id) => {
               let ty = try!(self.node_ty(fn_node_id));
               match ty.sty {
                   ty::TyClosure(closure_id, _) => {
@@ -603,7 +598,7 @@ pub fn cat_def(&self,
               }
           }
 
-          def::DefLocal(_, vid) => {
+          Def::Local(_, vid) => {
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
@@ -614,7 +609,7 @@ pub fn cat_def(&self,
             }))
           }
 
-          def::DefErr => panic!("DefErr in memory categorization")
+          Def::Err => panic!("Def::Err in memory categorization")
         }
     }
 
@@ -800,19 +795,19 @@ pub fn cat_rvalue_node(&self,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
         let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
-                               .unwrap_or(check_const::ConstQualif::NOT_CONST);
+                               .unwrap_or(ConstQualif::NOT_CONST);
 
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
         let qualif = match expr_ty.sty {
             ty::TyArray(_, 0) => qualif,
-            _ => check_const::ConstQualif::NOT_CONST
+            _ => ConstQualif::NOT_CONST
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
+        let re = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
             self.temporary_scope(id)
         } else {
             ty::ReStatic
@@ -1202,7 +1197,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         (*op)(self, cmt.clone(), pat);
 
         let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) {
-            if path_res.depth != 0 || path_res.base_def == def::DefErr {
+            if path_res.depth != 0 || path_res.base_def == Def::Err {
                 // Since patterns can be associated constants
                 // which are resolved during typeck, we might have
                 // some unresolved patterns reaching this stage
@@ -1218,7 +1213,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
         // alone) because struct patterns can refer to struct types or
         // to struct variants within enums.
         let cmt = match opt_def {
-            Some(def::DefVariant(enum_did, variant_did, _))
+            Some(Def::Variant(enum_did, variant_did))
                 // univariant enums do not need downcasts
                 if !self.tcx().lookup_adt_def(enum_did).is_univariant() => {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@@ -1236,7 +1231,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
           }
           hir::PatEnum(_, Some(ref subpats)) => {
             match opt_def {
-                Some(def::DefVariant(..)) => {
+                Some(Def::Variant(..)) => {
                     // variant(x, y, z)
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@@ -1249,7 +1244,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                         try!(self.cat_pattern_(subcmt, &**subpat, op));
                     }
                 }
-                Some(def::DefStruct(..)) => {
+                Some(Def::Struct(..)) => {
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
                         let cmt_field =
@@ -1259,7 +1254,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                         try!(self.cat_pattern_(cmt_field, &**subpat, op));
                     }
                 }
-                Some(def::DefConst(..)) | Some(def::DefAssociatedConst(..)) => {
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
index 1284e9fd1454eab7044b9cdd7e263f0c170f4f2a..41367b9361fbb2866d9979b536f65c73aa4753b4 100644 (file)
@@ -39,7 +39,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
         hir::PatIdent(_, _, None) |
         hir::PatStruct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefVariant(..)) => true,
+                Some(Def::Variant(..)) => true,
                 _ => false
             }
         }
@@ -54,7 +54,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
         hir::PatIdent(_, _, None) |
         hir::PatStruct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefVariant(..)) | Some(DefStruct(..)) => true,
+                Some(Def::Variant(..)) | Some(Def::Struct(..)) => true,
                 _ => false
             }
         }
@@ -66,7 +66,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
         hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
             }
         }
@@ -82,7 +82,7 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
             match dm.get(&pat.id)
                     .and_then(|d| if d.depth == 0 { Some(d.base_def) }
                                   else { None } ) {
-                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
+                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
             }
         }
@@ -228,7 +228,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
             hir::PatIdent(_, _, None) |
             hir::PatStruct(..) => {
                 match dm.get(&p.id) {
-                    Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
+                    Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => {
                         variants.push(id);
                     }
                     _ => ()
index 738440adf416d9280ff08a92a998db81e66c4f87..6373bfbc55ee65c70e8276916c76d9ad50e6a057 100644 (file)
@@ -17,7 +17,7 @@
 
 use dep_graph::DepNode;
 use front::map as ast_map;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::ty;
 use middle::privacy;
@@ -108,7 +108,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
-                            def::DefConst(..) | def::DefAssociatedConst(..) => {
+                            Def::Const(..) | Def::AssociatedConst(..) => {
                                 self.worklist.push(node_id);
                             }
 
index 2c74f3a82e41441e39cc501e9436691c96b5a669..af9d0987ff073e41be5363eac012eb4cafe4de56 100644 (file)
@@ -19,7 +19,7 @@
 use self::ScopeChain::*;
 
 use session::Session;
-use middle::def::{self, DefMap};
+use middle::def::{Def, DefMap};
 use middle::region;
 use middle::subst;
 use middle::ty;
@@ -205,7 +205,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
                 match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
-                    Some((def::DefTrait(..), 0)) => {
+                    Some((Def::Trait(..), 0)) => {
                         self.with(LateScope(&[], self.scope), |_, this| {
                             this.visit_path(path, ty.id);
                         });
index 87bc8bb885584a9ec7f599777083fc15c4d3e236..e0d38f1c76f6ceea10b7fd3a0c53d72a5388667c 100644 (file)
@@ -17,7 +17,7 @@
 use session::Session;
 use lint;
 use middle::cstore::{CrateStore, LOCAL_CRATE};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::ty;
 use middle::privacy::AccessLevels;
@@ -561,8 +561,8 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
 pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
-        Some(def::DefPrimTy(..)) => {}
-        Some(def::DefSelfTy(..)) => {}
+        Some(Def::PrimTy(..)) => {}
+        Some(Def::SelfTy(..)) => {}
         Some(def) => {
             maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
         }
@@ -573,7 +573,7 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
 pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
-        Some(def::DefPrimTy(..)) => {}
+        Some(Def::PrimTy(..)) => {}
         Some(def) => {
             maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
         }
index 61f7b2db4c43233769af36b0b8b5b185a49297b8..ddc817ffc023e0ee5c40c8436367334f6ff9cba9 100644 (file)
@@ -14,6 +14,7 @@
 pub use self::RegionSubsts::*;
 
 use middle::cstore;
+use middle::def_id::DefId;
 use middle::ty::{self, Ty};
 use middle::ty::fold::{TypeFoldable, TypeFolder};
 
@@ -142,16 +143,34 @@ pub fn with_method(self,
                        -> Substs<'tcx>
     {
         let Substs { types, regions } = self;
-        let types = types.with_vec(FnSpace, m_types);
-        let regions = regions.map(|r| r.with_vec(FnSpace, m_regions));
+        let types = types.with_slice(FnSpace, &m_types);
+        let regions = regions.map(|r| r.with_slice(FnSpace, &m_regions));
         Substs { types: types, regions: regions }
     }
 
-    pub fn method_to_trait(self) -> Substs<'tcx> {
-        let Substs { mut types, regions } = self;
+    pub fn with_method_from(self,
+                            meth_substs: &Substs<'tcx>)
+                            -> Substs<'tcx>
+    {
+        let Substs { types, regions } = self;
+        let types = types.with_slice(FnSpace, meth_substs.types.get_slice(FnSpace));
+        let regions = regions.map(|r| {
+            r.with_slice(FnSpace, meth_substs.regions().get_slice(FnSpace))
+        });
+        Substs { types: types, regions: regions }
+    }
+
+    /// Creates a trait-ref out of this substs, ignoring the FnSpace substs
+    pub fn to_trait_ref(&self, tcx: &ty::ctxt<'tcx>, trait_id: DefId)
+                        -> ty::TraitRef<'tcx> {
+        let Substs { mut types, regions } = self.clone();
         types.truncate(FnSpace, 0);
         let regions = regions.map(|mut r| { r.truncate(FnSpace, 0); r });
-        Substs { types: types, regions: regions }
+
+        ty::TraitRef {
+            def_id: trait_id,
+            substs: tcx.mk_substs(Substs { types: types, regions: regions })
+        }
     }
 }
 
@@ -290,10 +309,6 @@ pub fn empty() -> VecPerParamSpace<T> {
         }
     }
 
-    pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
-        VecPerParamSpace::empty().with_vec(TypeSpace, types)
-    }
-
     /// `t` is the type space.
     /// `s` is the self space.
     /// `f` is the fn space.
@@ -483,11 +498,15 @@ pub fn split(self) -> SeparateVecsPerParamSpace<T> {
         }
     }
 
-    pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
+    pub fn with_slice(mut self, space: ParamSpace, slice: &[T])
                     -> VecPerParamSpace<T>
+        where T: Clone
     {
         assert!(self.is_empty_in(space));
-        self.replace(space, vec);
+        for t in slice {
+            self.push(space, t.clone());
+        }
+
         self
     }
 }
index bdf1c4645c0ed84bfcba87aee4752f008f9cb33e..d28504db585c745b5a4c582b2a5b08b0cf1f0ae8 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use dep_graph::DepGraph;
 use middle::infer::InferCtxt;
 use middle::ty::{self, Ty, TypeFoldable};
 use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error};
 use super::Unimplemented;
 use super::util::predicate_for_builtin_bound;
 
-pub struct FulfilledPredicates<'tcx> {
+pub struct GlobalFulfilledPredicates<'tcx> {
+    set: FnvHashSet<ty::PolyTraitPredicate<'tcx>>,
+    dep_graph: DepGraph,
+}
+
+pub struct LocalFulfilledPredicates<'tcx> {
     set: FnvHashSet<ty::Predicate<'tcx>>
 }
 
@@ -56,7 +62,7 @@ pub struct FulfillmentContext<'tcx> {
     // initially-distinct type variables are unified after being
     // inserted. Deduplicating the predicate set on selection had a
     // significant performance cost the last time I checked.
-    duplicate_set: FulfilledPredicates<'tcx>,
+    duplicate_set: LocalFulfilledPredicates<'tcx>,
 
     // A list of all obligations that have been registered with this
     // fulfillment context.
@@ -106,7 +112,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
     /// Creates a new fulfillment context.
     pub fn new() -> FulfillmentContext<'tcx> {
         FulfillmentContext {
-            duplicate_set: FulfilledPredicates::new(),
+            duplicate_set: LocalFulfilledPredicates::new(),
             predicates: ObligationForest::new(),
             region_obligations: NodeMap(),
         }
@@ -240,7 +246,7 @@ fn is_duplicate_or_add(&mut self,
         // local cache).  This is because the tcx cache maintains the
         // invariant that it only contains things that have been
         // proven, and we have not yet proven that `predicate` holds.
-        if predicate.is_global() && tcx.fulfilled_predicates.borrow().is_duplicate(predicate) {
+        if tcx.fulfilled_predicates.borrow().check_duplicate(predicate) {
             return true;
         }
 
@@ -283,10 +289,7 @@ fn select<'a>(&mut self,
             // these are obligations that were proven to be true.
             for pending_obligation in outcome.completed {
                 let predicate = &pending_obligation.obligation.predicate;
-                if predicate.is_global() {
-                    selcx.tcx().fulfilled_predicates.borrow_mut()
-                                                    .is_duplicate_or_add(predicate);
-                }
+                selcx.tcx().fulfilled_predicates.borrow_mut().add_if_global(predicate);
             }
 
             errors.extend(
@@ -329,6 +332,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
             // However, this is a touch tricky, so I'm doing something
             // a bit hackier for now so that the `huge-struct.rs` passes.
 
+            let tcx = selcx.tcx();
+
             let retain_vec: Vec<_> = {
                 let mut dedup = FnvHashSet();
                 v.iter()
@@ -336,10 +341,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                      // Screen out obligations that we know globally
                      // are true. This should really be the DAG check
                      // mentioned above.
-                     if
-                         o.predicate.is_global() &&
-                         selcx.tcx().fulfilled_predicates.borrow().is_duplicate(&o.predicate)
-                     {
+                     if tcx.fulfilled_predicates.borrow().check_duplicate(&o.predicate) {
                          return false;
                      }
 
@@ -611,22 +613,62 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
 
 }
 
-impl<'tcx> FulfilledPredicates<'tcx> {
-    pub fn new() -> FulfilledPredicates<'tcx> {
-        FulfilledPredicates {
+impl<'tcx> LocalFulfilledPredicates<'tcx> {
+    pub fn new() -> LocalFulfilledPredicates<'tcx> {
+        LocalFulfilledPredicates {
             set: FnvHashSet()
         }
     }
 
-    pub fn is_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool {
-        self.set.contains(key)
-    }
-
     fn is_duplicate_or_add(&mut self, key: &ty::Predicate<'tcx>) -> bool {
+        // For a `LocalFulfilledPredicates`, if we find a match, we
+        // don't need to add a read edge to the dep-graph. This is
+        // because it means that the predicate has already been
+        // considered by this `FulfillmentContext`, and hence the
+        // containing task will already have an edge. (Here we are
+        // assuming each `FulfillmentContext` only gets used from one
+        // task; but to do otherwise makes no sense)
         !self.set.insert(key.clone())
     }
 }
 
+impl<'tcx> GlobalFulfilledPredicates<'tcx> {
+    pub fn new(dep_graph: DepGraph) -> GlobalFulfilledPredicates<'tcx> {
+        GlobalFulfilledPredicates {
+            set: FnvHashSet(),
+            dep_graph: dep_graph,
+        }
+    }
+
+    pub fn check_duplicate(&self, key: &ty::Predicate<'tcx>) -> bool {
+        if let ty::Predicate::Trait(ref data) = *key {
+            // For the global predicate registry, when we find a match, it
+            // may have been computed by some other task, so we want to
+            // add a read from the node corresponding to the predicate
+            // processing to make sure we get the transitive dependencies.
+            if self.set.contains(data) {
+                debug_assert!(data.is_global());
+                self.dep_graph.read(data.dep_node());
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    fn add_if_global(&mut self, key: &ty::Predicate<'tcx>) {
+        if let ty::Predicate::Trait(ref data) = *key {
+            // We only add things to the global predicate registry
+            // after the current task has proved them, and hence
+            // already has the required read edges, so we don't need
+            // to add any more edges here.
+            if data.is_global() {
+                self.set.insert(data.clone());
+            }
+        }
+    }
+}
+
 fn to_fulfillment_error<'tcx>(
     error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>)
     -> FulfillmentError<'tcx>
index 8fecffcea9fe446269f7b927bea4bbb32c41070e..f0ff0380aaa3109f1172b12fdc4afbd102d03bab 100644 (file)
 pub use self::Vtable::*;
 pub use self::ObligationCauseCode::*;
 
-use dep_graph::DepNode;
 use middle::def_id::DefId;
 use middle::free_region::FreeRegionMap;
 use middle::subst;
 use middle::ty::{self, Ty, TypeFoldable};
-use middle::ty::fast_reject;
 use middle::infer::{self, fixup_err_to_string, InferCtxt};
 
 use std::rc::Rc;
@@ -37,7 +35,7 @@
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
 pub use self::coherence::OrphanCheckErr;
-pub use self::fulfill::{FulfillmentContext, FulfilledPredicates, RegionObligation};
+pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
 pub use self::project::MismatchedProjectionTypes;
 pub use self::project::normalize;
 pub use self::project::Normalized;
@@ -617,18 +615,6 @@ fn new(obligation: PredicateObligation<'tcx>,
 }
 
 impl<'tcx> TraitObligation<'tcx> {
-    /// Creates the dep-node for selecting/evaluating this trait reference.
-    fn dep_node(&self, tcx: &ty::ctxt<'tcx>) -> DepNode {
-        let simplified_ty =
-            fast_reject::simplify_type(tcx,
-                                       self.predicate.skip_binder().self_ty(), // (*)
-                                       true);
-
-        // (*) skip_binder is ok because `simplify_type` doesn't care about regions
-
-        DepNode::TraitSelect(self.predicate.def_id(), simplified_ty)
-    }
-
     fn self_ty(&self) -> ty::Binder<Ty<'tcx>> {
         ty::Binder(self.predicate.skip_binder().self_ty())
     }
index 75992b6849b017193adc53aacfe73e92c4b684fa..61418734b674bacc1130ad16708c156ed3e18877 100644 (file)
@@ -307,7 +307,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
         debug!("select({:?})", obligation);
         assert!(!obligation.predicate.has_escaping_regions());
 
-        let dep_node = obligation.dep_node(self.tcx());
+        let dep_node = obligation.predicate.dep_node();
         let _task = self.tcx().dep_graph.in_task(dep_node);
 
         let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
@@ -462,7 +462,7 @@ fn evaluate_predicate_recursively<'o>(&mut self,
         // have been proven elsewhere. This cache only contains
         // predicates that are global in scope and hence unaffected by
         // the current environment.
-        if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
+        if self.tcx().fulfilled_predicates.borrow().check_duplicate(&obligation.predicate) {
             return EvaluatedToOk;
         }
 
index d1504d25288a8d93c4db24aee8e3ccdd5ed74006..7010bae7ee5bfc7d58bc85fca9bd9dec519adc79 100644 (file)
@@ -367,13 +367,13 @@ pub struct ctxt<'tcx> {
     /// This is used to avoid duplicate work. Predicates are only
     /// added to this set when they mention only "global" names
     /// (i.e., no type or lifetime parameters).
-    pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>,
+    pub fulfilled_predicates: RefCell<traits::GlobalFulfilledPredicates<'tcx>>,
 
     /// Caches the representation hints for struct definitions.
     repr_hint_cache: RefCell<DepTrackingMap<maps::ReprHints<'tcx>>>,
 
     /// Maps Expr NodeId's to their constant qualification.
-    pub const_qualif_map: RefCell<NodeMap<middle::check_const::ConstQualif>>,
+    pub const_qualif_map: RefCell<NodeMap<middle::const_qualif::ConstQualif>>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     pub custom_coerce_unsized_kinds: RefCell<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
@@ -510,6 +510,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
         let interner = RefCell::new(FnvHashMap());
         let common_types = CommonTypes::new(&arenas.type_, &interner);
         let dep_graph = DepGraph::new(s.opts.incremental_compilation);
+        let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
         tls::enter(ctxt {
             arenas: arenas,
             interner: interner,
@@ -532,7 +533,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             adt_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
             super_predicates: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
-            fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
+            fulfilled_predicates: RefCell::new(fulfilled_predicates),
             map: map,
             freevars: RefCell::new(freevars),
             tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
index b902a46fea314083d6a0e4d70c42d218b100a43c..06ea945a09eb3c0b055e179928127de29a688a8a 100644 (file)
@@ -24,7 +24,7 @@
 use front::map::LinkedPath;
 use middle;
 use middle::cstore::{self, CrateStore, LOCAL_CRATE};
-use middle::def::{self, ExportMap};
+use middle::def::{self, Def, ExportMap};
 use middle::def_id::DefId;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::region::{CodeExtent};
@@ -587,7 +587,7 @@ pub struct UpvarBorrow {
 
 #[derive(Copy, Clone)]
 pub struct ClosureUpvar<'tcx> {
-    pub def: def::Def,
+    pub def: Def,
     pub span: Span,
     pub ty: Ty<'tcx>,
 }
@@ -838,6 +838,11 @@ pub fn def_id(&self) -> DefId {
         self.trait_ref.def_id
     }
 
+    /// Creates the dep-node for selecting/evaluating this trait reference.
+    fn dep_node(&self) -> DepNode {
+        DepNode::TraitSelect(self.def_id())
+    }
+
     pub fn input_types(&self) -> &[Ty<'tcx>] {
         self.trait_ref.substs.types.as_slice()
     }
@@ -849,8 +854,14 @@ pub fn self_ty(&self) -> Ty<'tcx> {
 
 impl<'tcx> PolyTraitPredicate<'tcx> {
     pub fn def_id(&self) -> DefId {
+        // ok to skip binder since trait def-id does not care about regions
         self.0.def_id()
     }
+
+    pub fn dep_node(&self) -> DepNode {
+        // ok to skip binder since depnode does not care about regions
+        self.0.dep_node()
+    }
 }
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
@@ -1429,9 +1440,19 @@ fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> {
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum AdtKind { Struct, Enum }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum VariantKind { Struct, Tuple, Unit }
 
+impl VariantKind {
+    pub fn from_variant_data(vdata: &hir::VariantData) -> Self {
+        match *vdata {
+            hir::VariantData::Struct(..) => VariantKind::Struct,
+            hir::VariantData::Tuple(..) => VariantKind::Tuple,
+            hir::VariantData::Unit(..) => VariantKind::Unit,
+        }
+    }
+}
+
 impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
     fn new(tcx: &ctxt<'tcx>,
            did: DefId,
@@ -1575,10 +1596,10 @@ pub fn variant_index_with_id(&self, vid: DefId) -> usize {
             .expect("variant_index_with_id: unknown variant")
     }
 
-    pub fn variant_of_def(&self, def: def::Def) -> &VariantDefData<'tcx, 'container> {
+    pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'tcx, 'container> {
         match def {
-            def::DefVariant(_, vid, _) => self.variant_with_id(vid),
-            def::DefStruct(..) | def::DefTy(..) => self.struct_variant(),
+            Def::Variant(_, vid) => self.variant_with_id(vid),
+            Def::Struct(..) | Def::TyAlias(..) => self.struct_variant(),
             _ => panic!("unexpected def {:?} in variant_of_def", def)
         }
     }
@@ -1924,7 +1945,7 @@ pub fn local_var_name_str(&self, id: NodeId) -> InternedString {
         }
     }
 
-    pub fn resolve_expr(&self, expr: &hir::Expr) -> def::Def {
+    pub fn resolve_expr(&self, expr: &hir::Expr) -> Def {
         match self.def_map.borrow().get(&expr.id) {
             Some(def) => def.full_def(),
             None => {
@@ -1942,15 +1963,15 @@ pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool {
                 // rvalues.
                 match self.def_map.borrow().get(&expr.id) {
                     Some(&def::PathResolution {
-                        base_def: def::DefStatic(..), ..
+                        base_def: Def::Static(..), ..
                     }) | Some(&def::PathResolution {
-                        base_def: def::DefUpvar(..), ..
+                        base_def: Def::Upvar(..), ..
                     }) | Some(&def::PathResolution {
-                        base_def: def::DefLocal(..), ..
+                        base_def: Def::Local(..), ..
                     }) => {
                         true
                     }
-                    Some(&def::PathResolution { base_def: def::DefErr, .. })=> true,
+                    Some(&def::PathResolution { base_def: Def::Err, .. })=> true,
                     Some(..) => false,
                     None => self.sess.span_bug(expr.span, &format!(
                         "no def for path {}", expr.id))
@@ -2612,7 +2633,7 @@ pub enum ExplicitSelfCategory {
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub struct Freevar {
     /// The variable being accessed free.
-    pub def: def::Def,
+    pub def: Def,
 
     // First span where it is accessed (there can be multiple).
     pub span: Span
index 03145951367f9bb6b7614bffad966ddcd6aa5dd0..8cfd27843aee238e135ad022a198c7bf33751633 100644 (file)
@@ -604,7 +604,6 @@ pub struct ImplMethod<'tcx> {
 }
 
 impl<'tcx> ty::ctxt<'tcx> {
-    #[inline(never)] // is this perfy enough?
     pub fn get_impl_method(&self,
                            impl_def_id: DefId,
                            substs: Substs<'tcx>,
index 8496f606b7b87caf8b15e043ee5571786b5e5fe4..3e71d3ba9f397f2e44cf6c4566ad5e956bfd352d 100644 (file)
@@ -683,7 +683,7 @@ pub enum Rvalue<'tcx> {
     Use(Operand<'tcx>),
 
     // [x; 32]
-    Repeat(Operand<'tcx>, Constant<'tcx>),
+    Repeat(Operand<'tcx>, TypedConstVal<'tcx>),
 
     // &x or &mut x
     Ref(Region, BorrowKind, Lvalue<'tcx>),
@@ -891,6 +891,20 @@ pub struct Constant<'tcx> {
     pub literal: Literal<'tcx>,
 }
 
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub struct TypedConstVal<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub span: Span,
+    pub value: ConstVal
+}
+
+impl<'tcx> Debug for TypedConstVal<'tcx> {
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        try!(write!(fmt, "const "));
+        fmt_const_val(fmt, &self.value)
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ItemKind {
     Constant,
index 7c8ea22de8e922a315d42de9bb875ccfb5c6535d..a38ef078c6f8e713592f4de73350d4df3ce10f8a 100644 (file)
@@ -213,9 +213,8 @@ fn super_rvalue(&mut self,
                     }
 
                     Rvalue::Repeat(ref $($mutability)* value,
-                                   ref $($mutability)* len) => {
+                                   _) => {
                         self.visit_operand(value);
-                        self.visit_constant(len);
                     }
 
                     Rvalue::Ref(r, bk, ref $($mutability)* path) => {
index 1f5824f82e486377596c5827d3ba55f67cf729f4..7ad4d3ca708987edd8d43fd52620f158d6fb0ba2 100644 (file)
@@ -124,7 +124,7 @@ fn main() {
     let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
     let y = x.clone();
     x.borrow_mut().s = 6;
-    println!("{}", x.borrow.s);
+    println!("{}", x.borrow().s);
 }
 ```
 
index f26307fd8c58e202a3372e19c4de0c857ae98bfe..70f50b4c042b13c17f75447d974b18e03af602cb 100644 (file)
@@ -24,12 +24,14 @@ pub fn contains(&self, bit: usize) -> bool {
         (self.data[word] & mask) != 0
     }
 
+    /// Returns true if the bit has changed.
     pub fn insert(&mut self, bit: usize) -> bool {
         let (word, mask) = word_mask(bit);
         let data = &mut self.data[word];
         let value = *data;
-        *data = value | mask;
-        (value | mask) != value
+        let new_value = value | mask;
+        *data = new_value;
+        new_value != value
     }
 
     pub fn insert_all(&mut self, all: &BitVector) -> bool {
index 01ffd0efbe3143c4373eec24af55d7af9725a05d..fd5f711c9d6399d189b979a5b13b08892ed154cb 100644 (file)
@@ -34,6 +34,7 @@
 use rustc_plugin as plugin;
 use rustc_front::hir;
 use rustc_front::lowering::{lower_crate, LoweringContext};
+use rustc_passes::{no_asm, loops, consts, const_fn, rvalues, static_recursion};
 use super::Compilation;
 
 use serialize::json;
@@ -632,7 +633,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
     time(time_passes,
          "checking for inline asm in case the target doesn't support it",
-         || ::rustc_passes::no_asm::check_crate(sess, &krate));
+         || no_asm::check_crate(sess, &krate));
 
     // One final feature gating of the true AST that gets compiled
     // later, to make sure we've got everything (e.g. configuration
@@ -649,7 +650,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
 
     time(time_passes,
          "const fn bodies and arguments",
-         || ::rustc_passes::const_fn::check_crate(sess, &krate));
+         || const_fn::check_crate(sess, &krate));
 
     if sess.opts.debugging_opts.input_stats {
         println!("Post-expansion node count: {}", count_nodes(&krate));
@@ -743,11 +744,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     time(time_passes,
          "loop checking",
-         || middle::check_loop::check_crate(sess, krate));
+         || loops::check_crate(sess, krate));
 
     time(time_passes,
          "static item recursion checking",
-         || middle::check_static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map));
+         || static_recursion::check_crate(sess, krate, &def_map.borrow(), &hir_map));
 
     ty::ctxt::create_and_enter(sess,
                                arenas,
@@ -764,7 +765,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    time(time_passes,
                                         "const checking",
-                                        || middle::check_const::check_crate(tcx));
+                                        || consts::check_crate(tcx));
 
                                    let access_levels =
                                        time(time_passes, "privacy checking", || {
@@ -805,7 +806,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
                                    time(time_passes,
                                         "rvalue checking",
-                                        || middle::check_rvalues::check_crate(tcx));
+                                        || rvalues::check_crate(tcx));
 
                                    // Avoid overwhelming user with errors if type checking failed.
                                    // I'm not sure how helpful this is, to be honest, but it avoids
index 81d3367ab00dc97ccccb3b2c2ff564315b51c477..f6342831143256ce0709603d945a7cddc07986cb 100644 (file)
@@ -87,7 +87,8 @@ pub struct LoweringContext<'a> {
     cached_id: Cell<u32>,
     // Keep track of gensym'ed idents.
     gensym_cache: RefCell<HashMap<(NodeId, &'static str), hir::Ident>>,
-    // A copy of cached_id, but is also set to an id while it is being cached.
+    // A copy of cached_id, but is also set to an id while a node is lowered for
+    // the first time.
     gensym_key: Cell<u32>,
 }
 
@@ -114,32 +115,79 @@ pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContex
     }
 
     fn next_id(&self) -> NodeId {
-        let cached = self.cached_id.get();
-        if cached == 0 {
+        let cached_id = self.cached_id.get();
+        if cached_id == 0 {
             return self.id_assigner.next_node_id();
         }
 
-        self.cached_id.set(cached + 1);
-        cached
+        self.cached_id.set(cached_id + 1);
+        cached_id
     }
 
     fn str_to_ident(&self, s: &'static str) -> hir::Ident {
-        let cached_id = self.gensym_key.get();
-        if cached_id == 0 {
+        let gensym_key = self.gensym_key.get();
+        if gensym_key == 0 {
             return hir::Ident::from_name(token::gensym(s));
         }
 
-        let cached = self.gensym_cache.borrow().contains_key(&(cached_id, s));
+        let cached = self.gensym_cache.borrow().contains_key(&(gensym_key, s));
         if cached {
-            self.gensym_cache.borrow()[&(cached_id, s)]
+            self.gensym_cache.borrow()[&(gensym_key, s)]
         } else {
             let result = hir::Ident::from_name(token::gensym(s));
-            self.gensym_cache.borrow_mut().insert((cached_id, s), result);
+            self.gensym_cache.borrow_mut().insert((gensym_key, s), result);
             result
         }
     }
 }
 
+// Utility fn for setting and unsetting the cached id.
+fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
+    where OP: FnOnce(&LoweringContext) -> R
+{
+    // Only reset the id if it was previously 0, i.e., was not cached.
+    // If it was cached, we are in a nested node, but our id count will
+    // still count towards the parent's count.
+    let reset_cached_id = lctx.cached_id.get() == 0;
+    // We always reset gensym_key so that if we use the same name in a nested
+    // node and after that node, they get different values.
+    let old_gensym_key = lctx.gensym_key.get();
+
+    {
+        let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
+
+        if id_cache.contains_key(&expr_id) {
+            let cached_id = lctx.cached_id.get();
+            if cached_id == 0 {
+                // We're entering a node where we need to track ids, but are not
+                // yet tracking.
+                lctx.cached_id.set(id_cache[&expr_id]);
+            } else {
+                // We're already tracking - check that the tracked id is the same
+                // as the expected id.
+                assert!(cached_id == id_cache[&expr_id], "id mismatch");
+            }
+            lctx.gensym_key.set(id_cache[&expr_id]);
+        } else {
+            // We've never lowered this node before, remember it for next time.
+            let next_id = lctx.id_assigner.peek_node_id();
+            id_cache.insert(expr_id, next_id);
+            lctx.gensym_key.set(next_id);
+            // self.cached_id is not set when we lower a node for the first time,
+            // only on re-lowering.
+        }
+    }
+
+    let result = op(lctx);
+
+    if reset_cached_id {
+        lctx.cached_id.set(0);
+    }
+    lctx.gensym_key.set(old_gensym_key);
+
+    result
+}
+
 pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
     hir::Ident {
         name: mtwt::resolve(ident),
@@ -918,47 +966,6 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
     })
 }
 
-// Utility fn for setting and unsetting the cached id.
-fn cache_ids<'a, OP, R>(lctx: &LoweringContext, expr_id: NodeId, op: OP) -> R
-    where OP: FnOnce(&LoweringContext) -> R
-{
-    // Only reset the id if it was previously 0, i.e., was not cached.
-    // If it was cached, we are in a nested node, but our id count will
-    // still count towards the parent's count.
-    let reset_cached_id = lctx.cached_id.get() == 0;
-
-    {
-        let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
-
-        if id_cache.contains_key(&expr_id) {
-            let cached_id = lctx.cached_id.get();
-            if cached_id == 0 {
-                // We're entering a node where we need to track ids, but are not
-                // yet tracking.
-                lctx.cached_id.set(id_cache[&expr_id]);
-                lctx.gensym_key.set(id_cache[&expr_id]);
-            } else {
-                // We're already tracking - check that the tracked id is the same
-                // as the expected id.
-                assert!(cached_id == id_cache[&expr_id], "id mismatch");
-            }
-        } else {
-            let next_id = lctx.id_assigner.peek_node_id();
-            id_cache.insert(expr_id, next_id);
-            lctx.gensym_key.set(next_id);
-        }
-    }
-
-    let result = op(lctx);
-
-    if reset_cached_id {
-        lctx.cached_id.set(0);
-        lctx.gensym_key.set(0);
-    }
-
-    result
-}
-
 pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
     P(hir::Expr {
         id: e.id,
@@ -1935,7 +1942,9 @@ fn test_preserves_ids() {
         let ast_while_let = assigner.fold_expr(ast_while_let);
         let ast_for = quote_expr!(&cx,
                                   for i in 0..10 {
-                                      foo(i);
+                                      for j in 0..10 {
+                                          foo(i, j);
+                                      }
                                   });
         let ast_for = assigner.fold_expr(ast_for);
         let ast_in = quote_expr!(&cx, in HEAP { foo() });
index b5f8be496fb02f451867a5d26e61e2d4ca1f5a39..367475a14a2e6d64e26f60f03bb7758aa3594548 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::def;
+use middle::def::Def;
 use middle::ty;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
@@ -274,7 +274,7 @@ fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         if let &hir::PatIdent(_, ref path1, _) = &p.node {
             let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-            if let Some(def::DefLocal(..)) = def {
+            if let Some(Def::Local(..)) = def {
                 self.check_snake_case(cx, "variable", &path1.node.name.as_str(), Some(p.span));
             }
         }
@@ -362,7 +362,7 @@ fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
-            (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
+            (&hir::PatIdent(_, ref path1, _), Some(Def::Const(..))) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
                                                       path1.node.name, p.span);
             }
index 8985b1e56bc0097a2679137adc5c81b7c74046d4..9e3ca70e5e42d701c8aa287d46f8081fe064b4fa 100644 (file)
@@ -28,7 +28,8 @@
 //! Use the former for unit-like structs and the latter for structs with
 //! a `pub fn new()`.
 
-use middle::{cfg, def, infer, stability, traits};
+use middle::{cfg, infer, stability, traits};
+use middle::def::Def;
 use middle::cstore::CrateStore;
 use middle::def_id::DefId;
 use middle::subst::Substs;
@@ -163,7 +164,7 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
                 }
                 let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
                 if let Some(def_id) = cx.tcx.map.opt_local_def_id(fieldpat.node.pat.id) {
-                    def == Some(def::DefLocal(def_id, fieldpat.node.pat.id))
+                    def == Some(Def::Local(def_id, fieldpat.node.pat.id))
                 } else {
                     false
                 }
@@ -819,7 +820,7 @@ fn expr_refers_to_this_method(tcx: &ty::ctxt,
             match tcx.map.get(id) {
                 hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
                     match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) {
-                        Some(def::DefMethod(def_id)) => {
+                        Some(Def::Method(def_id)) => {
                             let item_substs =
                                 tcx.tables.borrow().item_substs
                                                    .get(&callee.id)
@@ -854,9 +855,7 @@ fn method_call_refers_to_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                 // A trait method, from any number of possible sources.
                 // Attempt to select a concrete impl before checking.
                 ty::TraitContainer(trait_def_id) => {
-                    let trait_substs = callee_substs.clone().method_to_trait();
-                    let trait_substs = tcx.mk_substs(trait_substs);
-                    let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
+                    let trait_ref = callee_substs.to_trait_ref(tcx, trait_def_id);
                     let trait_ref = ty::Binder(trait_ref);
                     let span = tcx.map.span(expr_id);
                     let obligation =
@@ -1060,7 +1059,7 @@ fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
                 hir::ExprPath(..) => (),
                 _ => return None
             }
-            if let def::DefFn(did, _) = cx.tcx.resolve_expr(expr) {
+            if let Def::Fn(did) = cx.tcx.resolve_expr(expr) {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
index 8c3bd3c4f8a5352851b919077ad90224bc70c425..e91c7e6ac450687f7584e92377619d60bf814e34 100644 (file)
@@ -29,8 +29,8 @@
 use middle::cstore::{InlinedItem, InlinedItemRef};
 use middle::ty::adjustment;
 use middle::ty::cast;
-use middle::check_const::ConstQualif;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::privacy::{AllPublic, LastMod};
 use middle::region;
@@ -368,49 +368,48 @@ fn decode_ast(par_doc: rbml::Doc) -> InlinedItem {
 // ______________________________________________________________________
 // Encoding and decoding of ast::def
 
-fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> def::Def {
-    let def: def::Def = Decodable::decode(dsr).unwrap();
+fn decode_def(dcx: &DecodeContext, dsr: &mut reader::Decoder) -> Def {
+    let def: Def = Decodable::decode(dsr).unwrap();
     def.tr(dcx)
 }
 
-impl tr for def::Def {
-    fn tr(&self, dcx: &DecodeContext) -> def::Def {
+impl tr for Def {
+    fn tr(&self, dcx: &DecodeContext) -> Def {
         match *self {
-          def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
-          def::DefMethod(did) => def::DefMethod(did.tr(dcx)),
-          def::DefSelfTy(opt_did, impl_ids) => { def::DefSelfTy(opt_did.map(|did| did.tr(dcx)),
+          Def::Fn(did) => Def::Fn(did.tr(dcx)),
+          Def::Method(did) => Def::Method(did.tr(dcx)),
+          Def::SelfTy(opt_did, impl_ids) => { Def::SelfTy(opt_did.map(|did| did.tr(dcx)),
                                                                 impl_ids.map(|(nid1, nid2)| {
                                                                     (dcx.tr_id(nid1),
                                                                      dcx.tr_id(nid2))
                                                                 })) }
-          def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
-          def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
-          def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
-          def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
-          def::DefAssociatedConst(did) => def::DefAssociatedConst(did.tr(dcx)),
-          def::DefLocal(_, nid) => {
+          Def::Mod(did) => { Def::Mod(did.tr(dcx)) }
+          Def::ForeignMod(did) => { Def::ForeignMod(did.tr(dcx)) }
+          Def::Static(did, m) => { Def::Static(did.tr(dcx), m) }
+          Def::Const(did) => { Def::Const(did.tr(dcx)) }
+          Def::AssociatedConst(did) => Def::AssociatedConst(did.tr(dcx)),
+          Def::Local(_, nid) => {
               let nid = dcx.tr_id(nid);
               let did = dcx.tcx.map.local_def_id(nid);
-              def::DefLocal(did, nid)
+              Def::Local(did, nid)
           }
-          def::DefVariant(e_did, v_did, is_s) => {
-            def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
-          },
-          def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
-          def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
-          def::DefAssociatedTy(trait_did, did) =>
-              def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
-          def::DefPrimTy(p) => def::DefPrimTy(p),
-          def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
-          def::DefUpvar(_, nid1, index, nid2) => {
+          Def::Variant(e_did, v_did) => Def::Variant(e_did.tr(dcx), v_did.tr(dcx)),
+          Def::Trait(did) => Def::Trait(did.tr(dcx)),
+          Def::Enum(did) => Def::Enum(did.tr(dcx)),
+          Def::TyAlias(did) => Def::TyAlias(did.tr(dcx)),
+          Def::AssociatedTy(trait_did, did) =>
+              Def::AssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
+          Def::PrimTy(p) => Def::PrimTy(p),
+          Def::TyParam(s, index, def_id, n) => Def::TyParam(s, index, def_id.tr(dcx), n),
+          Def::Upvar(_, nid1, index, nid2) => {
               let nid1 = dcx.tr_id(nid1);
               let nid2 = dcx.tr_id(nid2);
               let did1 = dcx.tcx.map.local_def_id(nid1);
-              def::DefUpvar(did1, nid1, index, nid2)
+              Def::Upvar(did1, nid1, index, nid2)
           }
-          def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
-          def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid)),
-          def::DefErr => def::DefErr,
+          Def::Struct(did) => Def::Struct(did.tr(dcx)),
+          Def::Label(nid) => Def::Label(dcx.tr_id(nid)),
+          Def::Err => Def::Err,
         }
     }
 }
index ecbc84023309105f9953e0a7babf1a36c43e79d5..802629e8f3e8b8d49c1dbd11485a9eb6f6fdce83 100644 (file)
@@ -18,7 +18,7 @@
 use middle::cstore::{NativeLibraryKind, LinkMeta, LinkagePreference};
 use middle::def;
 use middle::lang_items;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, VariantKind};
 use middle::def_id::{DefId, DefIndex};
 
 use rustc::front::map as hir_map;
@@ -377,6 +377,17 @@ fn def_path(&self, def: DefId) -> hir_map::DefPath
         local_path.into_iter().chain(path).collect()
     }
 
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> {
+        let cdata = self.get_crate_data(def_id.krate);
+        decoder::get_variant_kind(&cdata, def_id.index)
+    }
+
+    fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
+    {
+        let cdata = self.get_crate_data(struct_def_id.krate);
+        decoder::get_struct_ctor_def_id(&cdata, struct_def_id.index)
+    }
+
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
     {
         let cdata = self.get_crate_data(did.krate);
index def5897e92d9d8aa8d1161ad84577c95315382c0..bca8cb3995ab1ed341b0c2f82615127f819f65ab 100644 (file)
 
 use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
 use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
-use middle::ty::{self, Ty, TypeFoldable};
+use middle::ty::{self, Ty, TypeFoldable, VariantKind};
 
 use rustc::mir;
 use rustc::mir::visit::MutVisitor;
@@ -89,27 +89,22 @@ pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
     index::DenseIndex::from_buf(index.data, index.start, index.end)
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 enum Family {
     ImmStatic,             // c
     MutStatic,             // b
     Fn,                    // f
-    CtorFn,                // o
     StaticMethod,          // F
     Method,                // h
     Type,                  // y
     Mod,                   // m
     ForeignMod,            // n
     Enum,                  // t
-    StructVariant,         // V
-    TupleVariant,          // v
-    UnitVariant,           // w
+    Variant(VariantKind),  // V, v, w
     Impl,                  // i
     DefaultImpl,           // d
     Trait,                 // I
-    Struct,                // S
-    TupleStruct,           // s
-    UnitStruct,            // u
+    Struct(VariantKind),   // S, s, u
     PublicField,           // g
     InheritedField,        // N
     Constant,              // C
@@ -122,22 +117,21 @@ fn item_family(item: rbml::Doc) -> Family {
       'c' => ImmStatic,
       'b' => MutStatic,
       'f' => Fn,
-      'o' => CtorFn,
       'F' => StaticMethod,
       'h' => Method,
       'y' => Type,
       'm' => Mod,
       'n' => ForeignMod,
       't' => Enum,
-      'V' => StructVariant,
-      'v' => TupleVariant,
-      'w' => UnitVariant,
+      'V' => Variant(VariantKind::Struct),
+      'v' => Variant(VariantKind::Tuple),
+      'w' => Variant(VariantKind::Unit),
       'i' => Impl,
       'd' => DefaultImpl,
       'I' => Trait,
-      'S' => Struct,
-      's' => TupleStruct,
-      'u' => UnitStruct,
+      'S' => Struct(VariantKind::Struct),
+      's' => Struct(VariantKind::Tuple),
+      'u' => Struct(VariantKind::Unit),
       'g' => PublicField,
       'N' => InheritedField,
        c => panic!("unexpected family char: {}", c)
@@ -271,6 +265,18 @@ fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
     }
 }
 
+fn family_to_variant_kind<'tcx>(family: Family) -> Option<ty::VariantKind> {
+    match family {
+        Struct(VariantKind::Struct) | Variant(VariantKind::Struct) =>
+            Some(ty::VariantKind::Struct),
+        Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) =>
+            Some(ty::VariantKind::Tuple),
+        Struct(VariantKind::Unit) | Variant(VariantKind::Unit) =>
+            Some(ty::VariantKind::Unit),
+        _ => None,
+    }
+}
+
 fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
     let fam = item_family(item);
     match fam {
@@ -278,42 +284,37 @@ fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
             // Check whether we have an associated const item.
             match item_sort(item) {
                 Some('C') | Some('c') => {
-                    DlDef(def::DefAssociatedConst(did))
+                    DlDef(Def::AssociatedConst(did))
                 }
                 _ => {
                     // Regular const item.
-                    DlDef(def::DefConst(did))
+                    DlDef(Def::Const(did))
                 }
             }
         }
-        ImmStatic => DlDef(def::DefStatic(did, false)),
-        MutStatic => DlDef(def::DefStatic(did, true)),
-        Struct | TupleStruct | UnitStruct => DlDef(def::DefStruct(did)),
-        Fn        => DlDef(def::DefFn(did, false)),
-        CtorFn    => DlDef(def::DefFn(did, true)),
+        ImmStatic => DlDef(Def::Static(did, false)),
+        MutStatic => DlDef(Def::Static(did, true)),
+        Struct(..) => DlDef(Def::Struct(did)),
+        Fn        => DlDef(Def::Fn(did)),
         Method | StaticMethod => {
-            DlDef(def::DefMethod(did))
+            DlDef(Def::Method(did))
         }
         Type => {
             if item_sort(item) == Some('t') {
                 let trait_did = item_require_parent_item(cdata, item);
-                DlDef(def::DefAssociatedTy(trait_did, did))
+                DlDef(Def::AssociatedTy(trait_did, did))
             } else {
-                DlDef(def::DefTy(did, false))
+                DlDef(Def::TyAlias(did))
             }
         }
-        Mod => DlDef(def::DefMod(did)),
-        ForeignMod => DlDef(def::DefForeignMod(did)),
-        StructVariant => {
+        Mod => DlDef(Def::Mod(did)),
+        ForeignMod => DlDef(Def::ForeignMod(did)),
+        Variant(..) => {
             let enum_did = item_require_parent_item(cdata, item);
-            DlDef(def::DefVariant(enum_did, did, true))
+            DlDef(Def::Variant(enum_did, did))
         }
-        TupleVariant | UnitVariant => {
-            let enum_did = item_require_parent_item(cdata, item);
-            DlDef(def::DefVariant(enum_did, did, false))
-        }
-        Trait => DlDef(def::DefTrait(did)),
-        Enum => DlDef(def::DefTy(did, true)),
+        Trait => DlDef(Def::Trait(did)),
+        Enum => DlDef(Def::Enum(did)),
         Impl | DefaultImpl => DlImpl(did),
         PublicField | InheritedField => DlField,
     }
@@ -371,11 +372,9 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                          item_id: DefIndex,
                          tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
 {
-    fn family_to_variant_kind<'tcx>(family: Family, tcx: &ty::ctxt<'tcx>) -> ty::VariantKind {
-        match family {
-            Struct | StructVariant => ty::VariantKind::Struct,
-            TupleStruct | TupleVariant => ty::VariantKind::Tuple,
-            UnitStruct | UnitVariant => ty::VariantKind::Unit,
+    fn expect_variant_kind<'tcx>(family: Family, tcx: &ty::ctxt<'tcx>) -> ty::VariantKind {
+        match family_to_variant_kind(family) {
+            Some(kind) => kind,
             _ => tcx.sess.bug(&format!("unexpected family: {:?}", family)),
         }
     }
@@ -399,7 +398,7 @@ fn get_enum_variants<'tcx>(intr: &IdentInterner,
                 name: item_name(intr, item),
                 fields: get_variant_fields(intr, cdata, item, tcx),
                 disr_val: disr,
-                kind: family_to_variant_kind(item_family(item), tcx),
+                kind: expect_variant_kind(item_family(item), tcx),
             }
         }).collect()
     }
@@ -433,7 +432,7 @@ fn get_struct_variant<'tcx>(intr: &IdentInterner,
             name: item_name(intr, doc),
             fields: get_variant_fields(intr, cdata, doc, tcx),
             disr_val: 0,
-            kind: family_to_variant_kind(item_family(doc), tcx),
+            kind: expect_variant_kind(item_family(doc), tcx),
         }
     }
 
@@ -444,7 +443,7 @@ fn get_struct_variant<'tcx>(intr: &IdentInterner,
             (ty::AdtKind::Enum,
              get_enum_variants(intr, cdata, doc, tcx))
         }
-        Struct | TupleStruct | UnitStruct => {
+        Struct(..) => {
             let ctor_did =
                 reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
                 map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
@@ -1086,6 +1085,19 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
     }).collect()
 }
 
+pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option<VariantKind>
+{
+    let item = cdata.lookup_item(node_id);
+    family_to_variant_kind(item_family(item))
+}
+
+pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option<DefId>
+{
+    let item = cdata.lookup_item(node_id);
+    reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).
+        map(|ctor_doc| translated_def_id(cdata, ctor_doc))
+}
+
 /// If node_id is the constructor of a tuple struct, retrieve the NodeId of
 /// the actual type definition, otherwise, return None
 pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
index ec70a610e0b3afecc7c03e690228f0b5ebad496d..45cbb22e6c95270f3e736125f42364efa5b69148 100644 (file)
@@ -508,15 +508,20 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                          rbml_w: &mut Encoder,
                                          name: Name,
-                                         ctor_id: NodeId,
+                                         struct_def: &hir::VariantData,
                                          index: &mut CrateIndex<'tcx>,
                                          struct_id: NodeId) {
+    let ctor_id = struct_def.id();
     let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
 
     index.record(ctor_def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
     encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
-    encode_family(rbml_w, 'o');
+    encode_family(rbml_w, match *struct_def {
+        hir::VariantData::Struct(..) => 'S',
+        hir::VariantData::Tuple(..) => 's',
+        hir::VariantData::Unit(..) => 'u',
+    });
     encode_bounds_and_type_for_item(rbml_w, ecx, index, ctor_id);
     encode_name(rbml_w, name);
     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
@@ -1084,7 +1089,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
         // If this is a tuple-like struct, encode the type of the constructor.
         if !struct_def.is_struct() {
-            encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id(), index, item.id);
+            encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def, index, item.id);
         }
       }
       hir::ItemDefaultImpl(unsafety, _) => {
index 40665beaa5ac2698b08c92e6107ad139cef5ff17..b0fb12b26b28f96e778c9367a2d5fe7229198e3a 100644 (file)
@@ -388,11 +388,12 @@ fn find_library_crate(&mut self) -> Option<Library> {
         }
 
         let dypair = self.dylibname();
+        let staticpair = self.staticlibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
         let dylib_prefix = format!("{}{}", dypair.0, self.crate_name);
         let rlib_prefix = format!("lib{}", self.crate_name);
-        let staticlib_prefix = format!("lib{}", self.crate_name);
+        let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name);
 
         let mut candidates = HashMap::new();
         let mut staticlibs = vec!();
@@ -425,7 +426,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
                  false)
             } else {
                 if file.starts_with(&staticlib_prefix[..]) &&
-                   file.ends_with(".a") {
+                   file.ends_with(&staticpair.1) {
                     staticlibs.push(CrateMismatch {
                         path: path.to_path_buf(),
                         got: "static".to_string()
@@ -644,6 +645,13 @@ fn dylibname(&self) -> (String, String) {
         (t.options.dll_prefix.clone(), t.options.dll_suffix.clone())
     }
 
+    // Returns the corresponding (prefix, suffix) that files need to have for
+    // static libraries
+    fn staticlibname(&self) -> (String, String) {
+        let t = &self.target;
+        (t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone())
+    }
+
     fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
         // First, filter out all libraries that look suspicious. We only accept
         // files which actually exist that have the correct naming scheme for
index 2f57dd22454cb50c3841216fe1512b27e86fd6df..c389e8e7330917f7d88dba8fce39998b93d1e2ac 100644 (file)
@@ -44,7 +44,6 @@ fn expr_as_rvalue(&mut self,
             }
             ExprKind::Repeat { value, count } => {
                 let value_operand = unpack!(block = this.as_operand(block, value));
-                let count = this.as_constant(count);
                 block.and(Rvalue::Repeat(value_operand, count))
             }
             ExprKind::Borrow { region, borrow_kind, arg } => {
index 63eb760720479a750d90779fa96a21c135332975..4261efe8215a8190f478c42d4779727e6c1592d3 100644 (file)
@@ -146,11 +146,13 @@ pub fn into_expr(&mut self,
                 // start the loop
                 this.cfg.terminate(block, Terminator::Goto { target: loop_block });
 
-                this.in_loop_scope(loop_block, exit_block, |this| {
+                let might_break = this.in_loop_scope(loop_block, exit_block, move |this| {
                     // conduct the test, if necessary
                     let body_block;
-                    let opt_cond_expr = opt_cond_expr; // FIXME rustc bug
                     if let Some(cond_expr) = opt_cond_expr {
+                        // This loop has a condition, ergo its exit_block is reachable.
+                        this.find_loop_scope(expr_span, None).might_break = true;
+
                         let loop_block_end;
                         let cond = unpack!(loop_block_end = this.as_operand(loop_block, cond_expr));
                         body_block = this.cfg.start_new_block();
@@ -163,21 +165,22 @@ pub fn into_expr(&mut self,
                         body_block = loop_block;
                     }
 
-                    // execute the body, branching back to the test
-                    // We write body’s “return value” into the destination of loop. This is fine,
-                    // because:
-                    //
-                    // * In Rust both loop expression and its body are required to have `()`
-                    //   as the “return value”;
-                    // * The destination will be considered uninitialised (given it was
-                    //   uninitialised before the loop) during the first iteration, thus
-                    //   disallowing its use inside the body. Alternatively, if it was already
-                    //   initialised, the `destination` can only possibly have a value of `()`,
-                    //   therefore, “mutating” the destination during iteration is fine.
-                    let body_block_end = unpack!(this.into(destination, body_block, body));
+                    // The “return” value of the loop body must always be an unit, but we cannot
+                    // reuse that as a “return” value of the whole loop expressions, because some
+                    // loops are diverging (e.g. `loop {}`). Thus, we introduce a unit temporary as
+                    // the destination for the loop body and assign the loop’s own “return” value
+                    // immediately after the iteration is finished.
+                    let tmp = this.get_unit_temp();
+                    // Execute the body, branching back to the test.
+                    let body_block_end = unpack!(this.into(&tmp, body_block, body));
                     this.cfg.terminate(body_block_end, Terminator::Goto { target: loop_block });
-                    exit_block.unit()
-                })
+                });
+                // If the loop may reach its exit_block, we assign an empty tuple to the
+                // destination to keep the MIR well-formed.
+                if might_break {
+                    this.cfg.push_assign_unit(exit_block, expr_span, destination);
+                }
+                exit_block.unit()
             }
             ExprKind::Assign { lhs, rhs } => {
                 // Note: we evaluate assignments right-to-left. This
@@ -217,7 +220,10 @@ pub fn into_expr(&mut self,
                                        |loop_scope| loop_scope.continue_block)
             }
             ExprKind::Break { label } => {
-                this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
+                this.break_or_continue(expr_span, label, block, |loop_scope| {
+                    loop_scope.might_break = true;
+                    loop_scope.break_block
+                })
             }
             ExprKind::Return { value } => {
                 block = match value {
@@ -303,11 +309,13 @@ fn break_or_continue<F>(&mut self,
                             block: BasicBlock,
                             exit_selector: F)
                             -> BlockAnd<()>
-        where F: FnOnce(&LoopScope) -> BasicBlock
+        where F: FnOnce(&mut LoopScope) -> BasicBlock
     {
-        let loop_scope = self.find_loop_scope(span, label);
-        let exit_block = exit_selector(&loop_scope);
-        self.exit_scope(span, loop_scope.extent, block, exit_block);
+        let (exit_block, extent) = {
+            let loop_scope = self.find_loop_scope(span, label);
+            (exit_selector(loop_scope), loop_scope.extent)
+        };
+        self.exit_scope(span, extent, block, exit_block);
         self.cfg.start_new_block().unit()
     }
 }
index d217eb066479364de370bdc536bb7d96c3d091f0..a7459d62368e9cfa6e5f72b694f3deace3b93854 100644 (file)
@@ -26,6 +26,7 @@ pub struct Builder<'a, 'tcx: 'a> {
     var_decls: Vec<VarDecl<'tcx>>,
     var_indices: FnvHashMap<ast::NodeId, u32>,
     temp_decls: Vec<TempDecl<'tcx>>,
+    unit_temp: Option<Lvalue<'tcx>>,
 }
 
 struct CFG<'tcx> {
@@ -96,6 +97,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
         temp_decls: vec![],
         var_decls: vec![],
         var_indices: FnvHashMap(),
+        unit_temp: None
     };
 
     assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
@@ -156,6 +158,18 @@ fn args_and_body(&mut self,
             block.and(arg_decls)
         })
     }
+
+    fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
+        match self.unit_temp {
+            Some(ref tmp) => tmp.clone(),
+            None => {
+                let ty = self.hir.unit_ty();
+                let tmp = self.temp(ty);
+                self.unit_temp = Some(tmp.clone());
+                tmp
+            }
+        }
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
index 90d6a90682f6eb1680cd467d1730a56fa6e0ed47..dae525c84d033f53f4018d4dcb7bca201df50f0c 100644 (file)
@@ -103,31 +103,41 @@ pub struct Scope<'tcx> {
 
 #[derive(Clone, Debug)]
 pub struct LoopScope {
-    pub extent: CodeExtent, // extent of the loop
-    pub continue_block: BasicBlock, // where to go on a `loop`
+    /// Extent of the loop
+    pub extent: CodeExtent,
+    /// Where the body of the loop begins
+    pub continue_block: BasicBlock,
+    /// Block to branch into when the loop terminates (either by being `break`-en out from, or by
+    /// having its condition to become false)
     pub break_block: BasicBlock, // where to go on a `break
+    /// Indicates the reachability of the break_block for this loop
+    pub might_break: bool
 }
 
 impl<'a,'tcx> Builder<'a,'tcx> {
     /// Start a loop scope, which tracks where `continue` and `break`
     /// should branch to. See module comment for more details.
-    pub fn in_loop_scope<F, R>(&mut self,
+    ///
+    /// Returns the might_break attribute of the LoopScope used.
+    pub fn in_loop_scope<F>(&mut self,
                                loop_block: BasicBlock,
                                break_block: BasicBlock,
                                f: F)
-                               -> BlockAnd<R>
-        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
+                               -> bool
+        where F: FnOnce(&mut Builder<'a, 'tcx>)
     {
         let extent = self.extent_of_innermost_scope();
         let loop_scope = LoopScope {
             extent: extent.clone(),
             continue_block: loop_block,
             break_block: break_block,
+            might_break: false
         };
         self.loop_scopes.push(loop_scope);
-        let r = f(self);
-        assert!(self.loop_scopes.pop().unwrap().extent == extent);
-        r
+        f(self);
+        let loop_scope = self.loop_scopes.pop().unwrap();
+        assert!(loop_scope.extent == extent);
+        loop_scope.might_break
     }
 
     /// Convenience wrapper that pushes a scope and then executes `f`
@@ -181,28 +191,21 @@ pub fn pop_scope(&mut self, extent: CodeExtent, block: BasicBlock) {
     pub fn find_loop_scope(&mut self,
                            span: Span,
                            label: Option<CodeExtent>)
-                           -> LoopScope {
-        let loop_scope =
-            match label {
-                None => {
-                    // no label? return the innermost loop scope
-                    self.loop_scopes.iter()
-                                    .rev()
-                                    .next()
-                }
-                Some(label) => {
-                    // otherwise, find the loop-scope with the correct id
-                    self.loop_scopes.iter()
-                                    .rev()
-                                    .filter(|loop_scope| loop_scope.extent == label)
-                                    .next()
-                }
-            };
-
-        match loop_scope {
-            Some(loop_scope) => loop_scope.clone(),
-            None => self.hir.span_bug(span, "no enclosing loop scope found?"),
-        }
+                           -> &mut LoopScope {
+        let Builder { ref mut loop_scopes, ref mut hir, .. } = *self;
+        match label {
+            None => {
+                // no label? return the innermost loop scope
+                loop_scopes.iter_mut().rev().next()
+            }
+            Some(label) => {
+                // otherwise, find the loop-scope with the correct id
+                loop_scopes.iter_mut()
+                           .rev()
+                           .filter(|loop_scope| loop_scope.extent == label)
+                           .next()
+            }
+        }.unwrap_or_else(|| hir.span_bug(span, "no enclosing loop scope found?"))
     }
 
     /// Branch out of `block` to `target`, exiting all scopes up to
@@ -214,20 +217,19 @@ pub fn exit_scope(&mut self,
                       extent: CodeExtent,
                       block: BasicBlock,
                       target: BasicBlock) {
-        let popped_scopes =
-            match self.scopes.iter().rev().position(|scope| scope.extent == extent) {
-                Some(p) => p + 1,
-                None => self.hir.span_bug(span, &format!("extent {:?} does not enclose",
-                                                              extent)),
-            };
-
-        for scope in self.scopes.iter_mut().rev().take(popped_scopes) {
+        let Builder { ref mut scopes, ref mut cfg, ref mut hir, .. } = *self;
+
+        let scope_count = 1 + scopes.iter().rev().position(|scope| scope.extent == extent)
+                                                 .unwrap_or_else(||{
+            hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
+        });
+
+        for scope in scopes.iter_mut().rev().take(scope_count) {
             for &(kind, drop_span, ref lvalue) in &scope.drops {
-                self.cfg.push_drop(block, drop_span, kind, lvalue);
+                cfg.push_drop(block, drop_span, kind, lvalue);
             }
         }
-
-        self.cfg.terminate(block, Terminator::Goto { target: target });
+        cfg.terminate(block, Terminator::Goto { target: target });
     }
 
     /// Creates a path that performs all required cleanup for unwinding.
index 8090fca66bb6247904341cb8f1de0cd3bb5e33a4..d8a1930fd5c046688854f548f9239bbcbd10efe1 100644 (file)
@@ -14,7 +14,8 @@
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
 use rustc::front::map;
-use rustc::middle::def;
+use rustc::middle::def::Def;
+use rustc::middle::const_eval;
 use rustc::middle::region::CodeExtent;
 use rustc::middle::pat_util;
 use rustc::middle::ty::{self, VariantDef, Ty};
@@ -67,10 +68,10 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                         // Tuple-like ADTs are represented as ExprCall. We convert them here.
                         expr_ty.ty_adt_def().and_then(|adt_def|{
                             match cx.tcx.def_map.borrow()[&fun.id].full_def() {
-                                def::DefVariant(_, variant_id, false) => {
+                                Def::Variant(_, variant_id) => {
                                     Some((adt_def, adt_def.variant_index_with_id(variant_id)))
                                 },
-                                def::DefStruct(_) => {
+                                Def::Struct(..) => {
                                     Some((adt_def, 0))
                                 },
                                 _ => None
@@ -231,7 +232,7 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
                     }
                     ty::TyEnum(adt, substs) => {
                         match cx.tcx.def_map.borrow()[&self.id].full_def() {
-                            def::DefVariant(enum_id, variant_id, _) => {
+                            Def::Variant(enum_id, variant_id) => {
                                 debug_assert!(adt.did == enum_id);
                                 let index = adt.variant_index_with_id(variant_id);
                                 let field_refs = field_refs(&adt.variants[index], fields);
@@ -325,14 +326,11 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
 
             hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat {
                 value: v.to_ref(),
-                count: Expr {
+                count: TypedConstVal {
                     ty: cx.tcx.expr_ty(c),
-                    temp_lifetime: None,
                     span: c.span,
-                    kind: ExprKind::Literal {
-                        literal: cx.const_eval_literal(c)
-                    }
-                }.to_ref()
+                    value: const_eval::eval_const_expr(cx.tcx, c)
+                }
             },
             hir::ExprRet(ref v) =>
                 ExprKind::Return { value: v.to_ref() },
@@ -573,9 +571,9 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
     let (def_id, kind) = match def {
         // A regular function.
-        def::DefFn(def_id, _) => (def_id, ItemKind::Function),
-        def::DefMethod(def_id) => (def_id, ItemKind::Method),
-        def::DefStruct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
+        Def::Fn(def_id) => (def_id, ItemKind::Function),
+        Def::Method(def_id) => (def_id, ItemKind::Method),
+        Def::Struct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A tuple-struct constructor. Should only be reached if not called in the same
             // expression.
             ty::TyBareFn(..) => (def_id, ItemKind::Function),
@@ -590,7 +588,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             },
             ref sty => panic!("unexpected sty: {:?}", sty)
         },
-        def::DefVariant(enum_id, variant_id, false) => match cx.tcx.node_id_to_type(expr.id).sty {
+        Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A variant constructor. Should only be reached if not called in the same
             // expression.
             ty::TyBareFn(..) => (variant_id, ItemKind::Function),
@@ -608,8 +606,8 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             },
             ref sty => panic!("unexpected sty: {:?}", sty)
         },
-        def::DefConst(def_id) |
-        def::DefAssociatedConst(def_id) => {
+        Def::Const(def_id) |
+        Def::AssociatedConst(def_id) => {
             if let Some(v) = cx.try_const_eval_literal(expr) {
                 return ExprKind::Literal { literal: v };
             } else {
@@ -617,12 +615,12 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
             }
         }
 
-        def::DefStatic(node_id, _) => return ExprKind::StaticRef {
+        Def::Static(node_id, _) => return ExprKind::StaticRef {
             id: node_id,
         },
 
-        def @ def::DefLocal(..) |
-        def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
+        def @ Def::Local(..) |
+        def @ Def::Upvar(..) => return convert_var(cx, expr, def),
 
         def =>
             cx.tcx.sess.span_bug(
@@ -636,18 +634,18 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
 
 fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                              expr: &'tcx hir::Expr,
-                             def: def::Def)
+                             def: Def)
                              -> ExprKind<'tcx> {
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
 
     match def {
-        def::DefLocal(_, node_id) => {
+        Def::Local(_, node_id) => {
             ExprKind::VarRef {
                 id: node_id,
             }
         }
 
-        def::DefUpvar(_, id_var, index, closure_expr_id) => {
+        Def::Upvar(_, id_var, index, closure_expr_id) => {
             debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id);
             let var_ty = cx.tcx.node_id_to_type(id_var);
 
@@ -922,7 +920,7 @@ fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
 
 fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> CodeExtent {
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
-        Some(def::DefLabel(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
+        Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
             cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
         }
index b49dc6d89624265d68b6f82c396acbc75065efbc..7019b40bb252117b73efa8e8ce4c5168b42474dd 100644 (file)
@@ -58,6 +58,10 @@ pub fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
+    pub fn unit_ty(&mut self) -> Ty<'tcx> {
+        self.tcx.mk_nil()
+    }
+
     pub fn str_literal(&mut self, value: token::InternedString) -> Literal<'tcx> {
         Literal::Value { value: ConstVal::Str(value) }
     }
index dc377ac731a6581ddf9346c4c7e1cebfb37d61ed..e1a533ce42cca8f7308b49dcf7051c79113f1fb9 100644 (file)
@@ -12,7 +12,7 @@
 use hair::cx::Cx;
 use rustc_data_structures::fnv::FnvHashMap;
 use rustc::middle::const_eval;
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
 use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr::*;
@@ -84,7 +84,7 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
             {
                 let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
                 match def {
-                    def::DefConst(def_id) | def::DefAssociatedConst(def_id) =>
+                    Def::Const(def_id) | Def::AssociatedConst(def_id) =>
                         match const_eval::lookup_const_by_id(self.cx.tcx, def_id,
                                                              Some(pat.id), None) {
                             Some(const_expr) => {
@@ -290,7 +290,7 @@ fn variant_or_leaf(&mut self,
                        -> PatternKind<'tcx> {
         let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
         match def {
-            def::DefVariant(enum_id, variant_id, _) => {
+            Def::Variant(enum_id, variant_id) => {
                 let adt_def = self.cx.tcx.lookup_adt_def(enum_id);
                 if adt_def.variants.len() > 1 {
                     PatternKind::Variant {
@@ -303,9 +303,7 @@ fn variant_or_leaf(&mut self,
                 }
             }
 
-            // NB: resolving to DefStruct means the struct *constructor*,
-            // not the struct as a type.
-            def::DefStruct(..) | def::DefTy(..) => {
+            Def::Struct(..) | Def::TyAlias(..) => {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
index fb81cc7e6d97a4394d65702fbf809466616046d0..d87b25a094e2f0fc5fd5e7664516fff95ce6d784 100644 (file)
@@ -14,7 +14,8 @@
 //! unit-tested and separated from the Rust source and compiler data
 //! structures.
 
-use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind};
+use rustc::mir::repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp, ItemKind,
+    TypedConstVal};
 use rustc::middle::const_eval::ConstVal;
 use rustc::middle::def_id::DefId;
 use rustc::middle::region::CodeExtent;
@@ -213,10 +214,7 @@ pub enum ExprKind<'tcx> {
     },
     Repeat {
         value: ExprRef<'tcx>,
-        // FIXME(#29789): Add a separate hair::Constant<'tcx> so this could be more explicit about
-        // its contained data. Currently this should only contain expression of ExprKind::Literal
-        // kind.
-        count: ExprRef<'tcx>,
+        count: TypedConstVal<'tcx>,
     },
     Vec {
         fields: Vec<ExprRef<'tcx>>,
index 9679654d958e9a24e202443a272f5a52e762a9f8..66604786d467ffe4ef7073fd07c602c71c9e0737 100644 (file)
@@ -143,9 +143,9 @@ fn erase_regions_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) {
             Rvalue::Use(ref mut operand) => {
                 self.erase_regions_operand(operand)
             }
-            Rvalue::Repeat(ref mut operand, ref mut constant) => {
+            Rvalue::Repeat(ref mut operand, ref mut value) => {
                 self.erase_regions_operand(operand);
-                self.erase_regions_constant(constant);
+                value.ty = self.tcx.erase_regions(&value.ty);
             }
             Rvalue::Ref(ref mut region, _, ref mut lvalue) => {
                 *region = ty::ReStatic;
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
new file mode 100644 (file)
index 0000000..60cc658
--- /dev/null
@@ -0,0 +1,916 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Verifies that the types and values of const and static items
+// are safe. The rules enforced by this module are:
+//
+// - For each *mutable* static item, it checks that its **type**:
+//     - doesn't have a destructor
+//     - doesn't own a box
+//
+// - For each *immutable* static item, it checks that its **value**:
+//       - doesn't own a box
+//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
+//           - the type of the struct/enum has a dtor
+//
+// Rules Enforced Elsewhere:
+// - It's not possible to take the address of a static item with unsafe interior. This is enforced
+// by borrowck::gather_loans
+
+use rustc::dep_graph::DepNode;
+use rustc::middle::ty::cast::{CastKind};
+use rustc::middle::const_eval::{self, ConstEvalErr};
+use rustc::middle::const_eval::ErrKind::IndexOpFeatureGated;
+use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
+use rustc::middle::def::Def;
+use rustc::middle::def_id::DefId;
+use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
+use rustc::middle::mem_categorization as mc;
+use rustc::middle::mem_categorization::Categorization;
+use rustc::middle::traits;
+use rustc::middle::ty::{self, Ty};
+use rustc::util::nodemap::NodeMap;
+use rustc::middle::const_qualif::ConstQualif;
+use rustc::lint::builtin::CONST_ERR;
+
+use rustc_front::hir;
+use syntax::ast;
+use syntax::codemap::Span;
+use syntax::feature_gate::UnstableFeatures;
+use rustc_front::intravisit::{self, FnKind, Visitor};
+
+use std::collections::hash_map::Entry;
+use std::cmp::Ordering;
+
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+enum Mode {
+    Const,
+    ConstFn,
+    Static,
+    StaticMut,
+
+    // An expression that occurs outside of any constant context
+    // (i.e. `const`, `static`, array lengths, etc.). The value
+    // can be variable at runtime, but will be promotable to
+    // static memory if we can prove it is actually constant.
+    Var,
+}
+
+struct CheckCrateVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    mode: Mode,
+    qualif: ConstQualif,
+    rvalue_borrows: NodeMap<hir::Mutability>
+}
+
+impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
+    fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
+        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>) -> R,
+    {
+        let (old_mode, old_qualif) = (self.mode, self.qualif);
+        self.mode = mode;
+        self.qualif = ConstQualif::empty();
+        let r = f(self);
+        self.mode = old_mode;
+        self.qualif = old_qualif;
+        r
+    }
+
+    fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
+        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
+    {
+        let param_env = match item_id {
+            Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
+            None => self.tcx.empty_parameter_environment()
+        };
+
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env));
+
+        f(&mut euv::ExprUseVisitor::new(self, &infcx))
+    }
+
+    fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
+        assert!(mode != Mode::Var);
+        match self.tcx.const_qualif_map.borrow_mut().entry(expr.id) {
+            Entry::Occupied(entry) => return *entry.get(),
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(ConstQualif::empty());
+            }
+        }
+        self.with_mode(mode, |this| {
+            this.with_euv(None, |euv| euv.consume_expr(expr));
+            this.visit_expr(expr);
+            this.qualif
+        })
+    }
+
+    fn fn_like(&mut self,
+               fk: FnKind,
+               fd: &hir::FnDecl,
+               b: &hir::Block,
+               s: Span,
+               fn_id: ast::NodeId)
+               -> ConstQualif {
+        match self.tcx.const_qualif_map.borrow_mut().entry(fn_id) {
+            Entry::Occupied(entry) => return *entry.get(),
+            Entry::Vacant(entry) => {
+                // Prevent infinite recursion on re-entry.
+                entry.insert(ConstQualif::empty());
+            }
+        }
+
+        let mode = match fk {
+            FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
+                Mode::ConstFn
+            }
+            FnKind::Method(_, m, _) => {
+                if m.constness == hir::Constness::Const {
+                    Mode::ConstFn
+                } else {
+                    Mode::Var
+                }
+            }
+            _ => Mode::Var
+        };
+
+        let qualif = self.with_mode(mode, |this| {
+            this.with_euv(Some(fn_id), |euv| euv.walk_fn(fd, b));
+            intravisit::walk_fn(this, fk, fd, b, s);
+            this.qualif
+        });
+
+        // Keep only bits that aren't affected by function body (NON_ZERO_SIZED),
+        // and bits that don't change semantics, just optimizations (PREFER_IN_PLACE).
+        let qualif = qualif & (ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
+
+        self.tcx.const_qualif_map.borrow_mut().insert(fn_id, qualif);
+        qualif
+    }
+
+    fn add_qualif(&mut self, qualif: ConstQualif) {
+        self.qualif = self.qualif | qualif;
+    }
+
+    /// Returns true if the call is to a const fn or method.
+    fn handle_const_fn_call(&mut self,
+                            expr: &hir::Expr,
+                            def_id: DefId,
+                            ret_ty: Ty<'tcx>)
+                            -> bool {
+        if let Some(fn_like) = const_eval::lookup_const_fn_by_id(self.tcx, def_id) {
+            if
+                // we are in a static/const initializer
+                self.mode != Mode::Var &&
+
+                // feature-gate is not enabled
+                !self.tcx.sess.features.borrow().const_fn &&
+
+                // this doesn't come from a macro that has #[allow_internal_unstable]
+                !self.tcx.sess.codemap().span_allows_unstable(expr.span)
+            {
+                let mut err = self.tcx.sess.struct_span_err(
+                    expr.span,
+                    "const fns are an unstable feature");
+                fileline_help!(
+                    &mut err,
+                    expr.span,
+                    "in Nightly builds, add `#![feature(const_fn)]` to the crate \
+                     attributes to enable");
+                err.emit();
+            }
+
+            let qualif = self.fn_like(fn_like.kind(),
+                                      fn_like.decl(),
+                                      fn_like.body(),
+                                      fn_like.span(),
+                                      fn_like.id());
+            self.add_qualif(qualif);
+
+            if ret_ty.type_contents(self.tcx).interior_unsafe() {
+                self.add_qualif(ConstQualif::MUTABLE_MEM);
+            }
+
+            true
+        } else {
+            false
+        }
+    }
+
+    fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
+        match self.rvalue_borrows.entry(id) {
+            Entry::Occupied(mut entry) => {
+                // Merge the two borrows, taking the most demanding
+                // one, mutability-wise.
+                if mutbl == hir::MutMutable {
+                    entry.insert(mutbl);
+                }
+            }
+            Entry::Vacant(entry) => {
+                entry.insert(mutbl);
+            }
+        }
+    }
+
+    fn msg(&self) -> &'static str {
+        match self.mode {
+            Mode::Const => "constant",
+            Mode::ConstFn => "constant function",
+            Mode::StaticMut | Mode::Static => "static",
+            Mode::Var => unreachable!(),
+        }
+    }
+
+    fn check_static_mut_type(&self, e: &hir::Expr) {
+        let node_ty = self.tcx.node_id_to_type(e.id);
+        let tcontents = node_ty.type_contents(self.tcx);
+
+        let suffix = if tcontents.has_dtor() {
+            "destructors"
+        } else if tcontents.owns_owned() {
+            "boxes"
+        } else {
+            return
+        };
+
+        span_err!(self.tcx.sess, e.span, E0397,
+                 "mutable statics are not allowed to have {}", suffix);
+    }
+
+    fn check_static_type(&self, e: &hir::Expr) {
+        let ty = self.tcx.node_id_to_type(e.id);
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+        let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
+        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
+        match fulfill_cx.select_all_or_error(&infcx) {
+            Ok(()) => { },
+            Err(ref errors) => {
+                traits::report_fulfillment_errors(&infcx, errors);
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, i: &hir::Item) {
+        debug!("visit_item(item={})", self.tcx.map.node_to_string(i.id));
+        assert_eq!(self.mode, Mode::Var);
+        match i.node {
+            hir::ItemStatic(_, hir::MutImmutable, ref expr) => {
+                self.check_static_type(&**expr);
+                self.global_expr(Mode::Static, &**expr);
+            }
+            hir::ItemStatic(_, hir::MutMutable, ref expr) => {
+                self.check_static_mut_type(&**expr);
+                self.global_expr(Mode::StaticMut, &**expr);
+            }
+            hir::ItemConst(_, ref expr) => {
+                self.global_expr(Mode::Const, &**expr);
+            }
+            hir::ItemEnum(ref enum_definition, _) => {
+                for var in &enum_definition.variants {
+                    if let Some(ref ex) = var.node.disr_expr {
+                        self.global_expr(Mode::Const, &**ex);
+                    }
+                }
+            }
+            _ => {
+                intravisit::walk_item(self, i);
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, t: &'v hir::TraitItem) {
+        match t.node {
+            hir::ConstTraitItem(_, ref default) => {
+                if let Some(ref expr) = *default {
+                    self.global_expr(Mode::Const, &*expr);
+                } else {
+                    intravisit::walk_trait_item(self, t);
+                }
+            }
+            _ => self.with_mode(Mode::Var, |v| intravisit::walk_trait_item(v, t)),
+        }
+    }
+
+    fn visit_impl_item(&mut self, i: &'v hir::ImplItem) {
+        match i.node {
+            hir::ImplItemKind::Const(_, ref expr) => {
+                self.global_expr(Mode::Const, &*expr);
+            }
+            _ => self.with_mode(Mode::Var, |v| intravisit::walk_impl_item(v, i)),
+        }
+    }
+
+    fn visit_fn(&mut self,
+                fk: FnKind<'v>,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
+                s: Span,
+                fn_id: ast::NodeId) {
+        self.fn_like(fk, fd, b, s, fn_id);
+    }
+
+    fn visit_pat(&mut self, p: &hir::Pat) {
+        match p.node {
+            hir::PatLit(ref lit) => {
+                self.global_expr(Mode::Const, &**lit);
+            }
+            hir::PatRange(ref start, ref end) => {
+                self.global_expr(Mode::Const, &**start);
+                self.global_expr(Mode::Const, &**end);
+
+                match const_eval::compare_lit_exprs(self.tcx, start, end) {
+                    Some(Ordering::Less) |
+                    Some(Ordering::Equal) => {}
+                    Some(Ordering::Greater) => {
+                        span_err!(self.tcx.sess, start.span, E0030,
+                            "lower range bound must be less than or equal to upper");
+                    }
+                    None => {
+                        self.tcx.sess.delay_span_bug(start.span,
+                                                     "non-constant path in constant expr");
+                    }
+                }
+            }
+            _ => intravisit::walk_pat(self, p)
+        }
+    }
+
+    fn visit_block(&mut self, block: &hir::Block) {
+        // Check all statements in the block
+        for stmt in &block.stmts {
+            match stmt.node {
+                hir::StmtDecl(ref decl, _) => {
+                    match decl.node {
+                        hir::DeclLocal(_) => {},
+                        // Item statements are allowed
+                        hir::DeclItem(_) => continue
+                    }
+                }
+                hir::StmtExpr(_, _) => {},
+                hir::StmtSemi(_, _) => {},
+            }
+            self.add_qualif(ConstQualif::NOT_CONST);
+            // anything else should have been caught by check_const_fn
+            assert_eq!(self.mode, Mode::Var);
+        }
+        intravisit::walk_block(self, block);
+    }
+
+    fn visit_expr(&mut self, ex: &hir::Expr) {
+        let mut outer = self.qualif;
+        self.qualif = ConstQualif::empty();
+
+        let node_ty = self.tcx.node_id_to_type(ex.id);
+        check_expr(self, ex, node_ty);
+        check_adjustments(self, ex);
+
+        // Special-case some expressions to avoid certain flags bubbling up.
+        match ex.node {
+            hir::ExprCall(ref callee, ref args) => {
+                for arg in args {
+                    self.visit_expr(&**arg)
+                }
+
+                let inner = self.qualif;
+                self.visit_expr(&**callee);
+                // The callee's size doesn't count in the call.
+                let added = self.qualif - inner;
+                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
+            }
+            hir::ExprRepeat(ref element, _) => {
+                self.visit_expr(&**element);
+                // The count is checked elsewhere (typeck).
+                let count = match node_ty.sty {
+                    ty::TyArray(_, n) => n,
+                    _ => unreachable!()
+                };
+                // [element; 0] is always zero-sized.
+                if count == 0 {
+                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
+                }
+            }
+            hir::ExprMatch(ref discr, ref arms, _) => {
+                // Compute the most demanding borrow from all the arms'
+                // patterns and set that on the discriminator.
+                let mut borrow = None;
+                for pat in arms.iter().flat_map(|arm| &arm.pats) {
+                    let pat_borrow = self.rvalue_borrows.remove(&pat.id);
+                    match (borrow, pat_borrow) {
+                        (None, _) | (_, Some(hir::MutMutable)) => {
+                            borrow = pat_borrow;
+                        }
+                        _ => {}
+                    }
+                }
+                if let Some(mutbl) = borrow {
+                    self.record_borrow(discr.id, mutbl);
+                }
+                intravisit::walk_expr(self, ex);
+            }
+            // Division by zero and overflow checking.
+            hir::ExprBinary(op, _, _) => {
+                intravisit::walk_expr(self, ex);
+                let div_or_rem = op.node == hir::BiDiv || op.node == hir::BiRem;
+                match node_ty.sty {
+                    ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
+                        if !self.qualif.intersects(ConstQualif::NOT_CONST) {
+                            match const_eval::eval_const_expr_partial(
+                                    self.tcx, ex, ExprTypeChecked, None) {
+                                Ok(_) => {}
+                                Err(ConstEvalErr { kind: IndexOpFeatureGated, ..}) => {},
+                                Err(msg) => {
+                                    self.tcx.sess.add_lint(CONST_ERR, ex.id,
+                                                           msg.span,
+                                                           msg.description().into_owned())
+                                }
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => intravisit::walk_expr(self, ex)
+        }
+
+        // Handle borrows on (or inside the autorefs of) this expression.
+        match self.rvalue_borrows.remove(&ex.id) {
+            Some(hir::MutImmutable) => {
+                // Constants cannot be borrowed if they contain interior mutability as
+                // it means that our "silent insertion of statics" could change
+                // initializer values (very bad).
+                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
+                // propagated from another error, so erroring again would be just noise.
+                let tc = node_ty.type_contents(self.tcx);
+                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
+                    outer = outer | ConstQualif::NOT_CONST;
+                    if self.mode != Mode::Var {
+                        span_err!(self.tcx.sess, ex.span, E0492,
+                                  "cannot borrow a constant which contains \
+                                   interior mutability, create a static instead");
+                    }
+                }
+                // If the reference has to be 'static, avoid in-place initialization
+                // as that will end up pointing to the stack instead.
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
+                }
+            }
+            Some(hir::MutMutable) => {
+                // `&mut expr` means expr could be mutated, unless it's zero-sized.
+                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
+                    if self.mode == Mode::Var {
+                        outer = outer | ConstQualif::NOT_CONST;
+                        self.add_qualif(ConstQualif::MUTABLE_MEM);
+                    } else {
+                        span_err!(self.tcx.sess, ex.span, E0017,
+                            "references in {}s may only refer \
+                             to immutable values", self.msg())
+                    }
+                }
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
+                }
+            }
+            None => {}
+        }
+        self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
+        // Don't propagate certain flags.
+        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
+    }
+}
+
+/// This function is used to enforce the constraints on
+/// const/static items. It walks through the *value*
+/// of the item walking down the expression and evaluating
+/// every nested expression. If the expression is not part
+/// of a const/static item, it is qualified for promotion
+/// instead of producing errors.
+fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
+                        e: &hir::Expr, node_ty: Ty<'tcx>) {
+    match node_ty.sty {
+        ty::TyStruct(def, _) |
+        ty::TyEnum(def, _) if def.has_dtor() => {
+            v.add_qualif(ConstQualif::NEEDS_DROP);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0493,
+                          "{}s are not allowed to have destructors",
+                          v.msg());
+            }
+        }
+        _ => {}
+    }
+
+    let method_call = ty::MethodCall::expr(e.id);
+    match e.node {
+        hir::ExprUnary(..) |
+        hir::ExprBinary(..) |
+        hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0011,
+                            "user-defined operators are not allowed in {}s", v.msg());
+            }
+        }
+        hir::ExprBox(_) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0010,
+                          "allocations are not allowed in {}s", v.msg());
+            }
+        }
+        hir::ExprUnary(op, ref inner) => {
+            match v.tcx.node_id_to_type(inner.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op == hir::UnDeref);
+
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0396,
+                                  "raw pointers cannot be dereferenced in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprBinary(op, ref lhs, _) => {
+            match v.tcx.node_id_to_type(lhs.id).sty {
+                ty::TyRawPtr(_) => {
+                    assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
+                            op.node == hir::BiLe || op.node == hir::BiLt ||
+                            op.node == hir::BiGe || op.node == hir::BiGt);
+
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0395,
+                                  "raw pointers cannot be compared in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprCast(ref from, _) => {
+            debug!("Checking const cast(id={})", from.id);
+            match v.tcx.cast_kinds.borrow().get(&from.id) {
+                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
+                Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        span_err!(v.tcx.sess, e.span, E0018,
+                                  "raw pointers cannot be cast to integers in {}s", v.msg());
+                    }
+                }
+                _ => {}
+            }
+        }
+        hir::ExprPath(..) => {
+            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
+            match def {
+                Some(Def::Variant(..)) => {
+                    // Count the discriminator or function pointer.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                }
+                Some(Def::Struct(..)) => {
+                    if let ty::TyBareFn(..) = node_ty.sty {
+                        // Count the function pointer.
+                        v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                    }
+                }
+                Some(Def::Fn(..)) | Some(Def::Method(..)) => {
+                    // Count the function pointer.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                }
+                Some(Def::Static(..)) => {
+                    match v.mode {
+                        Mode::Static | Mode::StaticMut => {}
+                        Mode::Const | Mode::ConstFn => {
+                            span_err!(v.tcx.sess, e.span, E0013,
+                                "{}s cannot refer to other statics, insert \
+                                 an intermediate constant instead", v.msg());
+                        }
+                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
+                    }
+                }
+                Some(Def::Const(did)) |
+                Some(Def::AssociatedConst(did)) => {
+                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
+                                                                       Some(e.id),
+                                                                       None) {
+                        let inner = v.global_expr(Mode::Const, expr);
+                        v.add_qualif(inner);
+                    }
+                }
+                Some(Def::Local(..)) if v.mode == Mode::ConstFn => {
+                    // Sadly, we can't determine whether the types are zero-sized.
+                    v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
+                }
+                def => {
+                    v.add_qualif(ConstQualif::NOT_CONST);
+                    if v.mode != Mode::Var {
+                        debug!("(checking const) found bad def: {:?}", def);
+                        span_err!(v.tcx.sess, e.span, E0014,
+                                  "paths in {}s may only refer to constants \
+                                   or functions", v.msg());
+                    }
+                }
+            }
+        }
+        hir::ExprCall(ref callee, _) => {
+            let mut callee = &**callee;
+            loop {
+                callee = match callee.node {
+                    hir::ExprBlock(ref block) => match block.expr {
+                        Some(ref tail) => &**tail,
+                        None => break
+                    },
+                    _ => break
+                };
+            }
+            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
+            let is_const = match def {
+                Some(Def::Struct(..)) => true,
+                Some(Def::Variant(..)) => {
+                    // Count the discriminator.
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+                    true
+                }
+                Some(Def::Fn(did)) => {
+                    v.handle_const_fn_call(e, did, node_ty)
+                }
+                Some(Def::Method(did)) => {
+                    match v.tcx.impl_or_trait_item(did).container() {
+                        ty::ImplContainer(_) => {
+                            v.handle_const_fn_call(e, did, node_ty)
+                        }
+                        ty::TraitContainer(_) => false
+                    }
+                }
+                _ => false
+            };
+            if !is_const {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    // FIXME(#24111) Remove this check when const fn stabilizes
+                    let (msg, note) =
+                        if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
+                        (format!("function calls in {}s are limited to \
+                                  struct and enum constructors",
+                                 v.msg()),
+                         Some("a limited form of compile-time function \
+                               evaluation is available on a nightly \
+                               compiler via `const fn`"))
+                    } else {
+                        (format!("function calls in {}s are limited \
+                                  to constant functions, \
+                                  struct and enum constructors",
+                                 v.msg()),
+                         None)
+                    };
+                    let mut err = struct_span_err!(v.tcx.sess, e.span, E0015, "{}", msg);
+                    if let Some(note) = note {
+                        err.span_note(e.span, note);
+                    }
+                    err.emit();
+                }
+            }
+        }
+        hir::ExprMethodCall(..) => {
+            let method = v.tcx.tables.borrow().method_map[&method_call];
+            let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
+                ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
+                ty::TraitContainer(_) => false
+            };
+            if !is_const {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    span_err!(v.tcx.sess, e.span, E0378,
+                              "method calls in {}s are limited to \
+                               constant inherent methods", v.msg());
+                }
+            }
+        }
+        hir::ExprStruct(..) => {
+            let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
+            if did == v.tcx.lang_items.unsafe_cell_type() {
+                v.add_qualif(ConstQualif::MUTABLE_MEM);
+            }
+        }
+
+        hir::ExprLit(_) |
+        hir::ExprAddrOf(..) => {
+            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
+        }
+
+        hir::ExprRepeat(..) => {
+            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
+        }
+
+        hir::ExprClosure(..) => {
+            // Paths in constant contexts cannot refer to local variables,
+            // as there are none, and thus closures can't have upvars there.
+            if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
+                assert!(v.mode == Mode::Var,
+                        "global closures can't capture anything");
+                v.add_qualif(ConstQualif::NOT_CONST);
+            }
+        }
+
+        hir::ExprBlock(_) |
+        hir::ExprIndex(..) |
+        hir::ExprField(..) |
+        hir::ExprTupField(..) |
+        hir::ExprVec(_) |
+        hir::ExprType(..) |
+        hir::ExprTup(..) => {}
+
+        // Conditional control flow (possible to implement).
+        hir::ExprMatch(..) |
+        hir::ExprIf(..) |
+
+        // Loops (not very meaningful in constants).
+        hir::ExprWhile(..) |
+        hir::ExprLoop(..) |
+
+        // More control flow (also not very meaningful).
+        hir::ExprBreak(_) |
+        hir::ExprAgain(_) |
+        hir::ExprRet(_) |
+
+        // Miscellaneous expressions that could be implemented.
+        hir::ExprRange(..) |
+
+        // Expressions with side-effects.
+        hir::ExprAssign(..) |
+        hir::ExprAssignOp(..) |
+        hir::ExprInlineAsm(_) => {
+            v.add_qualif(ConstQualif::NOT_CONST);
+            if v.mode != Mode::Var {
+                span_err!(v.tcx.sess, e.span, E0019,
+                          "{} contains unimplemented expression type", v.msg());
+            }
+        }
+    }
+}
+
+/// Check the adjustments of an expression
+fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
+    match v.tcx.tables.borrow().adjustments.get(&e.id) {
+        None |
+        Some(&ty::adjustment::AdjustReifyFnPointer) |
+        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
+
+        Some(&ty::adjustment::AdjustDerefRef(
+            ty::adjustment::AutoDerefRef { autoderefs, .. }
+        )) => {
+            if (0..autoderefs as u32).any(|autoderef| {
+                    v.tcx.is_overloaded_autoderef(e.id, autoderef)
+            }) {
+                v.add_qualif(ConstQualif::NOT_CONST);
+                if v.mode != Mode::Var {
+                    span_err!(v.tcx.sess, e.span, E0400,
+                              "user-defined dereference operators are not allowed in {}s",
+                              v.msg());
+                }
+            }
+        }
+    }
+}
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
+        tcx: tcx,
+        mode: Mode::Var,
+        qualif: ConstQualif::NOT_CONST,
+        rvalue_borrows: NodeMap()
+    });
+    tcx.sess.abort_if_errors();
+}
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
+    fn consume(&mut self,
+               _consume_id: ast::NodeId,
+               consume_span: Span,
+               cmt: mc::cmt,
+               _mode: euv::ConsumeMode) {
+        let mut cur = &cmt;
+        loop {
+            match cur.cat {
+                Categorization::StaticItem => {
+                    if self.mode != Mode::Var {
+                        // statics cannot be consumed by value at any time, that would imply
+                        // that they're an initializer (what a const is for) or kept in sync
+                        // over time (not feasible), so deny it outright.
+                        span_err!(self.tcx.sess, consume_span, E0394,
+                                  "cannot refer to other statics by value, use the \
+                                   address-of operator or a constant instead");
+                    }
+                    break;
+                }
+                Categorization::Deref(ref cmt, _, _) |
+                Categorization::Downcast(ref cmt, _) |
+                Categorization::Interior(ref cmt, _) => cur = cmt,
+
+                Categorization::Rvalue(..) |
+                Categorization::Upvar(..) |
+                Categorization::Local(..) => break
+            }
+        }
+    }
+    fn borrow(&mut self,
+              borrow_id: ast::NodeId,
+              borrow_span: Span,
+              cmt: mc::cmt<'tcx>,
+              _loan_region: ty::Region,
+              bk: ty::BorrowKind,
+              loan_cause: euv::LoanCause)
+    {
+        // Kind of hacky, but we allow Unsafe coercions in constants.
+        // These occur when we convert a &T or *T to a *U, as well as
+        // when making a thin pointer (e.g., `*T`) into a fat pointer
+        // (e.g., `*Trait`).
+        match loan_cause {
+            euv::LoanCause::AutoUnsafe => {
+                return;
+            }
+            _ => { }
+        }
+
+        let mut cur = &cmt;
+        let mut is_interior = false;
+        loop {
+            match cur.cat {
+                Categorization::Rvalue(..) => {
+                    if loan_cause == euv::MatchDiscriminant {
+                        // Ignore the dummy immutable borrow created by EUV.
+                        break;
+                    }
+                    let mutbl = bk.to_mutbl_lossy();
+                    if mutbl == hir::MutMutable && self.mode == Mode::StaticMut {
+                        // Mutable slices are the only `&mut` allowed in
+                        // globals, but only in `static mut`, nowhere else.
+                        // FIXME: This exception is really weird... there isn't
+                        // any fundamental reason to restrict this based on
+                        // type of the expression.  `&mut [1]` has exactly the
+                        // same representation as &mut 1.
+                        match cmt.ty.sty {
+                            ty::TyArray(_, _) | ty::TySlice(_) => break,
+                            _ => {}
+                        }
+                    }
+                    self.record_borrow(borrow_id, mutbl);
+                    break;
+                }
+                Categorization::StaticItem => {
+                    if is_interior && self.mode != Mode::Var {
+                        // Borrowed statics can specifically *only* have their address taken,
+                        // not any number of other borrows such as borrowing fields, reading
+                        // elements of an array, etc.
+                        span_err!(self.tcx.sess, borrow_span, E0494,
+                                  "cannot refer to the interior of another \
+                                   static, use a constant instead");
+                    }
+                    break;
+                }
+                Categorization::Deref(ref cmt, _, _) |
+                Categorization::Downcast(ref cmt, _) |
+                Categorization::Interior(ref cmt, _) => {
+                    is_interior = true;
+                    cur = cmt;
+                }
+
+                Categorization::Upvar(..) |
+                Categorization::Local(..) => break
+            }
+        }
+    }
+
+    fn decl_without_init(&mut self,
+                         _id: ast::NodeId,
+                         _span: Span) {}
+    fn mutate(&mut self,
+              _assignment_id: ast::NodeId,
+              _assignment_span: Span,
+              _assignee_cmt: mc::cmt,
+              _mode: euv::MutateMode) {}
+
+    fn matched_pat(&mut self,
+                   _: &hir::Pat,
+                   _: mc::cmt,
+                   _: euv::MatchMode) {}
+
+    fn consume_pat(&mut self,
+                   _consume_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::ConsumeMode) {}
+}
index 380eada18a1e1c0c4d1d23bf20148b6ea03e3317..2c08cbd32338d47ae56713415d882a090e60055c 100644 (file)
 #![allow(non_snake_case)]
 
 register_long_diagnostics! {
+
+E0010: r##"
+The value of statics and constants must be known at compile time, and they live
+for the entire lifetime of a program. Creating a boxed value allocates memory on
+the heap at runtime, and therefore cannot be done at compile time. Erroneous
+code example:
+
+```
+#![feature(box_syntax)]
+
+const CON : Box<i32> = box 0;
+```
+"##,
+
+E0011: r##"
+Initializers for constants and statics are evaluated at compile time.
+User-defined operators rely on user-defined functions, which cannot be evaluated
+at compile time.
+
+Bad example:
+
+```
+use std::ops::Index;
+
+struct Foo { a: u8 }
+
+impl Index<u8> for Foo {
+    type Output = u8;
+
+    fn index<'a>(&'a self, idx: u8) -> &'a u8 { &self.a }
+}
+
+const a: Foo = Foo { a: 0u8 };
+const b: u8 = a[0]; // Index trait is defined by the user, bad!
+```
+
+Only operators on builtin types are allowed.
+
+Example:
+
+```
+const a: &'static [i32] = &[1, 2, 3];
+const b: i32 = a[0]; // Good!
+```
+"##,
+
+E0013: r##"
+Static and const variables can refer to other const variables. But a const
+variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
+here:
+
+```
+static X: i32 = 42;
+const Y: i32 = X;
+```
+
+To fix this, the value can be extracted as a const and then used:
+
+```
+const A: i32 = 42;
+static X: i32 = A;
+const Y: i32 = A;
+```
+"##,
+
+E0014: r##"
+Constants can only be initialized by a constant value or, in a future
+version of Rust, a call to a const function. This error indicates the use
+of a path (like a::b, or x) denoting something other than one of these
+allowed items. Example:
+
+```
+const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function!
+```
+
+To avoid it, you have to replace the non-constant value:
+
+```
+const FOO: i32 = { const X : i32 = 0; X };
+// or even:
+const FOO: i32 = { 0 }; // but brackets are useless here
+```
+"##,
+
+// FIXME(#24111) Change the language here when const fn stabilizes
+E0015: r##"
+The only functions that can be called in static or constant expressions are
+`const` functions, and struct/enum constructors. `const` functions are only
+available on a nightly compiler. Rust currently does not support more general
+compile-time function execution.
+
+```
+const FOO: Option<u8> = Some(1); // enum constructor
+struct Bar {x: u8}
+const BAR: Bar = Bar {x: 1}; // struct constructor
+```
+
+See [RFC 911] for more details on the design of `const fn`s.
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
 E0016: r##"
 Blocks in constants may only contain items (such as constant, function
 definition, etc...) and a tail expression. Example:
 ```
 "##,
 
+E0017: r##"
+References in statics and constants may only refer to immutable values. Example:
+
+```
+static X: i32 = 1;
+const C: i32 = 2;
+
+// these three are not allowed:
+const CR: &'static mut i32 = &mut C;
+static STATIC_REF: &'static mut i32 = &mut X;
+static CONST_REF: &'static mut i32 = &mut C;
+```
+
+Statics are shared everywhere, and if they refer to mutable data one might
+violate memory safety since holding multiple mutable references to shared data
+is not allowed.
+
+If you really want global mutable state, try using `static mut` or a global
+`UnsafeCell`.
+"##,
+
+E0018: r##"
+The value of static and const variables must be known at compile time. You
+can't cast a pointer as an integer because we can't know what value the
+address will take.
+
+However, pointers to other constants' addresses are allowed in constants,
+example:
+
+```
+const X: u32 = 50;
+const Y: *const u32 = &X;
+```
+
+Therefore, casting one of these non-constant pointers to an integer results
+in a non-constant integer which lead to this error. Example:
+
+```
+const X: u32 = 1;
+const Y: usize = &X as *const u32 as usize;
+println!("{}", Y);
+```
+"##,
+
+E0019: r##"
+A function call isn't allowed in the const's initialization expression
+because the expression's value must be known at compile-time. Example of
+erroneous code:
+
+```
+enum Test {
+    V1
+}
+
+impl Test {
+    fn test(&self) -> i32 {
+        12
+    }
+}
+
+fn main() {
+    const FOO: Test = Test::V1;
+
+    const A: i32 = FOO.test(); // You can't call Test::func() here !
+}
+```
+
+Remember: you can't use a function call inside a const's initialization
+expression! However, you can totally use it anywhere else:
+
+```
+fn main() {
+    const FOO: Test = Test::V1;
+
+    FOO.func(); // here is good
+    let x = FOO.func(); // or even here!
+}
+```
+"##,
+
 E0022: r##"
 Constant functions are not allowed to mutate anything. Thus, binding to an
 argument with a mutable pattern is not allowed. For example,
@@ -43,6 +225,366 @@ const fn foo(mut x: u8) {
 instead of using a `const fn`, or refactoring the code to a functional style to
 avoid mutation if possible.
 "##,
+
+E0030: r##"
+When matching against a range, the compiler verifies that the range is
+non-empty.  Range patterns include both end-points, so this is equivalent to
+requiring the start of the range to be less than or equal to the end of the
+range.
+
+For example:
+
+```
+match 5u32 {
+    // This range is ok, albeit pointless.
+    1 ... 1 => ...
+    // This range is empty, and the compiler can tell.
+    1000 ... 5 => ...
+}
+```
+"##,
+
+E0161: r##"
+In Rust, you can only move a value when its size is known at compile time.
+
+To work around this restriction, consider "hiding" the value behind a reference:
+either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
+it around as usual.
+"##,
+
+E0265: r##"
+This error indicates that a static or constant references itself.
+All statics and constants need to resolve to a value in an acyclic manner.
+
+For example, neither of the following can be sensibly compiled:
+
+```
+const X: u32 = X;
+```
+
+```
+const X: u32 = Y;
+const Y: u32 = X;
+```
+"##,
+
+E0267: r##"
+This error indicates the use of a loop keyword (`break` or `continue`) inside a
+closure but outside of any loop. Erroneous code example:
+
+```
+let w = || { break; }; // error: `break` inside of a closure
+```
+
+`break` and `continue` keywords can be used as normal inside closures as long as
+they are also contained within a loop. To halt the execution of a closure you
+should instead use a return statement. Example:
+
+```
+let w = || {
+    for _ in 0..10 {
+        break;
+    }
+};
+
+w();
+```
+"##,
+
+E0268: r##"
+This error indicates the use of a loop keyword (`break` or `continue`) outside
+of a loop. Without a loop to break out of or continue in, no sensible action can
+be taken. Erroneous code example:
+
+```
+fn some_func() {
+    break; // error: `break` outside of loop
+}
+```
+
+Please verify that you are using `break` and `continue` only in loops. Example:
+
+```
+fn some_func() {
+    for _ in 0..10 {
+        break; // ok!
+    }
+}
+```
+"##,
+
+E0378: r##"
+Method calls that aren't calls to inherent `const` methods are disallowed
+in statics, constants, and constant functions.
+
+For example:
+
+```
+const BAZ: i32 = Foo(25).bar(); // error, `bar` isn't `const`
+
+struct Foo(i32);
+
+impl Foo {
+    const fn foo(&self) -> i32 {
+        self.bar() // error, `bar` isn't `const`
+    }
+
+    fn bar(&self) -> i32 { self.0 }
+}
+```
+
+For more information about `const fn`'s, see [RFC 911].
+
+[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
+"##,
+
+E0394: r##"
+From [RFC 246]:
+
+ > It is invalid for a static to reference another static by value. It is
+ > required that all references be borrowed.
+
+[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
+"##,
+
+E0395: r##"
+The value assigned to a constant expression must be known at compile time,
+which is not the case when comparing raw pointers. Erroneous code example:
+
+```
+static foo: i32 = 42;
+static bar: i32 = 43;
+
+static baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
+// error: raw pointers cannot be compared in statics!
+```
+
+Please check that the result of the comparison can be determined at compile time
+or isn't assigned to a constant expression. Example:
+
+```
+static foo: i32 = 42;
+static bar: i32 = 43;
+
+let baz: bool = { (&foo as *const i32) == (&bar as *const i32) };
+// baz isn't a constant expression so it's ok
+```
+"##,
+
+E0396: r##"
+The value assigned to a constant expression must be known at compile time,
+which is not the case when dereferencing raw pointers. Erroneous code
+example:
+
+```
+const foo: i32 = 42;
+const baz: *const i32 = (&foo as *const i32);
+
+const deref: i32 = *baz;
+// error: raw pointers cannot be dereferenced in constants
+```
+
+To fix this error, please do not assign this value to a constant expression.
+Example:
+
+```
+const foo: i32 = 42;
+const baz: *const i32 = (&foo as *const i32);
+
+unsafe { let deref: i32 = *baz; }
+// baz isn't a constant expression so it's ok
+```
+
+You'll also note that this assignment must be done in an unsafe block!
+"##,
+
+E0397: r##"
+It is not allowed for a mutable static to allocate or have destructors. For
+example:
+
+```
+// error: mutable statics are not allowed to have boxes
+static mut FOO: Option<Box<usize>> = None;
+
+// error: mutable statics are not allowed to have destructors
+static mut BAR: Option<Vec<i32>> = None;
+```
+"##,
+
+E0400: r##"
+A user-defined dereference was attempted in an invalid context. Erroneous
+code example:
+
+```
+use std::ops::Deref;
+
+struct A;
+
+impl Deref for A {
+    type Target = str;
+
+    fn deref(&self)-> &str { "foo" }
+}
+
+const S: &'static str = &A;
+// error: user-defined dereference operators are not allowed in constants
+
+fn main() {
+    let foo = S;
+}
+```
+
+You cannot directly use a dereference operation whilst initializing a constant
+or a static. To fix this error, restructure your code to avoid this dereference,
+perhaps moving it inline:
+
+```
+use std::ops::Deref;
+
+struct A;
+
+impl Deref for A {
+    type Target = str;
+
+    fn deref(&self)-> &str { "foo" }
+}
+
+fn main() {
+    let foo : &str = &A;
+}
+```
+"##,
+
+E0492: r##"
+A borrow of a constant containing interior mutability was attempted. Erroneous
+code example:
+
+```
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+
+const A: AtomicUsize = ATOMIC_USIZE_INIT;
+static B: &'static AtomicUsize = &A;
+// error: cannot borrow a constant which contains interior mutability, create a
+//        static instead
+```
+
+A `const` represents a constant value that should never change. If one takes
+a `&` reference to the constant, then one is taking a pointer to some memory
+location containing the value. Normally this is perfectly fine: most values
+can't be changed via a shared `&` pointer, but interior mutability would allow
+it. That is, a constant value could be mutated. On the other hand, a `static` is
+explicitly a single memory location, which can be mutated at will.
+
+So, in order to solve this error, either use statics which are `Sync`:
+
+```
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+
+static A: AtomicUsize = ATOMIC_USIZE_INIT;
+static B: &'static AtomicUsize = &A; // ok!
+```
+
+You can also have this error while using a cell type:
+
+```
+#![feature(const_fn)]
+
+use std::cell::Cell;
+
+const A: Cell<usize> = Cell::new(1);
+const B: &'static Cell<usize> = &A;
+// error: cannot borrow a constant which contains interior mutability, create
+//        a static instead
+
+// or:
+struct C { a: Cell<usize> }
+
+const D: C = C { a: Cell::new(1) };
+const E: &'static Cell<usize> = &D.a; // error
+
+// or:
+const F: &'static C = &D; // error
+```
+
+This is because cell types do operations that are not thread-safe. Due to this,
+they don't implement Sync and thus can't be placed in statics. In this
+case, `StaticMutex` would work just fine, but it isn't stable yet:
+https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html
+
+However, if you still wish to use these types, you can achieve this by an unsafe
+wrapper:
+
+```
+#![feature(const_fn)]
+
+use std::cell::Cell;
+use std::marker::Sync;
+
+struct NotThreadSafe<T> {
+    value: Cell<T>,
+}
+
+unsafe impl<T> Sync for NotThreadSafe<T> {}
+
+static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
+static B: &'static NotThreadSafe<usize> = &A; // ok!
+```
+
+Remember this solution is unsafe! You will have to ensure that accesses to the
+cell are synchronized.
+"##,
+
+E0493: r##"
+A type with a destructor was assigned to an invalid type of variable. Erroneous
+code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+const F : Foo = Foo { a : 0 };
+// error: constants are not allowed to have destructors
+static S : Foo = Foo { a : 0 };
+// error: statics are not allowed to have destructors
+```
+
+To solve this issue, please use a type which does allow the usage of type with
+destructors.
+"##,
+
+E0494: r##"
+A reference of an interior static was assigned to another const/static.
+Erroneous code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+static S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a;
+// error: cannot refer to the interior of another static, use a
+//        constant instead
+```
+
+The "base" variable has to be a const if you want another static/const variable
+to refer to one of its fields. Example:
+
+```
+struct Foo {
+    a: u32
+}
+
+const S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a; // ok!
+```
+"##,
+
 }
 
 register_diagnostics! {
index 4adaa0cab7a04e79bb4b880bcc7ab599a59360f6..fcdbd6384d543465653a66515c4b880a2184d477 100644 (file)
 
 extern crate core;
 extern crate rustc;
+extern crate rustc_front;
 
+#[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
 pub mod diagnostics;
+
 pub mod const_fn;
+pub mod consts;
+pub mod loops;
 pub mod no_asm;
+pub mod rvalues;
+pub mod static_recursion;
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
new file mode 100644 (file)
index 0000000..eb2e445
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+use self::Context::*;
+
+use rustc::session::Session;
+
+use syntax::codemap::Span;
+use rustc_front::intravisit::{self, Visitor};
+use rustc_front::hir;
+
+#[derive(Clone, Copy, PartialEq)]
+enum Context {
+    Normal, Loop, Closure
+}
+
+#[derive(Copy, Clone)]
+struct CheckLoopVisitor<'a> {
+    sess: &'a Session,
+    cx: Context
+}
+
+pub fn check_crate(sess: &Session, krate: &hir::Crate) {
+    krate.visit_all_items(&mut CheckLoopVisitor { sess: sess, cx: Normal });
+}
+
+impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
+    fn visit_item(&mut self, i: &hir::Item) {
+        self.with_context(Normal, |v| intravisit::walk_item(v, i));
+    }
+
+    fn visit_expr(&mut self, e: &hir::Expr) {
+        match e.node {
+            hir::ExprWhile(ref e, ref b, _) => {
+                self.visit_expr(&**e);
+                self.with_context(Loop, |v| v.visit_block(&**b));
+            }
+            hir::ExprLoop(ref b, _) => {
+                self.with_context(Loop, |v| v.visit_block(&**b));
+            }
+            hir::ExprClosure(_, _, ref b) => {
+                self.with_context(Closure, |v| v.visit_block(&**b));
+            }
+            hir::ExprBreak(_) => self.require_loop("break", e.span),
+            hir::ExprAgain(_) => self.require_loop("continue", e.span),
+            _ => intravisit::walk_expr(self, e)
+        }
+    }
+}
+
+impl<'a> CheckLoopVisitor<'a> {
+    fn with_context<F>(&mut self, cx: Context, f: F) where
+        F: FnOnce(&mut CheckLoopVisitor<'a>),
+    {
+        let old_cx = self.cx;
+        self.cx = cx;
+        f(self);
+        self.cx = old_cx;
+    }
+
+    fn require_loop(&self, name: &str, span: Span) {
+        match self.cx {
+            Loop => {}
+            Closure => {
+                span_err!(self.sess, span, E0267,
+                                   "`{}` inside of a closure", name);
+            }
+            Normal => {
+                span_err!(self.sess, span, E0268,
+                                   "`{}` outside of loop", name);
+            }
+        }
+    }
+}
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
new file mode 100644 (file)
index 0000000..f5cc020
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks that all rvalues in a crate have statically known size. check_crate
+// is the public starting point.
+
+use rustc::dep_graph::DepNode;
+use rustc::middle::expr_use_visitor as euv;
+use rustc::middle::infer;
+use rustc::middle::mem_categorization as mc;
+use rustc::middle::ty::{self, ParameterEnvironment};
+
+use rustc_front::hir;
+use rustc_front::intravisit;
+use syntax::ast;
+use syntax::codemap::Span;
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    let mut rvcx = RvalueContext { tcx: tcx };
+    tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
+}
+
+struct RvalueContext<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+}
+
+impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
+    fn visit_fn(&mut self,
+                fk: intravisit::FnKind<'v>,
+                fd: &'v hir::FnDecl,
+                b: &'v hir::Block,
+                s: Span,
+                fn_id: ast::NodeId) {
+        {
+            // FIXME (@jroesch) change this to be an inference context
+            let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
+            let infcx = infer::new_infer_ctxt(self.tcx,
+                                              &self.tcx.tables,
+                                              Some(param_env.clone()));
+            let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
+            let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx);
+            euv.walk_fn(fd, b);
+        }
+        intravisit::walk_fn(self, fk, fd, b, s)
+    }
+}
+
+struct RvalueContextDelegate<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    param_env: &'a ty::ParameterEnvironment<'a,'tcx>,
+}
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
+    fn consume(&mut self,
+               _: ast::NodeId,
+               span: Span,
+               cmt: mc::cmt<'tcx>,
+               _: euv::ConsumeMode) {
+        debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
+        if !cmt.ty.is_sized(self.param_env, span) {
+            span_err!(self.tcx.sess, span, E0161,
+                "cannot move a value of type {0}: the size of {0} cannot be statically determined",
+                cmt.ty);
+        }
+    }
+
+    fn matched_pat(&mut self,
+                   _matched_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::MatchMode) {}
+
+    fn consume_pat(&mut self,
+                   _consume_pat: &hir::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::ConsumeMode) {
+    }
+
+    fn borrow(&mut self,
+              _borrow_id: ast::NodeId,
+              _borrow_span: Span,
+              _cmt: mc::cmt,
+              _loan_region: ty::Region,
+              _bk: ty::BorrowKind,
+              _loan_cause: euv::LoanCause) {
+    }
+
+    fn decl_without_init(&mut self,
+                         _id: ast::NodeId,
+                         _span: Span) {
+    }
+
+    fn mutate(&mut self,
+              _assignment_id: ast::NodeId,
+              _assignment_span: Span,
+              _assignee_cmt: mc::cmt,
+              _mode: euv::MutateMode) {
+    }
+}
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
new file mode 100644 (file)
index 0000000..b49db16
--- /dev/null
@@ -0,0 +1,290 @@
+// 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.
+
+// This compiler pass detects constants that refer to themselves
+// recursively.
+
+use rustc::front::map as ast_map;
+use rustc::session::Session;
+use rustc::middle::def::{Def, DefMap};
+use rustc::util::nodemap::NodeMap;
+
+use syntax::{ast};
+use syntax::codemap::Span;
+use syntax::feature_gate::{GateIssue, emit_feature_err};
+use rustc_front::intravisit::{self, Visitor};
+use rustc_front::hir;
+
+use std::cell::RefCell;
+
+struct CheckCrateVisitor<'a, 'ast: 'a> {
+    sess: &'a Session,
+    def_map: &'a DefMap,
+    ast_map: &'a ast_map::Map<'ast>,
+    // `discriminant_map` is a cache that associates the `NodeId`s of local
+    // variant definitions with the discriminant expression that applies to
+    // each one. If the variant uses the default values (starting from `0`),
+    // then `None` is stored.
+    discriminant_map: RefCell<NodeMap<Option<&'ast hir::Expr>>>,
+}
+
+impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
+        match it.node {
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &it.span);
+                recursion_visitor.visit_item(it);
+            },
+            hir::ItemEnum(ref enum_def, ref generics) => {
+                // We could process the whole enum, but handling the variants
+                // with discriminant expressions one by one gives more specific,
+                // less redundant output.
+                for variant in &enum_def.variants {
+                    if let Some(_) = variant.node.disr_expr {
+                        let mut recursion_visitor =
+                            CheckItemRecursionVisitor::new(self, &variant.span);
+                        recursion_visitor.populate_enum_discriminants(enum_def);
+                        recursion_visitor.visit_variant(variant, generics, it.id);
+                    }
+                }
+            }
+            _ => {}
+        }
+        intravisit::walk_item(self, it)
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        match ti.node {
+            hir::ConstTraitItem(_, ref default) => {
+                if let Some(_) = *default {
+                    let mut recursion_visitor =
+                        CheckItemRecursionVisitor::new(self, &ti.span);
+                    recursion_visitor.visit_trait_item(ti);
+                }
+            }
+            _ => {}
+        }
+        intravisit::walk_trait_item(self, ti)
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        match ii.node {
+            hir::ImplItemKind::Const(..) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &ii.span);
+                recursion_visitor.visit_impl_item(ii);
+            }
+            _ => {}
+        }
+        intravisit::walk_impl_item(self, ii)
+    }
+}
+
+pub fn check_crate<'ast>(sess: &Session,
+                         krate: &'ast hir::Crate,
+                         def_map: &DefMap,
+                         ast_map: &ast_map::Map<'ast>) {
+    let mut visitor = CheckCrateVisitor {
+        sess: sess,
+        def_map: def_map,
+        ast_map: ast_map,
+        discriminant_map: RefCell::new(NodeMap()),
+    };
+    sess.abort_if_new_errors(|| {
+        krate.visit_all_items(&mut visitor);
+    });
+}
+
+struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
+    root_span: &'a Span,
+    sess: &'a Session,
+    ast_map: &'a ast_map::Map<'ast>,
+    def_map: &'a DefMap,
+    discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
+    idstack: Vec<ast::NodeId>,
+}
+
+impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
+    fn new(v: &'a CheckCrateVisitor<'a, 'ast>, span: &'a Span)
+           -> CheckItemRecursionVisitor<'a, 'ast> {
+        CheckItemRecursionVisitor {
+            root_span: span,
+            sess: v.sess,
+            ast_map: v.ast_map,
+            def_map: v.def_map,
+            discriminant_map: &v.discriminant_map,
+            idstack: Vec::new(),
+        }
+    }
+    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
+          where F: Fn(&mut Self) {
+        if self.idstack.iter().any(|&x| x == id) {
+            let any_static = self.idstack.iter().any(|&x| {
+                if let ast_map::NodeItem(item) = self.ast_map.get(x) {
+                    if let hir::ItemStatic(..) = item.node {
+                        true
+                    } else {
+                        false
+                    }
+                } else {
+                    false
+                }
+            });
+            if any_static {
+                if !self.sess.features.borrow().static_recursion {
+                    emit_feature_err(&self.sess.parse_sess.span_diagnostic,
+                                     "static_recursion",
+                                     *self.root_span, GateIssue::Language, "recursive static");
+                }
+            } else {
+                span_err!(self.sess, *self.root_span, E0265, "recursive constant");
+            }
+            return;
+        }
+        self.idstack.push(id);
+        f(self);
+        self.idstack.pop();
+    }
+    // If a variant has an expression specifying its discriminant, then it needs
+    // to be checked just like a static or constant. However, if there are more
+    // variants with no explicitly specified discriminant, those variants will
+    // increment the same expression to get their values.
+    //
+    // So for every variant, we need to track whether there is an expression
+    // somewhere in the enum definition that controls its discriminant. We do
+    // this by starting from the end and searching backward.
+    fn populate_enum_discriminants(&self, enum_definition: &'ast hir::EnumDef) {
+        // Get the map, and return if we already processed this enum or if it
+        // has no variants.
+        let mut discriminant_map = self.discriminant_map.borrow_mut();
+        match enum_definition.variants.first() {
+            None => { return; }
+            Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => {
+                return;
+            }
+            _ => {}
+        }
+
+        // Go through all the variants.
+        let mut variant_stack: Vec<ast::NodeId> = Vec::new();
+        for variant in enum_definition.variants.iter().rev() {
+            variant_stack.push(variant.node.data.id());
+            // When we find an expression, every variant currently on the stack
+            // is affected by that expression.
+            if let Some(ref expr) = variant.node.disr_expr {
+                for id in &variant_stack {
+                    discriminant_map.insert(*id, Some(expr));
+                }
+                variant_stack.clear()
+            }
+        }
+        // If we are at the top, that always starts at 0, so any variant on the
+        // stack has a default value and does not need to be checked.
+        for id in &variant_stack {
+            discriminant_map.insert(*id, None);
+        }
+    }
+}
+
+impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
+    fn visit_item(&mut self, it: &'ast hir::Item) {
+        self.with_item_id_pushed(it.id, |v| intravisit::walk_item(v, it));
+    }
+
+    fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
+                      generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) {
+        self.populate_enum_discriminants(enum_definition);
+        intravisit::walk_enum_def(self, enum_definition, generics, item_id);
+    }
+
+    fn visit_variant(&mut self, variant: &'ast hir::Variant,
+                     _: &'ast hir::Generics, _: ast::NodeId) {
+        let variant_id = variant.node.data.id();
+        let maybe_expr;
+        if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
+            // This is necessary because we need to let the `discriminant_map`
+            // borrow fall out of scope, so that we can reborrow farther down.
+            maybe_expr = (*get_expr).clone();
+        } else {
+            self.sess.span_bug(variant.span,
+                               "`check_static_recursion` attempted to visit \
+                                variant with unknown discriminant")
+        }
+        // If `maybe_expr` is `None`, that's because no discriminant is
+        // specified that affects this variant. Thus, no risk of recursion.
+        if let Some(expr) = maybe_expr {
+            self.with_item_id_pushed(expr.id, |v| intravisit::walk_expr(v, expr));
+        }
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) {
+        self.with_item_id_pushed(ti.id, |v| intravisit::walk_trait_item(v, ti));
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
+        self.with_item_id_pushed(ii.id, |v| intravisit::walk_impl_item(v, ii));
+    }
+
+    fn visit_expr(&mut self, e: &'ast hir::Expr) {
+        match e.node {
+            hir::ExprPath(..) => {
+                match self.def_map.get(&e.id).map(|d| d.base_def) {
+                    Some(Def::Static(def_id, _)) |
+                    Some(Def::AssociatedConst(def_id)) |
+                    Some(Def::Const(def_id)) => {
+                        if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
+                            match self.ast_map.get(node_id) {
+                                ast_map::NodeItem(item) =>
+                                    self.visit_item(item),
+                                ast_map::NodeTraitItem(item) =>
+                                    self.visit_trait_item(item),
+                                ast_map::NodeImplItem(item) =>
+                                    self.visit_impl_item(item),
+                                ast_map::NodeForeignItem(_) => {},
+                                _ => {
+                                    self.sess.span_bug(
+                                        e.span,
+                                        &format!("expected item, found {}",
+                                                 self.ast_map.node_to_string(node_id)));
+                                }
+                            }
+                        }
+                    }
+                    // For variants, we only want to check expressions that
+                    // affect the specific variant used, but we need to check
+                    // the whole enum definition to see what expression that
+                    // might be (if any).
+                    Some(Def::Variant(enum_id, variant_id)) => {
+                        if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) {
+                            if let hir::ItemEnum(ref enum_def, ref generics) =
+                                self.ast_map.expect_item(enum_node_id).node
+                            {
+                                self.populate_enum_discriminants(enum_def);
+                                let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap();
+                                let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap();
+                                let variant = self.ast_map.expect_variant(variant_id);
+                                self.visit_variant(variant, generics, enum_id);
+                            } else {
+                                self.sess.span_bug(e.span,
+                                                   "`check_static_recursion` found \
+                                                    non-enum in Def::Variant");
+                            }
+                        }
+                    }
+                    _ => ()
+                }
+            },
+            _ => ()
+        }
+        intravisit::walk_expr(self, e);
+    }
+}
index d3da93a3e080d53508928af23f0c8b0068568b03..cfd0540cc60e782227f5430e270e76c9c07f5f69 100644 (file)
@@ -37,7 +37,7 @@
 
 use rustc::dep_graph::DepNode;
 use rustc::lint;
-use rustc::middle::def;
+use rustc::middle::def::{self, Def};
 use rustc::middle::def_id::DefId;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::middle::privacy::ImportUse::*;
@@ -172,7 +172,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
         if let hir::TyPath(..) = ty.node {
             match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
+                Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     Some(AccessLevel::Public)
                 }
                 def => {
@@ -294,7 +294,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             hir::ItemTy(ref ty, _) if item_level.is_some() => {
                 if let hir::TyPath(..) = ty.node {
                     match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                        def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {},
+                        Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {},
                         def => {
                             if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
                                 self.update(node_id, Some(AccessLevel::Reachable));
@@ -806,17 +806,17 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) {
         // be accurate and we can get slightly wonky error messages (but type
         // checking is always correct).
         match path_res.full_def() {
-            def::DefFn(..) => ck("function"),
-            def::DefStatic(..) => ck("static"),
-            def::DefConst(..) => ck("const"),
-            def::DefAssociatedConst(..) => ck("associated const"),
-            def::DefVariant(..) => ck("variant"),
-            def::DefTy(_, false) => ck("type"),
-            def::DefTy(_, true) => ck("enum"),
-            def::DefTrait(..) => ck("trait"),
-            def::DefStruct(..) => ck("struct"),
-            def::DefMethod(..) => ck("method"),
-            def::DefMod(..) => ck("module"),
+            Def::Fn(..) => ck("function"),
+            Def::Static(..) => ck("static"),
+            Def::Const(..) => ck("const"),
+            Def::AssociatedConst(..) => ck("associated const"),
+            Def::Variant(..) => ck("variant"),
+            Def::TyAlias(..) => ck("type"),
+            Def::Enum(..) => ck("enum"),
+            Def::Trait(..) => ck("trait"),
+            Def::Struct(..) => ck("struct"),
+            Def::Method(..) => ck("method"),
+            Def::Mod(..) => ck("module"),
             _ => {}
         }
     }
@@ -887,7 +887,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
             }
             hir::ExprPath(..) => {
 
-                if let def::DefStruct(_) = self.tcx.resolve_expr(expr) {
+                if let Def::Struct(..) = self.tcx.resolve_expr(expr) {
                     let expr_ty = self.tcx.expr_ty(expr);
                     let def = match expr_ty.sty {
                         ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
@@ -1132,7 +1132,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
         let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
             // `int` etc. (None doesn't seem to occur.)
-            None | Some(def::DefPrimTy(..)) | Some(def::DefSelfTy(..)) => return false,
+            None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => return false,
             Some(def) => def.def_id(),
         };
 
@@ -1503,10 +1503,10 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
         if let hir::TyPath(_, ref path) = ty.node {
             let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
             match def {
-                def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
+                Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     // Public
                 }
-                def::DefAssociatedTy(..) if self.is_quiet => {
+                Def::AssociatedTy(..) if self.is_quiet => {
                     // Conservatively approximate the whole type alias as public without
                     // recursing into its components when determining impl publicity.
                     // For example, `impl <Type as Trait>::Alias {...}` may be a public impl
@@ -1515,8 +1515,8 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
                     // free type aliases, but this isn't done yet.
                     return
                 }
-                def::DefStruct(def_id) | def::DefTy(def_id, _) |
-                def::DefTrait(def_id) | def::DefAssociatedTy(def_id, _) => {
+                Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
+                Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
                     // Non-local means public (private items can't leave their crate, modulo bugs)
                     if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
                         let item = self.tcx.map.expect_item(node_id);
index 2e713a2f50e0fcdb0d5dfe08db3c54f2107f20ab..22c18c9d6a43cdab32f32031ca611b20a435ec9b 100644 (file)
@@ -31,6 +31,7 @@
 use rustc::middle::cstore::{CrateStore, ChildItem, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
 use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::middle::ty::VariantKind;
 
 use syntax::ast::{Name, NodeId};
 use syntax::attr::AttrMetaMethods;
@@ -315,7 +316,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                     };
                     self.external_exports.insert(def_id);
                     let parent_link = ModuleParentLink(parent, name);
-                    let def = DefMod(def_id);
+                    let def = Def::Mod(def_id);
                     let external_module = self.new_module(parent_link, Some(def), false, true);
 
                     debug!("(build reduced graph for item) found extern `{}`",
@@ -333,7 +334,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateTypes, sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefMod(self.ast_map.local_def_id(item.id));
+                let def = Def::Mod(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
                 module
@@ -346,20 +347,20 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
                 let mutbl = m == hir::MutMutable;
 
-                name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl),
+                name_bindings.define_value(Def::Static(self.ast_map.local_def_id(item.id), mutbl),
                                            sp,
                                            modifiers);
                 parent
             }
             ItemConst(_, _) => {
                 self.add_child(name, parent, ForbidDuplicateValues, sp)
-                    .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers);
+                    .define_value(Def::Const(self.ast_map.local_def_id(item.id)), sp, modifiers);
                 parent
             }
             ItemFn(_, _, _, _, _, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
 
-                let def = DefFn(self.ast_map.local_def_id(item.id), false);
+                let def = Def::Fn(self.ast_map.local_def_id(item.id));
                 name_bindings.define_value(def, sp, modifiers);
                 parent
             }
@@ -372,7 +373,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                                                    sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTy(self.ast_map.local_def_id(item.id), false);
+                let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module, sp);
                 parent
@@ -385,7 +386,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                                                    sp);
 
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTy(self.ast_map.local_def_id(item.id), true);
+                let def = Def::Enum(self.ast_map.local_def_id(item.id));
                 let module = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module.clone(), sp);
 
@@ -414,14 +415,14 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
                 let name_bindings = self.add_child(name, parent, forbid, sp);
 
                 // Define a name in the type namespace.
-                name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false),
+                name_bindings.define_type(Def::Struct(self.ast_map.local_def_id(item.id)),
                                           sp,
                                           modifiers);
 
                 // If this is a newtype or unit-like struct, define a name
                 // in the value namespace as well
                 if let Some(cid) = ctor_id {
-                    name_bindings.define_value(DefStruct(self.ast_map.local_def_id(cid)),
+                    name_bindings.define_value(Def::Struct(self.ast_map.local_def_id(cid)),
                                                sp,
                                                modifiers);
                 }
@@ -455,7 +456,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
 
                 // Add all the items within to a new module.
                 let parent_link = ModuleParentLink(parent, name);
-                let def = DefTrait(def_id);
+                let def = Def::Trait(def_id);
                 let module_parent = self.new_module(parent_link, Some(def), false, is_public);
                 name_bindings.define_module(module_parent.clone(), sp);
 
@@ -468,17 +469,18 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: Module<'b>) -> M
 
                     match trait_item.node {
                         hir::ConstTraitItem(..) => {
-                            let def = DefAssociatedConst(self.ast_map.local_def_id(trait_item.id));
+                            let def = Def::AssociatedConst(self.ast_map.
+                                                                local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::MethodTraitItem(..) => {
-                            let def = DefMethod(self.ast_map.local_def_id(trait_item.id));
+                            let def = Def::Method(self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::TypeTraitItem(..) => {
-                            let def = DefAssociatedTy(self.ast_map.local_def_id(item.id),
+                            let def = Def::AssociatedTy(self.ast_map.local_def_id(item.id),
                                                       self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
@@ -502,26 +504,19 @@ fn build_reduced_graph_for_variant(&mut self,
                                        parent: Module<'b>,
                                        variant_modifiers: DefModifiers) {
         let name = variant.node.name;
-        let is_exported = if variant.node.data.is_struct() {
+        if variant.node.data.is_struct() {
             // Not adding fields for variants as they are not accessed with a self receiver
             let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
             self.structs.insert(variant_def_id, Vec::new());
-            true
-        } else {
-            false
-        };
+        }
 
+        // Variants are always treated as importable to allow them to be glob used.
+        // All variants are defined in both type and value namespaces as future-proofing.
         let child = self.add_child(name, parent, ForbidDuplicateTypesAndValues, variant.span);
-        // variants are always treated as importable to allow them to be glob
-        // used
-        child.define_value(DefVariant(item_id,
-                                      self.ast_map.local_def_id(variant.node.data.id()),
-                                      is_exported),
+        child.define_value(Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id())),
                            variant.span,
                            DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
-        child.define_type(DefVariant(item_id,
-                                     self.ast_map.local_def_id(variant.node.data.id()),
-                                     is_exported),
+        child.define_type(Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id())),
                           variant.span,
                           DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
     }
@@ -541,10 +536,10 @@ fn build_reduced_graph_for_foreign_item(&mut self,
 
         let def = match foreign_item.node {
             ForeignItemFn(..) => {
-                DefFn(self.ast_map.local_def_id(foreign_item.id), false)
+                Def::Fn(self.ast_map.local_def_id(foreign_item.id))
             }
             ForeignItemStatic(_, m) => {
-                DefStatic(self.ast_map.local_def_id(foreign_item.id), m)
+                Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
             }
         };
         name_bindings.define_value(def, foreign_item.span, modifiers);
@@ -591,12 +586,18 @@ fn handle_external_def(&mut self,
         if is_exported {
             self.external_exports.insert(def.def_id());
         }
+        let is_struct_ctor = if let Def::Struct(def_id) = def {
+            self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_some()
+        } else {
+            false
+        };
 
         match def {
-            DefMod(_) |
-            DefForeignMod(_) |
-            DefStruct(_) |
-            DefTy(..) => {
+            Def::Mod(_) |
+            Def::ForeignMod(_) |
+            Def::Struct(..) |
+            Def::Enum(..) |
+            Def::TyAlias(..) if !is_struct_ctor => {
                 if let Some(module_def) = child_name_bindings.type_ns.module() {
                     debug!("(building reduced graph for external crate) already created module");
                     module_def.def.set(Some(def));
@@ -613,31 +614,25 @@ fn handle_external_def(&mut self,
         }
 
         match def {
-            DefMod(_) | DefForeignMod(_) => {}
-            DefVariant(_, variant_id, is_struct) => {
+            Def::Mod(_) | Def::ForeignMod(_) => {}
+            Def::Variant(_, variant_id) => {
                 debug!("(building reduced graph for external crate) building variant {}",
                        final_ident);
-                // variants are always treated as importable to allow them to be
-                // glob used
+                // Variants are always treated as importable to allow them to be glob used.
+                // All variants are defined in both type and value namespaces as future-proofing.
                 let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
-                if is_struct {
-                    child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+                child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+                child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+                if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
                     // Not adding fields for variants as they are not accessed with a self receiver
                     self.structs.insert(variant_id, Vec::new());
-                } else {
-                    child_name_bindings.define_value(def, DUMMY_SP, modifiers);
                 }
             }
-            DefFn(ctor_id, true) => {
-                child_name_bindings.define_value(
-                self.session.cstore.tuple_struct_definition_if_ctor(ctor_id)
-                    .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
-            }
-            DefFn(..) |
-            DefStatic(..) |
-            DefConst(..) |
-            DefAssociatedConst(..) |
-            DefMethod(..) => {
+            Def::Fn(..) |
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Method(..) => {
                 debug!("(building reduced graph for external crate) building value (fn/static) {}",
                        final_ident);
                 // impl methods have already been defined with the correct importability
@@ -652,7 +647,7 @@ fn handle_external_def(&mut self,
                 }
                 child_name_bindings.define_value(def, DUMMY_SP, modifiers);
             }
-            DefTrait(def_id) => {
+            Def::Trait(def_id) => {
                 debug!("(building reduced graph for external crate) building type {}",
                        final_ident);
 
@@ -680,7 +675,7 @@ fn handle_external_def(&mut self,
                 let module = self.new_module(parent_link, Some(def), true, is_public);
                 child_name_bindings.define_module(module, DUMMY_SP);
             }
-            DefTy(..) | DefAssociatedTy(..) => {
+            Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) => {
                 debug!("(building reduced graph for external crate) building type {}",
                        final_ident);
 
@@ -689,33 +684,38 @@ fn handle_external_def(&mut self,
                     _ => modifiers & !DefModifiers::IMPORTABLE,
                 };
 
-                if let DefTy(..) = def {
+                if let Def::Enum(..) = def {
+                    child_name_bindings.type_ns.set_modifiers(modifiers);
+                } else if let Def::TyAlias(..) = def {
                     child_name_bindings.type_ns.set_modifiers(modifiers);
                 } else {
                     child_name_bindings.define_type(def, DUMMY_SP, modifiers);
                 }
             }
-            DefStruct(def_id) => {
+            Def::Struct(..) if is_struct_ctor => {
+                // Do nothing
+            }
+            Def::Struct(def_id) => {
                 debug!("(building reduced graph for external crate) building type and value for \
                         {}",
                        final_ident);
-                child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-                let fields = self.session.cstore.struct_field_names(def_id);
 
-                if fields.is_empty() {
-                    child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+                child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+                if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
+                    child_name_bindings.define_value(Def::Struct(ctor_def_id), DUMMY_SP, modifiers);
                 }
 
                 // Record the def ID and fields of this struct.
+                let fields = self.session.cstore.struct_field_names(def_id);
                 self.structs.insert(def_id, fields);
             }
-            DefLocal(..) |
-            DefPrimTy(..) |
-            DefTyParam(..) |
-            DefUpvar(..) |
-            DefLabel(..) |
-            DefSelfTy(..) |
-            DefErr => {
+            Def::Local(..) |
+            Def::PrimTy(..) |
+            Def::TyParam(..) |
+            Def::Upvar(..) |
+            Def::Label(..) |
+            Def::SelfTy(..) |
+            Def::Err => {
                 panic!("didn't expect `{:?}`", def);
             }
         }
@@ -729,7 +729,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
             DlDef(def) => {
                 // Add the new child item, if necessary.
                 match def {
-                    DefForeignMod(def_id) => {
+                    Def::ForeignMod(def_id) => {
                         // Foreign modules have no names. Recur and populate
                         // eagerly.
                         for child in self.session.cstore.item_children(def_id) {
index 04ab3fe70e9fabdea01732ec67a15b205bf09c21..dc6da1f0ef847044254a47e52aa7d018b379c505 100644 (file)
@@ -207,7 +207,41 @@ fn main() {}
 E0317: r##"
 User-defined types or type parameters cannot shadow the primitive types.
 This error indicates you tried to define a type, struct or enum with the same
-name as an existing primitive type.
+name as an existing primitive type:
+
+```
+struct u8 {
+    // ...
+}
+```
+
+To fix this, simply name it something else.
+
+Such an error may also occur if you define a type parameter which shadows a
+primitive type. An example would be something like:
+
+```
+impl<u8> MyTrait for Option<u8> {
+    // ...
+}
+```
+
+In such a case, if you meant for `u8` to be a generic type parameter (i.e. any
+type can be used in its place), use something like `T` instead:
+
+```
+impl<T> MyTrait for Option<T> {
+    // ...
+}
+```
+
+On the other hand, if you wished to refer to the specific type `u8`, remove it
+from the type parameter list:
+
+```
+impl MyTrait for Option<u8> {
+    // ...
+}
 
 See the Types section of the reference for more information about the primitive
 types:
index 8464d3ef298708187449cd32d5cd78b6ff86b477..444c43163e3c3ad4f1113e8b463ab98c4e0be5cf 100644 (file)
@@ -737,7 +737,7 @@ enum TypeParameters<'a> {
 }
 
 // The rib kind controls the translation of local
-// definitions (`DefLocal`) to upvars (`DefUpvar`).
+// definitions (`Def::Local`) to upvars (`Def::Upvar`).
 #[derive(Copy, Clone, Debug)]
 enum RibKind {
     // No translation needs to be applied.
@@ -913,14 +913,14 @@ fn def_id(&self) -> Option<DefId> {
 
     fn is_normal(&self) -> bool {
         match self.def.get() {
-            Some(DefMod(_)) | Some(DefForeignMod(_)) => true,
+            Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
             _ => false,
         }
     }
 
     fn is_trait(&self) -> bool {
         match self.def.get() {
-            Some(DefTrait(_)) => true,
+            Some(Def::Trait(_)) => true,
             _ => false,
         }
     }
@@ -1243,7 +1243,7 @@ fn new(session: &'a Session,
            arenas: &'a ResolverArenas<'a>)
            -> Resolver<'a, 'tcx> {
         let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
-        let graph_root = ModuleS::new(NoParentLink, Some(DefMod(root_def_id)), false, true);
+        let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, true);
         let graph_root = arenas.modules.alloc(graph_root);
 
         Resolver {
@@ -2020,7 +2020,7 @@ fn resolve_item(&mut self, item: &Item) {
                                                                ItemRibKind),
                                              |this| {
                     let local_def_id = this.ast_map.local_def_id(item.id);
-                    this.with_self_rib(DefSelfTy(Some(local_def_id), None), |this| {
+                    this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_ty_param_bound, bounds);
 
@@ -2076,7 +2076,8 @@ fn resolve_item(&mut self, item: &Item) {
                 // check for imports shadowing primitive types
                 let check_rename = |this: &Self, id, name| {
                     match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
-                        Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
+                        Some(Def::Enum(..)) | Some(Def::TyAlias(..)) | Some(Def::Struct(..)) |
+                        Some(Def::Trait(..)) | None => {
                             this.check_if_primitive_type_name(name, item.span);
                         }
                         _ => {}
@@ -2142,7 +2143,7 @@ fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
                     // plain insert (no renaming)
                     function_type_rib.bindings
                                      .insert(name,
-                                             DlDef(DefTyParam(space,
+                                             DlDef(Def::TyParam(space,
                                                               index as u32,
                                                               self.ast_map
                                                                   .local_def_id(type_parameter.id),
@@ -2225,7 +2226,7 @@ fn resolve_trait_reference(&mut self,
                                path_depth: usize)
                                -> Result<PathResolution, ()> {
         if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
-            if let DefTrait(_) = path_res.base_def {
+            if let Def::Trait(_) = path_res.base_def {
                 debug!("(resolving trait) found trait def: {:?}", path_res);
                 Ok(path_res)
             } else {
@@ -2236,7 +2237,7 @@ fn resolve_trait_reference(&mut self,
                                                                                       path_depth)));
 
                 // If it's a typedef, give a note
-                if let DefTy(..) = path_res.base_def {
+                if let Def::TyAlias(..) = path_res.base_def {
                     err.span_note(trait_path.span,
                                   "`type` aliases cannot be used for traits");
                 }
@@ -2262,7 +2263,7 @@ fn resolve_generics(&mut self, generics: &Generics) {
                 &hir::WherePredicate::RegionPredicate(_) => {}
                 &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                     let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
-                    if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
+                    if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res {
                         self.record_def(eq_pred.id, path_res.unwrap());
                     } else {
                         resolve_error(self,
@@ -2344,7 +2345,7 @@ fn resolve_implementation(&mut self,
                 // Resolve the self type.
                 this.visit_ty(self_type);
 
-                this.with_self_rib(DefSelfTy(trait_id, Some((item_id, self_type.id))), |this| {
+                this.with_self_rib(Def::SelfTy(trait_id, Some((item_id, self_type.id))), |this| {
                     this.with_current_self_type(self_type, |this| {
                         for impl_item in impl_items {
                             match impl_item.node {
@@ -2680,7 +2681,7 @@ fn resolve_pattern(&mut self,
                             debug!("(resolving pattern) binding `{}`", renamed);
 
                             let def_id = self.ast_map.local_def_id(pattern.id);
-                            let def = DefLocal(def_id, pattern.id);
+                            let def = Def::Local(def_id, pattern.id);
 
                             // Record the definition so that later passes
                             // will be able to distinguish variants from
@@ -2751,10 +2752,13 @@ fn resolve_pattern(&mut self,
                     };
                     if let Some(path_res) = resolution {
                         match path_res.base_def {
-                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
+                            Def::Struct(..) if path_res.depth == 0 => {
                                 self.record_def(pattern.id, path_res);
                             }
-                            DefStatic(..) => {
+                            Def::Variant(..) | Def::Const(..) => {
+                                self.record_def(pattern.id, path_res);
+                            }
+                            Def::Static(..) => {
                                 resolve_error(&self,
                                               path.span,
                                               ResolutionError::StaticVariableReference);
@@ -2829,7 +2833,7 @@ fn resolve_pattern(&mut self,
                         match path_res.base_def {
                             // All `<T as Trait>::CONST` should end up here, and
                             // have the trait already selected.
-                            DefAssociatedConst(..) => {
+                            Def::AssociatedConst(..) => {
                                 self.record_def(pattern.id, path_res);
                             }
                             _ => {
@@ -2906,13 +2910,13 @@ fn resolve_bare_identifier_pattern(&mut self,
                     // For the two success cases, this lookup can be
                     // considered as not having a private component because
                     // the lookup happened only within the current module.
-                    Some(def @ DefVariant(..)) | Some(def @ DefStruct(..)) => {
+                    Some(def @ Def::Variant(..)) | Some(def @ Def::Struct(..)) => {
                         return FoundStructOrEnumVariant(def, LastMod(AllPublic));
                     }
-                    Some(def @ DefConst(..)) | Some(def @ DefAssociatedConst(..)) => {
+                    Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
                         return FoundConst(def, LastMod(AllPublic), name);
                     }
-                    Some(DefStatic(..)) => {
+                    Some(Def::Static(..)) => {
                         resolve_error(self, span, ResolutionError::StaticVariableReference);
                         return BareIdentifierPatternUnresolved;
                     }
@@ -2972,7 +2976,7 @@ fn resolve_possibly_assoc_item(&mut self,
                 resolution = this.resolve_path(id, path, depth, TypeNS, true);
             });
         }
-        if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+        if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) {
             // A module is not a valid type or value.
             resolution = None;
         }
@@ -3038,7 +3042,7 @@ fn resolve_identifier(&mut self,
             if let Some(&prim_ty) = self.primitive_type_table
                                         .primitive_types
                                         .get(&identifier.unhygienic_name) {
-                return Some(LocalDef::from_def(DefPrimTy(prim_ty)));
+                return Some(LocalDef::from_def(Def::PrimTy(prim_ty)));
             }
         }
 
@@ -3062,10 +3066,10 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
         };
         let mut def = local_def.def;
         match def {
-            DefUpvar(..) => {
+            Def::Upvar(..) => {
                 self.session.span_bug(span, &format!("unexpected {:?} in bindings", def))
             }
-            DefLocal(_, node_id) => {
+            Def::Local(_, node_id) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind => {
@@ -3079,7 +3083,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                                            .entry(function_id)
                                            .or_insert_with(|| NodeMap());
                             if let Some(&index) = seen.get(&node_id) {
-                                def = DefUpvar(node_def_id, node_id, index, function_id);
+                                def = Def::Upvar(node_def_id, node_id, index, function_id);
                                 continue;
                             }
                             let vec = self.freevars
@@ -3091,7 +3095,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                                 span: span,
                             });
 
-                            def = DefUpvar(node_def_id, node_id, depth, function_id);
+                            def = Def::Upvar(node_def_id, node_id, depth, function_id);
                             seen.insert(node_id, depth);
                         }
                         ItemRibKind | MethodRibKind => {
@@ -3113,7 +3117,7 @@ fn adjust_local_def(&mut self, local_def: LocalDef, span: Span) -> Option<Def> {
                     }
                 }
             }
-            DefTyParam(..) | DefSelfTy(..) => {
+            Def::TyParam(..) | Def::SelfTy(..) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
@@ -3425,9 +3429,10 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
         if allowed == Everything {
             // Look for a field with the same name in the current self_type.
             match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
-                Some(DefTy(did, _)) |
-                Some(DefStruct(did)) |
-                Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
+                Some(Def::Enum(did)) |
+                Some(Def::TyAlias(did)) |
+                Some(Def::Struct(did)) |
+                Some(Def::Variant(_, did)) => match self.structs.get(&did) {
                     None => {}
                     Some(fields) => {
                         if fields.iter().any(|&field_name| name == field_name) {
@@ -3444,7 +3449,7 @@ fn is_static_method(this: &Resolver, did: DefId) -> bool {
         // Look for a method in the current self type's impl module.
         if let Some(module) = get_module(self, path.span, &name_path) {
             if let Some(binding) = module.children.borrow().get(&name) {
-                if let Some(DefMethod(did)) = binding.value_ns.def() {
+                if let Some(Def::Method(did)) = binding.value_ns.def() {
                     if is_static_method(self, did) {
                         return StaticMethod(path_names_to_string(&path, 0));
                     }
@@ -3518,7 +3523,13 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 // scopes looking for it.
                 if let Some(path_res) = resolution {
                     // Check if struct variant
-                    if let DefVariant(_, _, true) = path_res.base_def {
+                    let is_struct_variant = if let Def::Variant(_, variant_id) = path_res.base_def {
+                        self.structs.contains_key(&variant_id)
+                    } else {
+                        false
+                    };
+                    if is_struct_variant {
+                        let _ = self.structs.contains_key(&path_res.base_def.def_id());
                         let path_name = path_names_to_string(path, 0);
 
                         let mut err = resolve_struct_error(self,
@@ -3561,7 +3572,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
                     self.record_def(expr.id, err_path_resolution());
                     match type_res.map(|r| r.base_def) {
-                        Some(DefTy(struct_id, _)) if self.structs.contains_key(&struct_id) => {
+                        Some(Def::Struct(..)) => {
                             let mut err = resolve_struct_error(self,
                                 expr.span,
                                 ResolutionError::StructVariantUsedAsFunction(&*path_name));
@@ -3673,7 +3684,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
             ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
                 self.with_label_rib(|this| {
-                    let def_like = DlDef(DefLabel(expr.id));
+                    let def_like = DlDef(Def::Label(expr.id));
 
                     {
                         let rib = this.label_ribs.last_mut().unwrap();
@@ -3692,7 +3703,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                       label.span,
                                       ResolutionError::UndeclaredLabel(&label.node.name.as_str()))
                     }
-                    Some(DlDef(def @ DefLabel(_))) => {
+                    Some(DlDef(def @ Def::Label(_))) => {
                         // Since this def is a label, it is never read.
                         self.record_def(expr.id,
                                         PathResolution {
@@ -3768,7 +3779,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                         None => continue,
                     };
                     let trait_def_id = match def {
-                        DefTrait(trait_def_id) => trait_def_id,
+                        Def::Trait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
                     if self.trait_item_map.contains_key(&(name, trait_def_id)) {
@@ -3784,7 +3795,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>, trait_def_id: DefId, name: Name
                     Some(ref target) => target,
                 };
                 let did = match target.binding.def() {
-                    Some(DefTrait(trait_def_id)) => trait_def_id,
+                    Some(Def::Trait(trait_def_id)) => trait_def_id,
                     Some(..) | None => continue,
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
@@ -3939,7 +3950,7 @@ fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
 
 fn err_path_resolution() -> PathResolution {
     PathResolution {
-        base_def: DefErr,
+        base_def: Def::Err,
         last_private: LastMod(AllPublic),
         depth: 0,
     }
index abaf45cb1704d0abcf2ecf756f9306e2673b277d..7df71fadd89f2b015b623bd8fc26628c2ccc87bb 100644 (file)
@@ -852,7 +852,7 @@ fn resolve_glob_import(&mut self,
         if let Some(did) = target_module.def_id() {
             self.resolver.def_map.borrow_mut().insert(id,
                                                       PathResolution {
-                                                          base_def: DefMod(did),
+                                                          base_def: Def::Mod(did),
                                                           last_private: lp,
                                                           depth: 0,
                                                       });
index ec1383f1f7b2b19ac8b40dc4db49d3e801096b13..0f327d5c84cfd80f4f889a84c547079276f64372 100644 (file)
@@ -396,6 +396,9 @@ fn command_path(sess: &Session) -> OsString {
     if let Some(path) = env::var_os("PATH") {
         new_path.extend(env::split_paths(&path));
     }
+    if sess.target.target.options.is_like_msvc {
+        new_path.extend(msvc::host_dll_path());
+    }
     env::join_paths(new_path).unwrap()
 }
 
@@ -490,7 +493,10 @@ pub fn filename_for_input(sess: &Session,
                                                 suffix))
         }
         config::CrateTypeStaticlib => {
-            outputs.out_directory.join(&format!("lib{}.a", libname))
+            let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
+                                    &sess.target.target.options.staticlib_suffix);
+            outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
+                                                suffix))
         }
         config::CrateTypeExecutable => {
             let suffix = &sess.target.target.options.exe_suffix;
index f585c65228a825116d0e402eeb7b42f97f74d0c5..9c445737b10eefa01ea58705f216d6095658a3d4 100644 (file)
@@ -210,7 +210,14 @@ impl<'a> Linker for MsvcLinker<'a> {
     fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
     fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
     fn args(&mut self, args: &[String]) { self.cmd.args(args); }
-    fn build_dylib(&mut self, _out_filename: &Path) { self.cmd.arg("/DLL"); }
+
+    fn build_dylib(&mut self, out_filename: &Path) {
+        self.cmd.arg("/DLL");
+        let mut arg: OsString = "/IMPLIB:".into();
+        arg.push(out_filename.with_extension("dll.lib"));
+        self.cmd.arg(arg);
+    }
+
     fn gc_sections(&mut self, _is_dylib: bool) { self.cmd.arg("/OPT:REF,ICF"); }
 
     fn link_dylib(&mut self, lib: &str) {
@@ -222,7 +229,7 @@ fn link_rust_dylib(&mut self, lib: &str, path: &Path) {
         // `foo.lib` file if the dll doesn't actually export any symbols, so we
         // check to see if the file is there and just omit linking to it if it's
         // not present.
-        let name = format!("{}.lib", lib);
+        let name = format!("{}.dll.lib", lib);
         if fs::metadata(&path.join(&name)).is_ok() {
             self.cmd.arg(name);
         }
index 6f0baa86579e02438bfc494457ad03c666eb63e8..0112da57cc0a6bed711e7ee16618b85b9dc1b406 100644 (file)
 //! paths/files is based on Microsoft's logic in their vcvars bat files, but
 //! comments can also be found below leading through the various code paths.
 
-use std::process::Command;
-use session::Session;
-
 #[cfg(windows)]
 mod registry;
 
 #[cfg(windows)]
-pub fn link_exe_cmd(sess: &Session) -> Command {
+mod platform {
     use std::env;
     use std::ffi::OsString;
     use std::fs;
     use std::path::{Path, PathBuf};
-    use self::registry::{LOCAL_MACHINE};
-
-    let arch = &sess.target.target.arch;
-    let (binsub, libsub, vclibsub) =
-        match (bin_subdir(arch), lib_subdir(arch), vc_lib_subdir(arch)) {
-        (Some(x), Some(y), Some(z)) => (x, y, z),
-        _ => return Command::new("link.exe"),
-    };
+    use std::process::Command;
+    use session::Session;
+    use super::registry::{LOCAL_MACHINE};
 
-    // First we need to figure out whether the environment is already correctly
-    // configured by vcvars. We do this by looking at the environment variable
-    // `VCINSTALLDIR` which is always set by vcvars, and unlikely to be set
-    // otherwise. If it is defined, then we derive the path to `link.exe` from
-    // that and trust that everything else is configured correctly.
-    //
-    // If `VCINSTALLDIR` wasn't defined (or we couldn't find the linker where it
-    // claimed it should be), then we resort to finding everything ourselves.
-    // First we find where the latest version of MSVC is installed and what
-    // version it is. Then based on the version we find the appropriate SDKs.
-    //
-    // For MSVC 14 (VS 2015) we look for the Win10 SDK and failing that we look
-    // for the Win8.1 SDK. We also look for the Universal CRT.
-    //
-    // For MSVC 12 (VS 2013) we look for the Win8.1 SDK.
-    //
-    // For MSVC 11 (VS 2012) we look for the Win8 SDK.
-    //
-    // For all other versions the user has to execute the appropriate vcvars bat
-    // file themselves to configure the environment.
-    //
-    // If despite our best efforts we are still unable to find MSVC then we just
-    // blindly call `link.exe` and hope for the best.
-    return env::var_os("VCINSTALLDIR").and_then(|dir| {
-        debug!("Environment already configured by user. Assuming it works.");
-        let mut p = PathBuf::from(dir);
-        p.push("bin");
-        p.push(binsub);
-        p.push("link.exe");
-        if !p.is_file() { return None }
-        Some(Command::new(p))
-    }).or_else(|| {
-        get_vc_dir().and_then(|(ver, vcdir)| {
-            debug!("Found VC installation directory {:?}", vcdir);
-            let mut linker = vcdir.clone();
-            linker.push("bin");
-            linker.push(binsub);
-            linker.push("link.exe");
-            if !linker.is_file() { return None }
-            let mut cmd = Command::new(linker);
-            add_lib(&mut cmd, &vcdir.join("lib").join(vclibsub));
-            if ver == "14.0" {
-                if let Some(dir) = get_ucrt_dir() {
-                    debug!("Found Universal CRT {:?}", dir);
-                    add_lib(&mut cmd, &dir.join("ucrt").join(libsub));
-                }
-                if let Some(dir) = get_sdk10_dir() {
-                    debug!("Found Win10 SDK {:?}", dir);
-                    add_lib(&mut cmd, &dir.join("um").join(libsub));
-                } else if let Some(dir) = get_sdk81_dir() {
-                    debug!("Found Win8.1 SDK {:?}", dir);
-                    add_lib(&mut cmd, &dir.join("um").join(libsub));
-                }
-            } else if ver == "12.0" {
-                if let Some(dir) = get_sdk81_dir() {
-                    debug!("Found Win8.1 SDK {:?}", dir);
-                    add_lib(&mut cmd, &dir.join("um").join(libsub));
-                }
-            } else { // ver == "11.0"
-                if let Some(dir) = get_sdk8_dir() {
-                    debug!("Found Win8 SDK {:?}", dir);
-                    add_lib(&mut cmd, &dir.join("um").join(libsub));
-                }
-            }
-            Some(cmd)
+    // Cross toolchains depend on dlls from the host toolchain
+    // We can't just add it to the Command's PATH in `link_exe_cmd` because it
+    // is later overridden so we publicly expose it here instead
+    pub fn host_dll_path() -> Option<PathBuf> {
+        get_vc_dir().and_then(|(_, vcdir)| {
+            host_dll_subdir().map(|sub| {
+                vcdir.join("bin").join(sub)
+            })
         })
-    }).unwrap_or_else(|| {
-        debug!("Failed to locate linker.");
-        Command::new("link.exe")
-    });
+    }
+
+    pub fn link_exe_cmd(sess: &Session) -> Command {
+        let arch = &sess.target.target.arch;
+        let (binsub, libsub, vclibsub) =
+            match (bin_subdir(arch), lib_subdir(arch), vc_lib_subdir(arch)) {
+            (Some(x), Some(y), Some(z)) => (x, y, z),
+            _ => return Command::new("link.exe"),
+        };
 
+        // First we need to figure out whether the environment is already correctly
+        // configured by vcvars. We do this by looking at the environment variable
+        // `VCINSTALLDIR` which is always set by vcvars, and unlikely to be set
+        // otherwise. If it is defined, then we derive the path to `link.exe` from
+        // that and trust that everything else is configured correctly.
+        //
+        // If `VCINSTALLDIR` wasn't defined (or we couldn't find the linker where it
+        // claimed it should be), then we resort to finding everything ourselves.
+        // First we find where the latest version of MSVC is installed and what
+        // version it is. Then based on the version we find the appropriate SDKs.
+        //
+        // For MSVC 14 (VS 2015) we look for the Win10 SDK and failing that we look
+        // for the Win8.1 SDK. We also look for the Universal CRT.
+        //
+        // For MSVC 12 (VS 2013) we look for the Win8.1 SDK.
+        //
+        // For MSVC 11 (VS 2012) we look for the Win8 SDK.
+        //
+        // For all other versions the user has to execute the appropriate vcvars bat
+        // file themselves to configure the environment.
+        //
+        // If despite our best efforts we are still unable to find MSVC then we just
+        // blindly call `link.exe` and hope for the best.
+        return env::var_os("VCINSTALLDIR").and_then(|dir| {
+            debug!("Environment already configured by user. Assuming it works.");
+            let mut p = PathBuf::from(dir);
+            p.push("bin");
+            p.push(binsub);
+            p.push("link.exe");
+            if !p.is_file() { return None }
+            Some(Command::new(p))
+        }).or_else(|| {
+            get_vc_dir().and_then(|(ver, vcdir)| {
+                debug!("Found VC installation directory {:?}", vcdir);
+                let linker = vcdir.clone().join("bin").join(binsub).join("link.exe");
+                if !linker.is_file() { return None }
+                let mut cmd = Command::new(linker);
+                add_lib(&mut cmd, &vcdir.join("lib").join(vclibsub));
+                if ver == "14.0" {
+                    if let Some(dir) = get_ucrt_dir() {
+                        debug!("Found Universal CRT {:?}", dir);
+                        add_lib(&mut cmd, &dir.join("ucrt").join(libsub));
+                    }
+                    if let Some(dir) = get_sdk10_dir() {
+                        debug!("Found Win10 SDK {:?}", dir);
+                        add_lib(&mut cmd, &dir.join("um").join(libsub));
+                    } else if let Some(dir) = get_sdk81_dir() {
+                        debug!("Found Win8.1 SDK {:?}", dir);
+                        add_lib(&mut cmd, &dir.join("um").join(libsub));
+                    }
+                } else if ver == "12.0" {
+                    if let Some(dir) = get_sdk81_dir() {
+                        debug!("Found Win8.1 SDK {:?}", dir);
+                        add_lib(&mut cmd, &dir.join("um").join(libsub));
+                    }
+                } else { // ver == "11.0"
+                    if let Some(dir) = get_sdk8_dir() {
+                        debug!("Found Win8 SDK {:?}", dir);
+                        add_lib(&mut cmd, &dir.join("um").join(libsub));
+                    }
+                }
+                Some(cmd)
+            })
+        }).unwrap_or_else(|| {
+            debug!("Failed to locate linker.");
+            Command::new("link.exe")
+        });
+    }
     // A convenience function to make the above code simpler
     fn add_lib(cmd: &mut Command, lib: &Path) {
         let mut arg: OsString = "/LIBPATH:".into();
@@ -257,11 +265,23 @@ fn vc_lib_subdir(arch: &str) -> Option<&'static str> {
             _ => None,
         }
     }
+    fn host_dll_subdir() -> Option<&'static str> {
+        if cfg!(target_arch = "x86_64") { Some("amd64") }
+        else if cfg!(target_arch = "x86") { Some("") }
+        else { None }
+    }
 }
 
 // If we're not on Windows, then there's no registry to search through and MSVC
 // wouldn't be able to run, so we just call `link.exe` and hope for the best.
 #[cfg(not(windows))]
-pub fn link_exe_cmd(_sess: &Session) -> Command {
-    Command::new("link.exe")
+mod platform {
+    use std::path::PathBuf;
+    use std::process::Command;
+    use session::Session;
+    pub fn link_exe_cmd(_sess: &Session) -> Command {
+        Command::new("link.exe")
+    }
+    pub fn host_dll_path() -> Option<PathBuf> { None }
 }
+pub use self::platform::*;
index c34013a7bbbb1b56d8955e44954e748ec32ba02d..a6f8e3f10f117b4c4a29e3b95427565a83752a72 100644 (file)
@@ -32,7 +32,7 @@
 
 use session::Session;
 
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::ty;
 
@@ -239,8 +239,8 @@ fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(..) => None,
-            def::DefSelfTy(..) => None,
+            Def::PrimTy(..) => None,
+            Def::SelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
@@ -254,27 +254,28 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
         }
         let def = def_map.get(&ref_id).unwrap().full_def();
         match def {
-            def::DefMod(_) |
-            def::DefForeignMod(_) => Some(recorder::ModRef),
-            def::DefStruct(_) => Some(recorder::TypeRef),
-            def::DefTy(..) |
-            def::DefAssociatedTy(..) |
-            def::DefTrait(_) => Some(recorder::TypeRef),
-            def::DefStatic(_, _) |
-            def::DefConst(_) |
-            def::DefAssociatedConst(..) |
-            def::DefLocal(..) |
-            def::DefVariant(_, _, _) |
-            def::DefUpvar(..) => Some(recorder::VarRef),
-
-            def::DefFn(..) => Some(recorder::FnRef),
-
-            def::DefSelfTy(..) |
-            def::DefLabel(_) |
-            def::DefTyParam(..) |
-            def::DefMethod(..) |
-            def::DefPrimTy(_) |
-            def::DefErr => {
+            Def::Mod(_) |
+            Def::ForeignMod(_) => Some(recorder::ModRef),
+            Def::Struct(..) => Some(recorder::TypeRef),
+            Def::Enum(..) |
+            Def::TyAlias(..) |
+            Def::AssociatedTy(..) |
+            Def::Trait(_) => Some(recorder::TypeRef),
+            Def::Static(_, _) |
+            Def::Const(_) |
+            Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Variant(..) |
+            Def::Upvar(..) => Some(recorder::VarRef),
+
+            Def::Fn(..) => Some(recorder::FnRef),
+
+            Def::SelfTy(..) |
+            Def::Label(_) |
+            Def::TyParam(..) |
+            Def::Method(..) |
+            Def::PrimTy(_) |
+            Def::Err => {
                 self.sess.span_bug(span,
                                    &format!("lookup_def_kind for unexpected item: {:?}", def));
             }
@@ -509,14 +510,28 @@ fn process_enum(&mut self,
             qualname.push_str(name);
             let val = self.span.snippet(variant.span);
 
-            self.fmt.struct_variant_str(variant.span,
-                                        self.span.span_for_first_ident(variant.span),
-                                        variant.node.data.id(),
-                                        variant.node.data.id(),
-                                        &qualname,
-                                        &enum_data.qualname,
-                                        &val,
-                                        enum_data.id);
+            match variant.node.data {
+                ast::VariantData::Struct(..) => {
+                    self.fmt.struct_variant_str(variant.span,
+                                                self.span.span_for_first_ident(variant.span),
+                                                variant.node.data.id(),
+                                                &qualname,
+                                                &enum_data.qualname,
+                                                &val,
+                                                enum_data.scope);
+                }
+                _ => {
+                    self.fmt.tuple_variant_str(variant.span,
+                                               self.span.span_for_first_ident(variant.span),
+                                               variant.node.data.id(),
+                                               name,
+                                               &qualname,
+                                               &enum_data.qualname,
+                                               &val,
+                                               enum_data.scope);
+                }
+            }
+
 
             for field in variant.node.data.fields() {
                 self.process_struct_field_def(field, variant.node.data.id());
@@ -679,7 +694,7 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
         let def_map = self.tcx.def_map.borrow();
         let def = def_map.get(&id).unwrap().full_def();
         match def {
-            def::DefMethod(did) => {
+            Def::Method(did) => {
                 let ti = self.tcx.impl_or_trait_item(did);
                 if let ty::MethodTraitItem(m) = ti {
                     if m.explicit_self == ty::ExplicitSelfCategory::Static {
@@ -687,13 +702,13 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
                     }
                 }
             }
-            def::DefLocal(..) |
-            def::DefStatic(_,_) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefStruct(_) |
-            def::DefVariant(..) |
-            def::DefFn(..) => self.write_sub_paths_truncated(path, false),
+            Def::Local(..) |
+            Def::Static(_,_) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Struct(..) |
+            Def::Variant(..) |
+            Def::Fn(..) => self.write_sub_paths_truncated(path, false),
             _ => {}
         }
     }
@@ -1163,7 +1178,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
             }
             let def = def_map.get(&id).unwrap().full_def();
             match def {
-                def::DefLocal(_, id) => {
+                Def::Local(_, id) => {
                     let value = if immut == ast::MutImmutable {
                         self.span.snippet(p.span).to_string()
                     } else {
@@ -1174,13 +1189,14 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                             "qualified path for local variable def in arm");
                     self.fmt.variable_str(p.span, Some(p.span), id, &path_to_string(p), &value, "")
                 }
-                def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => {
+                Def::Variant(..) | Def::Enum(..) |
+                Def::TyAlias(..) | Def::Struct(..) => {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
-                def::DefStatic(_, _) |
-                def::DefConst(..) |
-                def::DefAssociatedConst(..) => {}
+                Def::Static(_, _) |
+                Def::Const(..) |
+                Def::AssociatedConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
                             def),
             }
index e1343c73acfa90cfbd0db544dd8b4bdbbecc2a51..00554419e649c673e7ccf9adda0ae4c86e387bb3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use middle::ty;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 
 use std::env;
@@ -533,12 +533,12 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
         let def = def_map.get(&id).unwrap().full_def();
         let sub_span = self.span_utils.span_for_last_ident(path.span);
         match def {
-            def::DefUpvar(..) |
-            def::DefLocal(..) |
-            def::DefStatic(..) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefVariant(..) => {
+            Def::Upvar(..) |
+            Def::Local(..) |
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Variant(..) => {
                 Some(Data::VariableRefData(VariableRefData {
                     name: self.span_utils.snippet(sub_span.unwrap()),
                     span: sub_span.unwrap(),
@@ -546,17 +546,18 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                     ref_id: def.def_id(),
                 }))
             }
-            def::DefStruct(def_id) |
-            def::DefTy(def_id, _) |
-            def::DefTrait(def_id) |
-            def::DefTyParam(_, _, def_id, _) => {
+            Def::Struct(def_id) |
+            Def::Enum(def_id) |
+            Def::TyAlias(def_id) |
+            Def::Trait(def_id) |
+            Def::TyParam(_, _, def_id, _) => {
                 Some(Data::TypeRefData(TypeRefData {
                     span: sub_span.unwrap(),
                     ref_id: def_id,
                     scope: self.enclosing_scope(id),
                 }))
             }
-            def::DefMethod(decl_id) => {
+            Def::Method(decl_id) => {
                 let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.impl_or_trait_item(decl_id);
@@ -591,14 +592,14 @@ pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
                     decl_id: Some(decl_id),
                 }))
             }
-            def::DefFn(def_id, _) => {
+            Def::Fn(def_id) => {
                 Some(Data::FunctionCallData(FunctionCallData {
                     ref_id: def_id,
                     span: sub_span.unwrap(),
                     scope: self.enclosing_scope(id),
                 }))
             }
-            def::DefMod(def_id) => {
+            Def::Mod(def_id) => {
                 Some(Data::ModRefData(ModRefData {
                     ref_id: def_id,
                     span: sub_span.unwrap(),
@@ -651,7 +652,7 @@ fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(_) | def::DefSelfTy(..) => None,
+            Def::PrimTy(_) | Def::SelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
index 1db31baf30dcc192e847f185f36e1a64c8bd813c..17fdbe2e8398ed65739d265af674a4d7733d660a 100644 (file)
@@ -433,14 +433,13 @@ pub fn struct_variant_str(&mut self,
                               span: Span,
                               sub_span: Option<Span>,
                               id: NodeId,
-                              ctor_id: NodeId,
                               name: &str,
                               typ: &str,
                               val: &str,
                               scope_id: NodeId) {
         let id = self.normalize_node_id(id);
+        let ctor_id = id;
         let scope_id = self.normalize_node_id(scope_id);
-        let ctor_id = self.normalize_node_id(ctor_id);
         self.check_and_record(VariantStruct,
                               span,
                               sub_span,
index 6c1a31738afb960d679513a13b14087c20a46671..9a05135b76e3163cfe8bf2763ed4f6fdbc59ca1e 100644 (file)
 use middle::check_match::StaticInliner;
 use middle::check_match;
 use middle::const_eval;
-use middle::def::{self, DefMap};
+use middle::def::{Def, DefMap};
 use middle::def_id::DefId;
 use middle::expr_use_visitor as euv;
 use middle::infer;
@@ -669,7 +669,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // This is either an enum variant or a variable binding.
                 let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
-                    Some(def::DefVariant(enum_id, var_id, _)) => {
+                    Some(Def::Variant(enum_id, var_id)) => {
                         let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
                         Variant(Disr::from(variant.disr_val),
                                 adt::represent_node(bcx, cur.id),
@@ -800,13 +800,13 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: usize) -> bool {
             hir::PatTup(_) => true,
             hir::PatStruct(..) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(def::DefVariant(..)) => false,
+                    Some(Def::Variant(..)) => false,
                     _ => true,
                 }
             }
             hir::PatEnum(..) | hir::PatIdent(_, _, None) => {
                 match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(def::DefStruct(..)) => true,
+                    Some(Def::Struct(..)) => true,
                     _ => false
                 }
             }
@@ -1452,19 +1452,19 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
     let (vid, field) = match discr.node {
         hir::ExprPath(..) => match bcx.def(discr.id) {
-            def::DefLocal(_, vid) | def::DefUpvar(_, vid, _, _) => (vid, None),
+            Def::Local(_, vid) | Def::Upvar(_, vid, _, _) => (vid, None),
             _ => return false
         },
         hir::ExprField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
+                Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::NamedField(field.node)))
         },
         hir::ExprTupField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
+                Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::PositionalField(field.node)))
@@ -1851,7 +1851,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         hir::PatEnum(_, ref sub_pats) => {
             let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
-                Some(def::DefVariant(enum_id, var_id, _)) => {
+                Some(Def::Variant(enum_id, var_id)) => {
                     let repr = adt::represent_node(bcx, pat.id);
                     let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
                     let args = extract_variant_args(bcx,
@@ -1868,7 +1868,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         }
                     }
                 }
-                Some(def::DefStruct(..)) => {
+                Some(Def::Struct(..)) => {
                     match *sub_pats {
                         None => {
                             // This is a unit-like struct. Nothing to do here.
index 4c619f895de56a987bf8d9a6e8829ae93503e2be..7460ef82ebee4d493e79f1b49fe5474565c1e3d9 100644 (file)
@@ -3323,6 +3323,14 @@ fn visit_item(&mut self, i: &hir::Item) {
                 // giving `trans_item` access to this item, so also record a read.
                 tcx.dep_graph.with_task(DepNode::TransCrateItem(def_id), || {
                     tcx.dep_graph.read(DepNode::Hir(def_id));
+
+                    // We are going to be accessing various tables
+                    // generated by TypeckItemBody; we also assume
+                    // that the body passes type check. These tables
+                    // are not individually tracked, so just register
+                    // a read here.
+                    tcx.dep_graph.read(DepNode::TypeckItemBody(def_id));
+
                     trans_item(self.ccx, i);
                 });
 
index c7ec1c0955146ca82182a4593023bba29d16fd51..2651b3576feb27faf9794b39dae0a8880109ea67 100644 (file)
@@ -22,7 +22,7 @@
 use back::link;
 use llvm::{self, ValueRef, get_params};
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::subst;
@@ -133,13 +133,13 @@ fn fn_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum: Datum<'tcx, Rvalue>)
     }
 
     fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             def: def::Def,
+                             def: Def,
                              ref_expr: &hir::Expr)
                              -> Callee<'blk, 'tcx> {
         debug!("trans_def(def={:?}, ref_expr={:?})", def, ref_expr);
         let expr_ty = common::node_id_type(bcx, ref_expr.id);
         match def {
-            def::DefFn(did, _) if {
+            Def::Fn(did) if {
                 let maybe_def_id = inline::get_local_instance(bcx.ccx(), did);
                 let maybe_ast_node = maybe_def_id.and_then(|def_id| {
                     let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
@@ -156,7 +156,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     ty: expr_ty
                 }
             }
-            def::DefFn(did, _) if match expr_ty.sty {
+            Def::Fn(did) if match expr_ty.sty {
                 ty::TyBareFn(_, ref f) => f.abi == synabi::RustIntrinsic ||
                                           f.abi == synabi::PlatformIntrinsic,
                 _ => false
@@ -168,11 +168,11 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
                 Callee { bcx: bcx, data: Intrinsic(node_id, substs), ty: expr_ty }
             }
-            def::DefFn(did, _) => {
+            Def::Fn(did) => {
                 fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
                                             bcx.fcx.param_substs))
             }
-            def::DefMethod(meth_did) => {
+            Def::Method(meth_did) => {
                 let method_item = bcx.tcx().impl_or_trait_item(meth_did);
                 let fn_datum = match method_item.container() {
                     ty::ImplContainer(_) => {
@@ -190,7 +190,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 };
                 fn_callee(bcx, fn_datum)
             }
-            def::DefVariant(tid, vid, _) => {
+            Def::Variant(tid, vid) => {
                 let vinfo = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
                 assert_eq!(vinfo.kind(), ty::VariantKind::Tuple);
 
@@ -200,24 +200,24 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     ty: expr_ty
                 }
             }
-            def::DefStruct(_) => {
+            Def::Struct(..) => {
                 Callee {
                     bcx: bcx,
                     data: NamedTupleConstructor(Disr(0)),
                     ty: expr_ty
                 }
             }
-            def::DefStatic(..) |
-            def::DefConst(..) |
-            def::DefAssociatedConst(..) |
-            def::DefLocal(..) |
-            def::DefUpvar(..) => {
+            Def::Static(..) |
+            Def::Const(..) |
+            Def::AssociatedConst(..) |
+            Def::Local(..) |
+            Def::Upvar(..) => {
                 datum_callee(bcx, ref_expr)
             }
-            def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
-            def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
-            def::DefLabel(..) | def::DefTyParam(..) |
-            def::DefSelfTy(..) | def::DefErr => {
+            Def::Mod(..) | Def::ForeignMod(..) | Def::Trait(..) |
+            Def::Enum(..) | Def::TyAlias(..) | Def::PrimTy(..) |
+            Def::AssociatedTy(..) | Def::Label(..) | Def::TyParam(..) |
+            Def::SelfTy(..) | Def::Err => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     &format!("cannot translate def {:?} \
index b73e5ff3e038eb493f1d88f958a16bd533726648..ed47e529d4906a24f93322932141e3eb4d2035b3 100644 (file)
@@ -19,7 +19,7 @@
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind};
 use llvm::{True, False, Bool};
 use middle::cfg;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::lang_items::LangItem;
@@ -184,7 +184,7 @@ pub struct VariantInfo<'tcx> {
 impl<'tcx> VariantInfo<'tcx> {
     pub fn from_ty(tcx: &ty::ctxt<'tcx>,
                    ty: Ty<'tcx>,
-                   opt_def: Option<def::Def>)
+                   opt_def: Option<Def>)
                    -> Self
     {
         match ty.sty {
@@ -627,7 +627,7 @@ pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
         self.tcx().map.node_to_string(id).to_string()
     }
 
-    pub fn def(&self, nid: ast::NodeId) -> def::Def {
+    pub fn def(&self, nid: ast::NodeId) -> Def {
         match self.tcx().def_map.borrow().get(&nid) {
             Some(v) => v.full_def(),
             None => {
@@ -1049,9 +1049,9 @@ pub enum ExprOrMethodCall {
 }
 
 pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                            node: ExprOrMethodCall,
-                            param_substs: &subst::Substs<'tcx>)
-                            -> subst::Substs<'tcx> {
+                                node: ExprOrMethodCall,
+                                param_substs: &subst::Substs<'tcx>)
+                                -> subst::Substs<'tcx> {
     let tcx = ccx.tcx();
 
     let substs = match node {
@@ -1064,13 +1064,13 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     };
 
     if substs.types.needs_infer() {
-            tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
-                                 node, substs));
-        }
+        tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
+                              node, substs));
+    }
 
-        monomorphize::apply_param_substs(tcx,
-                                         param_substs,
-                                         &substs.erase_regions())
+    monomorphize::apply_param_substs(tcx,
+                                     param_substs,
+                                     &substs.erase_regions())
 }
 
 pub fn langcall(bcx: Block,
index 0fc879707331df7b2bc62e8f1d4495881970e9c3..0f5d8dbd94db01f2275e2a5ad6b2556bbfc4976e 100644 (file)
@@ -13,7 +13,7 @@
 use llvm;
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
-use middle::{check_const, def};
+use middle::const_qualif::ConstQualif;
 use middle::cstore::LOCAL_CRATE;
 use middle::const_eval::{self, ConstVal, ConstEvalErr};
 use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg};
@@ -26,6 +26,7 @@
 use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
 use middle::const_eval::EvalHint::ExprTypeChecked;
 use middle::const_eval::eval_const_expr_partial;
+use middle::def::Def;
 use middle::def_id::DefId;
 use trans::{adt, closure, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
@@ -273,8 +274,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            -> Result<ValueRef, ConstEvalFailure> {
     let expr = get_const_expr(ccx, def_id, ref_expr, param_substs);
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-    match get_const_expr_as_global(ccx, expr, check_const::ConstQualif::empty(),
-                                   empty_substs, TrueConst::Yes) {
+    match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
         Err(Runtime(err)) => {
             ccx.tcx().sess.span_err(expr.span, &err.description());
             Err(Compiletime(err))
@@ -285,7 +285,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           expr: &hir::Expr,
-                                          qualif: check_const::ConstQualif,
+                                          qualif: ConstQualif,
                                           param_substs: &'tcx Substs<'tcx>,
                                           trueconst: TrueConst)
                                           -> Result<ValueRef, ConstEvalFailure> {
@@ -297,7 +297,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // of just to get the `def` value
         let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
         match def {
-            def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+            Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
                     debug!("get_const_expr_as_global ({:?}): found const {:?}",
                            expr.id, def_id);
@@ -314,7 +314,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
     let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
                                               &ccx.tcx().expr_ty(expr));
-    let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
+    let val = if qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
         // Avoid autorefs as they would create global instead of stack
         // references, even when only the latter are correct.
         try!(const_expr_unadjusted(ccx, expr, ty, param_substs, None, trueconst))
@@ -792,7 +792,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
             let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
-            if let Some(def::DefStatic(def_id, _)) = opt_def {
+            if let Some(Def::Static(def_id, _)) = opt_def {
                 common::get_static_val(cx, def_id, ety)
             } else {
                 // If this isn't the address of a static, then keep going through
@@ -881,20 +881,20 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprPath(..) => {
             let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
-                def::DefLocal(_, id) => {
+                Def::Local(_, id) => {
                     if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
                         val
                     } else {
                         cx.sess().span_bug(e.span, "const fn argument not found")
                     }
                 }
-                def::DefFn(..) | def::DefMethod(..) => {
+                Def::Fn(..) | Def::Method(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
-                def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
+                Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                     const_deref_ptr(cx, try!(get_const_val(cx, def_id, e, param_substs)))
                 }
-                def::DefVariant(enum_did, variant_did, _) => {
+                Def::Variant(enum_did, variant_did) => {
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
                     match vinfo.kind() {
                         ty::VariantKind::Unit => {
@@ -909,7 +909,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         }
                     }
                 }
-                def::DefStruct(_) => {
+                Def::Struct(..) => {
                     if let ty::TyBareFn(..) = ety.sty {
                         // Tuple struct.
                         expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@@ -938,7 +938,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
             let arg_vals = try!(map_list(args));
             match def {
-                def::DefFn(did, _) | def::DefMethod(did) => {
+                Def::Fn(did) | Def::Method(did) => {
                     try!(const_fn_call(
                         cx,
                         ExprId(callee.id),
@@ -948,7 +948,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         trueconst,
                     ))
                 }
-                def::DefStruct(_) => {
+                Def::Struct(..) => {
                     if ety.is_simd() {
                         C_vector(&arg_vals[..])
                     } else {
@@ -956,7 +956,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         adt::trans_const(cx, &*repr, Disr(0), &arg_vals[..])
                     }
                 }
-                def::DefVariant(enum_did, variant_did, _) => {
+                Def::Variant(enum_did, variant_did) => {
                     let repr = adt::represent_type(cx, ety);
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
                     adt::trans_const(cx,
index 45f46410068beb711ed45cd1e70f9428238b26ca..fc3bd4f4d02330de8d693f339bb33b713d05849c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use middle::def;
+use middle::def::Def;
 use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
 use trans::base::*;
 use trans::basic_block::BasicBlock;
@@ -322,7 +322,7 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => fcx.top_loop_scope(),
         Some(_) => {
             match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def())  {
-                Some(def::DefLabel(loop_id)) => loop_id,
+                Some(Def::Label(loop_id)) => loop_id,
                 r => {
                     bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
                 }
index ab2f4462757d57529e43c414c5781e923edc6301..ada37c5d8dfbecc4d8316447ca65759f55630f12 100644 (file)
@@ -53,8 +53,8 @@
 
 use back::abi;
 use llvm::{self, ValueRef, TypeKind};
-use middle::check_const;
-use middle::def;
+use middle::const_qualif::ConstQualif;
+use middle::def::Def;
 use middle::lang_items::CoerceUnsizedTraitLangItem;
 use middle::subst::{Substs, VecPerParamSpace};
 use middle::traits;
@@ -128,11 +128,8 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    if !qualif.intersects(
-        check_const::ConstQualif::NOT_CONST |
-        check_const::ConstQualif::NEEDS_DROP
-    ) {
-        if !qualif.intersects(check_const::ConstQualif::PREFER_IN_PLACE) {
+    if !qualif.intersects(ConstQualif::NOT_CONST | ConstQualif::NEEDS_DROP) {
+        if !qualif.intersects(ConstQualif::PREFER_IN_PLACE) {
             if let SaveIn(lldest) = dest {
                 match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                        bcx.fcx.param_substs,
@@ -165,7 +162,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match expr.node {
                 hir::ExprPath(..) => {
                     match bcx.def(expr.id) {
-                        def::DefConst(did) => {
+                        Def::Const(did) => {
                             let empty_substs = bcx.tcx().mk_substs(Substs::trans_empty());
                             let const_expr = consts::get_const_expr(bcx.ccx(), did, expr,
                                                                     empty_substs);
@@ -231,16 +228,13 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut bcx = bcx;
     let fcx = bcx.fcx;
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
-    let global = if !qualif.intersects(
-        check_const::ConstQualif::NOT_CONST |
-        check_const::ConstQualif::NEEDS_DROP
-    ) {
+    let adjusted_global = !qualif.intersects(ConstQualif::NON_STATIC_BORROWS);
+    let global = if !qualif.intersects(ConstQualif::NOT_CONST | ConstQualif::NEEDS_DROP) {
         match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                             bcx.fcx.param_substs,
                                                             consts::TrueConst::No) {
             Ok(global) => {
-                if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
+                if qualif.intersects(ConstQualif::HAS_STATIC_BORROWS) {
                     // Is borrowed as 'static, must return lvalue.
 
                     // Cast pointer to global, because constants have different types.
@@ -903,25 +897,25 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                          ref_expr: &hir::Expr,
-                         def: def::Def)
+                         def: Def)
                          -> DatumBlock<'blk, 'tcx, Expr> {
     //! Translates a reference to a path.
 
     let _icx = push_ctxt("trans_def_lvalue");
     match def {
-        def::DefFn(..) | def::DefMethod(..) |
-        def::DefStruct(_) | def::DefVariant(..) => {
+        Def::Fn(..) | Def::Method(..) |
+        Def::Struct(..) | Def::Variant(..) => {
             let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
                                                 bcx.fcx.param_substs);
             DatumBlock::new(bcx, datum.to_expr_datum())
         }
-        def::DefStatic(did, _) => {
+        Def::Static(did, _) => {
             let const_ty = expr_ty(bcx, ref_expr);
             let val = get_static_val(bcx.ccx(), did, const_ty);
             let lval = Lvalue::new("expr::trans_def");
             DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr(lval)))
         }
-        def::DefConst(_) => {
+        Def::Const(_) => {
             bcx.sess().span_bug(ref_expr.span,
                 "constant expression should not reach expr::trans_def")
         }
@@ -1272,7 +1266,7 @@ fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
 
 fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         ref_expr: &hir::Expr,
-                                        def: def::Def,
+                                        def: Def,
                                         dest: Dest)
                                         -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_def_dps_unadjusted");
@@ -1283,7 +1277,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     match def {
-        def::DefVariant(tid, vid, _) => {
+        Def::Variant(tid, vid) => {
             let variant = bcx.tcx().lookup_adt_def(tid).variant_with_id(vid);
             if let ty::VariantKind::Tuple = variant.kind() {
                 // N-ary variant.
@@ -1300,7 +1294,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 return bcx;
             }
         }
-        def::DefStruct(_) => {
+        Def::Struct(..) => {
             let ty = expr_ty(bcx, ref_expr);
             match ty.sty {
                 ty::TyStruct(def, _) if def.has_dtor() => {
@@ -1321,17 +1315,17 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                          ref_expr: &hir::Expr,
-                                         def: def::Def,
+                                         def: Def,
                                          param_substs: &'tcx Substs<'tcx>)
                                          -> Datum<'tcx, Rvalue> {
     let _icx = push_ctxt("trans_def_datum_unadjusted");
 
     match def {
-        def::DefFn(did, _) |
-        def::DefStruct(did) | def::DefVariant(_, did, _) => {
+        Def::Fn(did) |
+        Def::Struct(did) | Def::Variant(_, did) => {
             callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
-        def::DefMethod(method_did) => {
+        Def::Method(method_did) => {
             match ccx.tcx().impl_or_trait_item(method_did).container() {
                 ty::ImplContainer(_) => {
                     callee::trans_fn_ref(ccx, method_did,
@@ -1356,12 +1350,12 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 /// Translates a reference to a local variable or argument. This always results in an lvalue datum.
 pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   def: def::Def)
+                                   def: Def)
                                    -> Datum<'tcx, Lvalue> {
     let _icx = push_ctxt("trans_local_var");
 
     match def {
-        def::DefUpvar(_, nid, _, _) => {
+        Def::Upvar(_, nid, _, _) => {
             // Can't move upvars, so this is never a ZeroMemLastUse.
             let local_ty = node_id_type(bcx, nid);
             let lval = Lvalue::new_with_hint("expr::trans_local_var (upvar)",
@@ -1375,7 +1369,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        def::DefLocal(_, nid) => {
+        Def::Local(_, nid) => {
             let datum = match bcx.fcx.lllocals.borrow().get(&nid) {
                 Some(&v) => v,
                 None => {
@@ -2587,7 +2581,7 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
     match expr.node {
         hir::ExprPath(..) => {
             match tcx.resolve_expr(expr) {
-                def::DefStruct(_) | def::DefVariant(..) => {
+                Def::Struct(..) | Def::Variant(..) => {
                     if let ty::TyBareFn(..) = tcx.node_id_to_type(expr.id).sty {
                         // ctor function
                         ExprKind::RvalueDatum
@@ -2596,24 +2590,18 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
                     }
                 }
 
-                // Special case: A unit like struct's constructor must be called without () at the
-                // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
-                // of unit structs this is should not be interpreted as function pointer but as
-                // call to the constructor.
-                def::DefFn(_, true) => ExprKind::RvalueDps,
-
                 // Fn pointers are just scalar values.
-                def::DefFn(..) | def::DefMethod(..) => ExprKind::RvalueDatum,
+                Def::Fn(..) | Def::Method(..) => ExprKind::RvalueDatum,
 
                 // Note: there is actually a good case to be made that
                 // DefArg's, particularly those of immediate type, ought to
                 // considered rvalues.
-                def::DefStatic(..) |
-                def::DefUpvar(..) |
-                def::DefLocal(..) => ExprKind::Lvalue,
+                Def::Static(..) |
+                Def::Upvar(..) |
+                Def::Local(..) => ExprKind::Lvalue,
 
-                def::DefConst(..) |
-                def::DefAssociatedConst(..) => ExprKind::RvalueDatum,
+                Def::Const(..) |
+                Def::AssociatedConst(..) => ExprKind::RvalueDatum,
 
                 def => {
                     tcx.sess.span_bug(
index bd12dd8c3effcc9ad49ad5185daa835fd8e555c1..4695595d16f306c1edf2de543b61a494792a5f9f 100644 (file)
@@ -14,7 +14,6 @@
 use middle::def_id::DefId;
 use middle::infer;
 use middle::subst::{Subst, Substs};
-use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
 use trans::base::*;
@@ -34,7 +33,7 @@
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
-use middle::ty::{self, Ty, TypeFoldable};
+use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 
 use syntax::ast;
@@ -117,10 +116,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
 
         ty::TraitContainer(trait_def_id) => {
-            let trait_substs = method.substs.clone().method_to_trait();
-            let trait_substs = bcx.tcx().mk_substs(trait_substs);
-            let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs);
-
+            let trait_ref = method.substs.to_trait_ref(bcx.tcx(), trait_def_id);
             let trait_ref = ty::Binder(bcx.monomorphize(&trait_ref));
             let span = bcx.tcx().map.span(method_call.expr_id);
             debug!("method_call={:?} trait_ref={:?} trait_ref id={:?} substs={:?}",
@@ -128,9 +124,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                    trait_ref,
                    trait_ref.0.def_id,
                    trait_ref.0.substs);
-            let origin = fulfill_obligation(bcx.ccx(),
-                                            span,
-                                            trait_ref.clone());
+            let origin = fulfill_obligation(bcx.ccx(), span, trait_ref);
             debug!("origin = {:?}", origin);
             trans_monomorphized_callee(bcx,
                                        method_call,
@@ -169,44 +163,9 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // type parameters that belong to the trait but also some that
     // belong to the method:
     let rcvr_substs = node_id_substs(ccx, ExprId(expr_id), param_substs);
-    let subst::SeparateVecsPerParamSpace {
-        types: rcvr_type,
-        selfs: rcvr_self,
-        fns: rcvr_method
-    } = rcvr_substs.types.split();
-
-    // Lookup the precise impl being called. To do that, we need to
-    // create a trait reference identifying the self type and other
-    // input type parameters. To create that trait reference, we have
-    // to pick apart the type parameters to identify just those that
-    // pertain to the trait. This is easiest to explain by example:
-    //
-    //     trait Convert {
-    //         fn from<U:Foo>(n: U) -> Option<Self>;
-    //     }
-    //     ...
-    //     let f = <Vec<i32> as Convert>::from::<String>(...)
-    //
-    // Here, in this call, which I've written with explicit UFCS
-    // notation, the set of type parameters will be:
-    //
-    //     rcvr_type: [] <-- nothing declared on the trait itself
-    //     rcvr_self: [Vec<i32>] <-- the self type
-    //     rcvr_method: [String] <-- method type parameter
-    //
-    // So we create a trait reference using the first two,
-    // basically corresponding to `<Vec<i32> as Convert>`.
-    // The remaining type parameters (`rcvr_method`) will be used below.
-    let trait_substs =
-        Substs::erased(VecPerParamSpace::new(rcvr_type,
-                                             rcvr_self,
-                                             Vec::new()));
-    let trait_substs = tcx.mk_substs(trait_substs);
-    debug!("trait_substs={:?}", trait_substs);
-    let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs));
-    let vtbl = fulfill_obligation(ccx,
-                                  DUMMY_SP,
-                                  trait_ref);
+    debug!("rcvr_substs={:?}", rcvr_substs);
+    let trait_ref = ty::Binder(rcvr_substs.to_trait_ref(tcx, trait_id));
+    let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref);
 
     // Now that we know which impl is being used, we can dispatch to
     // the actual function:
@@ -216,33 +175,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             substs: impl_substs,
             nested: _ }) =>
         {
-            assert!(!impl_substs.types.needs_infer());
-
-            // Create the substitutions that are in scope. This combines
-            // the type parameters from the impl with those declared earlier.
-            // To see what I mean, consider a possible impl:
-            //
-            //    impl<T> Convert for Vec<T> {
-            //        fn from<U:Foo>(n: U) { ... }
-            //    }
-            //
-            // Recall that we matched `<Vec<i32> as Convert>`. Trait
-            // resolution will have given us a substitution
-            // containing `impl_substs=[[T=i32],[],[]]` (the type
-            // parameters defined on the impl). We combine
-            // that with the `rcvr_method` from before, which tells us
-            // the type parameters from the *method*, to yield
-            // `callee_substs=[[T=i32],[],[U=String]]`.
-            let subst::SeparateVecsPerParamSpace {
-                types: impl_type,
-                selfs: impl_self,
-                fns: _
-            } = impl_substs.types.split();
-            let callee_substs =
-                Substs::erased(VecPerParamSpace::new(impl_type,
-                                                     impl_self,
-                                                     rcvr_method));
-
+            let callee_substs = impl_substs.with_method_from(&rcvr_substs);
             let mth = tcx.get_impl_method(impl_did, callee_substs, mname);
             trans_fn_ref_with_substs(ccx, mth.method.def_id, ExprId(expr_id),
                                      param_substs,
@@ -256,6 +189,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               idx)
         }
         _ => {
+            // FIXME(#20847): handle at least VtableFnPointer
             tcx.sess.bug(&format!("static call to invalid vtable: {:?}",
                                  vtbl));
         }
@@ -285,11 +219,11 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             // create a concatenated set of substitutions which includes
             // those from the impl and those from the method:
-            let callee_substs =
-                combine_impl_and_methods_tps(
-                    bcx, MethodCallKey(method_call), vtable_impl.substs);
-
-            let mth = bcx.tcx().get_impl_method(impl_did, callee_substs, mname);
+            let meth_substs = node_id_substs(ccx,
+                                             MethodCallKey(method_call),
+                                             bcx.fcx.param_substs);
+            let impl_substs = vtable_impl.substs.with_method_from(&meth_substs);
+            let mth = bcx.tcx().get_impl_method(impl_did, impl_substs, mname);
             // translate the function
             let datum = trans_fn_ref_with_substs(bcx.ccx(),
                                                  mth.method.def_id,
@@ -346,43 +280,6 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
- /// Creates a concatenated set of substitutions which includes those from the impl and those from
- /// the method.  This are some subtle complications here.  Statically, we have a list of type
- /// parameters like `[T0, T1, T2, M1, M2, M3]` where `Tn` are type parameters that appear on the
- /// receiver.  For example, if the receiver is a method parameter `A` with a bound like
- /// `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
- ///
- /// The weird part is that the type `A` might now be bound to any other type, such as `foo<X>`.
- /// In that case, the vector we want is: `[X, M1, M2, M3]`.  Therefore, what we do now is to slice
- /// off the method type parameters and append them to the type parameters from the type that the
- /// receiver is mapped to.
-fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                            node: ExprOrMethodCall,
-                                            rcvr_substs: subst::Substs<'tcx>)
-                                            -> subst::Substs<'tcx>
-{
-    let ccx = bcx.ccx();
-
-    let node_substs = node_id_substs(ccx, node, bcx.fcx.param_substs);
-
-    debug!("rcvr_substs={:?}", rcvr_substs);
-    debug!("node_substs={:?}", node_substs);
-
-    // Break apart the type parameters from the node and type
-    // parameters from the receiver.
-    let node_method = node_substs.types.split().fns;
-    let subst::SeparateVecsPerParamSpace {
-        types: rcvr_type,
-        selfs: rcvr_self,
-        fns: rcvr_method
-    } = rcvr_substs.types.clone().split();
-    assert!(rcvr_method.is_empty());
-    subst::Substs {
-        regions: subst::ErasedRegions,
-        types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
-    }
-}
-
 /// Create a method callee where the method is coming from a trait object (e.g., Box<Trait> type).
 /// In this case, we must pull the fn pointer out of the vtable that is packaged up with the
 /// object. Objects are represented as a pair, so we first evaluate the self expression and then
index 9d4c7663cb0d3bcbfca75938ef95284c8601de20..23cca55e4d480e49e92a38aa19820343e6376783 100644 (file)
@@ -11,7 +11,7 @@
 //! An analysis to determine which temporaries require allocas and
 //! which do not.
 
-use rustc_data_structures::fnv::FnvHashSet;
+use rustc_data_structures::bitvec::BitVector;
 use rustc::mir::repr as mir;
 use rustc::mir::visit::{Visitor, LvalueContext};
 use trans::common::{self, Block};
@@ -19,8 +19,8 @@
 
 pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
                                mir: &mir::Mir<'tcx>)
-                               -> FnvHashSet<usize> {
-    let mut analyzer = TempAnalyzer::new();
+                               -> BitVector {
+    let mut analyzer = TempAnalyzer::new(mir.temp_decls.len());
 
     analyzer.visit_mir(mir);
 
@@ -51,18 +51,28 @@ pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
 }
 
 struct TempAnalyzer {
-    lvalue_temps: FnvHashSet<usize>,
+    lvalue_temps: BitVector,
+    seen_assigned: BitVector
 }
 
 impl TempAnalyzer {
-    fn new() -> TempAnalyzer {
-        TempAnalyzer { lvalue_temps: FnvHashSet() }
+    fn new(temp_count: usize) -> TempAnalyzer {
+        TempAnalyzer {
+            lvalue_temps: BitVector::new(temp_count),
+            seen_assigned: BitVector::new(temp_count)
+        }
     }
 
     fn mark_as_lvalue(&mut self, temp: usize) {
         debug!("marking temp {} as lvalue", temp);
         self.lvalue_temps.insert(temp);
     }
+
+    fn mark_assigned(&mut self, temp: usize) {
+        if !self.seen_assigned.insert(temp) {
+            self.mark_as_lvalue(temp);
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for TempAnalyzer {
@@ -74,6 +84,7 @@ fn visit_assign(&mut self,
 
         match *lvalue {
             mir::Lvalue::Temp(index) => {
+                self.mark_assigned(index as usize);
                 if !rvalue::rvalue_creates_operand(rvalue) {
                     self.mark_as_lvalue(index as usize);
                 }
index 3238869cac5c1ad9adb165faf70ec246ca769fba..e433776bef2933fad64f460501b9067c6203b6a8 100644 (file)
@@ -16,7 +16,6 @@
 use rustc::middle::subst::Substs;
 use rustc::middle::const_eval;
 use rustc::middle::def_id::DefId;
-use rustc::middle::subst;
 use rustc::middle::traits;
 use rustc::mir::repr::ItemKind;
 use trans::common::{Block, fulfill_obligation};
@@ -46,7 +45,7 @@ pub fn trans_item_ref(&mut self,
             ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did),
             ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
                 ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
-                ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
+                ty::TraitContainer(tdid) => self.trans_trait_method(bcx, ty, did, tdid, substs)
             },
             ItemKind::Constant => {
                 let did = inline::maybe_instantiate_inline(bcx.ccx(), did);
@@ -98,16 +97,16 @@ pub fn trans_fn_ref(&mut self,
         }
     }
 
-    /// Translates references to static methods.
+    /// Translates references to trait methods.
     ///
     /// This is an adaptation of meth::trans_static_method_callee
-    pub fn trans_static_method(&mut self,
-                               bcx: Block<'bcx, 'tcx>,
-                               ty: Ty<'tcx>,
-                               method_id: DefId,
-                               trait_id: DefId,
-                               substs: &'tcx Substs<'tcx>)
-                               -> OperandRef<'tcx> {
+    pub fn trans_trait_method(&mut self,
+                              bcx: Block<'bcx, 'tcx>,
+                              ty: Ty<'tcx>,
+                              method_id: DefId,
+                              trait_id: DefId,
+                              substs: &'tcx Substs<'tcx>)
+                              -> OperandRef<'tcx> {
         debug!("trans_static_method(ty={:?}, method={}, trait={}, substs={:?})",
                 ty,
                 bcx.tcx().item_path_str(method_id),
@@ -116,34 +115,20 @@ pub fn trans_static_method(&mut self,
 
         let ccx = bcx.ccx();
         let tcx = bcx.tcx();
-        let subst::SeparateVecsPerParamSpace {
-            types: rcvr_type,
-            selfs: rcvr_self,
-            fns: rcvr_method
-        } = substs.clone().types.split();
-        let trait_substs = Substs::erased(
-            subst::VecPerParamSpace::new(rcvr_type, rcvr_self, Vec::new())
-        );
-        let trait_substs = tcx.mk_substs(trait_substs);
-        let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, trait_substs));
+        let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
         let vtbl = fulfill_obligation(ccx, DUMMY_SP, trait_ref);
         match vtbl {
-            traits::VtableImpl(traits::VtableImplData { impl_def_id, substs: imp_substs, .. }) => {
-                assert!(!imp_substs.types.needs_infer());
+            traits::VtableImpl(traits::VtableImplData {
+                impl_def_id, substs: impl_substs, ..
+            }) => {
+                assert!(!impl_substs.types.needs_infer());
 
                 let mname = tcx.item_name(method_id);
 
-                let subst::SeparateVecsPerParamSpace {
-                    types: impl_type,
-                    selfs: impl_self,
-                    fns: _
-                } = imp_substs.types.split();
-                let callee_substs = Substs::erased(
-                    subst::VecPerParamSpace::new(impl_type, impl_self, rcvr_method)
-                );
+                let callee_substs = impl_substs.with_method_from(substs);
                 let mth = tcx.get_impl_method(impl_def_id, callee_substs, mname);
-                let mthsubsts = tcx.mk_substs(mth.substs);
-                self.trans_fn_ref(bcx, ty, mthsubsts, mth.method.def_id)
+                let mth_substs = tcx.mk_substs(mth.substs);
+                self.trans_fn_ref(bcx, ty, mth_substs, mth.method.def_id)
             },
             traits::VtableClosure(data) => {
                 let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
index 75ce33da2c9b9da66eb84a77ad40fbdabb3f1eaf..cdde4cbb286046afc8aa5cd090cdd11e73f14c12 100644 (file)
@@ -97,7 +97,7 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
     let temps = mir.temp_decls.iter()
                               .map(|decl| bcx.monomorphize(&decl.ty))
                               .enumerate()
-                              .map(|(i, mty)| if lvalue_temps.contains(&i) {
+                              .map(|(i, mty)| if lvalue_temps.contains(i) {
                                   TempRef::Lvalue(LvalueRef::alloca(bcx,
                                                                     mty,
                                                                     &format!("temp{:?}", i)))
index f53653d7cad6aaf9cd3977231aa84f5d158d026a..fa925241c72cd3734f2151b54e2f8c65e8e08dc8 100644 (file)
@@ -89,7 +89,7 @@ pub fn trans_rvalue(&mut self,
 
             mir::Rvalue::Repeat(ref elem, ref count) => {
                 let elem = self.trans_operand(bcx, elem);
-                let size = self.trans_constant(bcx, count).immediate();
+                let size = self.trans_constval(bcx, &count.value, count.ty).immediate();
                 let base = expr::get_dataptr(bcx, dest.llval);
                 tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
                     self.store_operand(bcx, llslot, elem);
index 98effeefad2a74fa9aaba4cc421683248c295368..d67f5f9db5ee4f3bc70f1adae480e017aeef4c7b 100644 (file)
@@ -51,7 +51,7 @@
 use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
 use middle::const_eval::{self, ConstVal};
 use middle::const_eval::EvalHint::UncheckedExprHint;
-use middle::def;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use middle::privacy::{AllPublic, LastMod};
@@ -718,8 +718,8 @@ pub fn instantiate_mono_trait_ref<'tcx>(
 fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId {
     let path = &trait_ref.path;
     match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
-        def::DefTrait(trait_def_id) => trait_def_id,
-        def::DefErr => {
+        Def::Trait(trait_def_id) => trait_def_id,
+        Def::Err => {
             this.tcx().sess.fatal("cannot continue compilation due to previous error");
         }
         _ => {
@@ -1028,7 +1028,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
                 _ => None
             };
             match def {
-                Some(def::DefTrait(trait_def_id)) => {
+                Some(Def::Trait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
                     let trait_ref = object_path_to_poly_trait_ref(this,
                                                                   rscope,
@@ -1263,9 +1263,9 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    span: Span,
                                    ty: Ty<'tcx>,
-                                   ty_path_def: def::Def,
+                                   ty_path_def: Def,
                                    item_segment: &hir::PathSegment)
-                                   -> (Ty<'tcx>, def::Def)
+                                   -> (Ty<'tcx>, Def)
 {
     let tcx = this.tcx();
     let assoc_name = item_segment.identifier.name;
@@ -1277,7 +1277,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     // Find the type of the associated item, and the trait where the associated
     // item is declared.
     let bound = match (&ty.sty, ty_path_def) {
-        (_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => {
+        (_, Def::SelfTy(Some(trait_did), Some((impl_id, _)))) => {
             // `Self` in an impl of a trait - we have a concrete self type and a
             // trait reference.
             let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
@@ -1306,7 +1306,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
-        (&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => {
+        (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
             let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
             match find_bound_for_assoc_item(this,
                                             trait_node_id,
@@ -1317,7 +1317,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
-        (&ty::TyParam(_), def::DefTyParam(_, _, param_did, param_name)) => {
+        (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
             let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
             match find_bound_for_assoc_item(this,
                                             param_node_id,
@@ -1359,7 +1359,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         item.expect("missing associated type").def_id()
     };
 
-    (ty, def::DefAssociatedTy(trait_did, item_did))
+    (ty, Def::AssociatedTy(trait_did, item_did))
 }
 
 fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
@@ -1443,14 +1443,14 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                         rscope: &RegionScope,
                         span: Span,
                         param_mode: PathParamMode,
-                        def: &def::Def,
+                        def: &Def,
                         opt_self_ty: Option<Ty<'tcx>>,
                         base_segments: &[hir::PathSegment])
                         -> Ty<'tcx> {
     let tcx = this.tcx();
 
     match *def {
-        def::DefTrait(trait_def_id) => {
+        Def::Trait(trait_def_id) => {
             // N.B. this case overlaps somewhat with
             // TyObjectSum, see that fn for details
             let mut projection_bounds = Vec::new();
@@ -1471,7 +1471,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                      projection_bounds,
                                      &[])
         }
-        def::DefTy(did, _) | def::DefStruct(did) => {
+        Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
             prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
             ast_path_to_ty(this,
                            rscope,
@@ -1480,11 +1480,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                            did,
                            base_segments.last().unwrap())
         }
-        def::DefTyParam(space, index, _, name) => {
+        Def::TyParam(space, index, _, name) => {
             prohibit_type_params(tcx, base_segments);
             tcx.mk_param(space, index, name)
         }
-        def::DefSelfTy(_, Some((_, self_ty_id))) => {
+        Def::SelfTy(_, Some((_, self_ty_id))) => {
             // Self in impl (we know the concrete type).
             prohibit_type_params(tcx, base_segments);
             if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
@@ -1497,12 +1497,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                 tcx.sess.span_bug(span, "self type has not been fully resolved")
             }
         }
-        def::DefSelfTy(Some(_), None) => {
+        Def::SelfTy(Some(_), None) => {
             // Self in trait.
             prohibit_type_params(tcx, base_segments);
             tcx.mk_self_type()
         }
-        def::DefAssociatedTy(trait_did, _) => {
+        Def::AssociatedTy(trait_did, _) => {
             prohibit_type_params(tcx, &base_segments[..base_segments.len()-2]);
             qpath_to_ty(this,
                         rscope,
@@ -1513,7 +1513,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                         &base_segments[base_segments.len()-2],
                         base_segments.last().unwrap())
         }
-        def::DefMod(id) => {
+        Def::Mod(..) => {
             // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
             // FIXME(#22519) This part of the resolution logic should be
             // avoided entirely for that form, once we stop needed a Def
@@ -1522,29 +1522,20 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             // resolve Self::Foo, at the moment we can't resolve the former because
             // we don't have the trait information around, which is just sad.
 
-            if !base_segments.is_empty() {
-                let id_node = tcx.map.as_local_node_id(id).unwrap();
-                span_err!(tcx.sess,
-                          span,
-                          E0247,
-                          "found module name used as a type: {}",
-                          tcx.map.node_to_user_string(id_node));
-                return this.tcx().types.err;
-            }
+            assert!(base_segments.is_empty());
 
             opt_self_ty.expect("missing T in <T>::a::b::c")
         }
-        def::DefPrimTy(prim_ty) => {
+        Def::PrimTy(prim_ty) => {
             prim_ty_to_ty(tcx, base_segments, prim_ty)
         }
-        def::DefErr => {
+        Def::Err => {
             return this.tcx().types.err;
         }
         _ => {
-            let id_node = tcx.map.as_local_node_id(def.def_id()).unwrap();
             span_err!(tcx.sess, span, E0248,
                       "found value `{}` used as a type",
-                      tcx.map.path_to_string(id_node));
+                      tcx.item_path_str(def.def_id()));
             return this.tcx().types.err;
         }
     }
@@ -1556,7 +1547,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                         rscope: &RegionScope,
                                         span: Span,
                                         param_mode: PathParamMode,
-                                        def: &def::Def,
+                                        def: &Def,
                                         opt_self_ty: Option<Ty<'tcx>>,
                                         base_segments: &[hir::PathSegment],
                                         assoc_segments: &[hir::PathSegment])
@@ -1658,7 +1649,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
+                    base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -2177,7 +2168,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
         match *ast_bound {
             hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
                 match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
-                    def::DefTrait(trait_did) => {
+                    Def::Trait(trait_did) => {
                         if tcx.try_add_builtin_trait(trait_did,
                                                      &mut builtin_bounds) {
                             let segments = &b.trait_ref.path.segments;
index dfa144699b217ad0a6ec540dbf96f096ca41dccc..c43349f88104dd149522bcc6ee8f994db4cf2a54 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::def;
+use middle::def::{self, Def};
 use middle::infer::{self, TypeOrigin};
 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
 use middle::pat_util::pat_is_resolved_const;
@@ -214,7 +214,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         hir::PatQPath(ref qself, ref path) => {
             let self_ty = fcx.to_ty(&qself.ty);
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
-                if d.base_def == def::DefErr {
+                if d.base_def == Def::Err {
                     fcx.write_error(pat.id);
                     return;
                 }
@@ -223,7 +223,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 // This is just a sentinel for finish_resolving_def_to_ty.
                 let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
                 def::PathResolution {
-                    base_def: def::DefMod(sentinel),
+                    base_def: Def::Mod(sentinel),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -410,10 +410,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     // subtyping.
 }
 
-fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool {
+fn check_assoc_item_is_const(pcx: &pat_ctxt, def: Def, span: Span) -> bool {
     match def {
-        def::DefAssociatedConst(..) => true,
-        def::DefMethod(..) => {
+        Def::AssociatedConst(..) => true,
+        Def::Method(..) => {
             span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
                       "associated items in match patterns must be constants");
             false
@@ -616,7 +616,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let tcx = pcx.fcx.ccx.tcx;
 
     let path_res = match tcx.def_map.borrow().get(&pat.id) {
-        Some(&path_res) if path_res.base_def != def::DefErr => path_res,
+        Some(&path_res) if path_res.base_def != Def::Err => path_res,
         _ => {
             fcx.write_error(pat.id);
 
@@ -693,10 +693,12 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     let real_path_ty = fcx.node_ty(pat.id);
     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
-        ty::TyEnum(enum_def, expected_substs)
-            if def == def::DefVariant(enum_def.did, def.def_id(), false) =>
-        {
+        ty::TyEnum(enum_def, expected_substs) => {
             let variant = enum_def.variant_of_def(def);
+            if variant.kind() == ty::VariantKind::Struct {
+                report_bad_struct_kind(false);
+                return;
+            }
             if is_tuple_struct_pat && variant.kind() != ty::VariantKind::Tuple {
                 // Matching unit variants with tuple variant patterns (`UnitVariant(..)`)
                 // is allowed for backward compatibility.
index a1b378d84d0010faf8f9a1fbbb3a4c1c612d748f..84c436c59c1d29b35b3b9137ff1a606d9db96a0d 100644 (file)
@@ -26,7 +26,7 @@
 
 use CrateCtxt;
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::infer;
 use middle::ty::{self, LvaluePreference, Ty};
@@ -236,7 +236,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             if let hir::ExprCall(ref expr, _) = call_expr.node {
                 let tcx = fcx.tcx();
                 if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
-                    if pr.depth == 0 && pr.base_def != def::DefErr {
+                    if pr.depth == 0 && pr.base_def != Def::Err {
                         if let Some(span) = tcx.map.span_if_local(pr.def_id()) {
                             err.span_note(span, "defined here");
                         }
index b2462a3612ca4821b2530507eea02d236fbaf449..1d8f6f005cddc362610c7f7fdcaf746605c054e1 100644 (file)
@@ -332,7 +332,7 @@ fn instantiate_method_substs(&mut self,
                     .generics.regions.get_slice(subst::FnSpace));
 
         let subst::Substs { types, regions } = substs;
-        let regions = regions.map(|r| r.with_vec(subst::FnSpace, method_regions));
+        let regions = regions.map(|r| r.with_slice(subst::FnSpace, &method_regions));
         let mut final_substs = subst::Substs { types: types, regions: regions };
 
         if num_supplied_types == 0 {
index d462e2b45b28121d44d85cfe1d200197c2331834..fc2dd4475e3ffabf135a56b5fb95ac42b8427a70 100644 (file)
@@ -12,7 +12,7 @@
 
 use astconv::AstConv;
 use check::FnCtxt;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
 use middle::subst;
@@ -334,7 +334,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               method_name: ast::Name,
                               self_ty: ty::Ty<'tcx>,
                               expr_id: ast::NodeId)
-                              -> Result<(def::Def, LastPrivate), MethodError<'tcx>>
+                              -> Result<(Def, LastPrivate), MethodError<'tcx>>
 {
     let mode = probe::Mode::Path;
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
@@ -346,8 +346,8 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
     }
     let def_result = match pick.item {
-        ty::ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id),
-        ty::ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id),
+        ty::ImplOrTraitItem::MethodTraitItem(..) => Def::Method(def_id),
+        ty::ImplOrTraitItem::ConstTraitItem(..) => Def::AssociatedConst(def_id),
         ty::ImplOrTraitItem::TypeTraitItem(..) => {
             fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type");
         }
index 560e84b52d1d6966a8e2ee9fd70ff9703ce0632a..21bf67d2d5c7529e911c0d9d4832bfe675d64410 100644 (file)
@@ -18,7 +18,7 @@
 use front::map as hir_map;
 use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TypeFoldable};
 use middle::cstore::{self, CrateStore, DefLike};
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use middle::lang_items::FnOnceTraitLangItem;
 use middle::subst::Substs;
@@ -432,10 +432,10 @@ fn handle_external_def(traits: &mut AllTraitsVec,
                                cstore: &for<'a> cstore::CrateStore<'a>,
                                dl: cstore::DefLike) {
             match dl {
-                cstore::DlDef(def::DefTrait(did)) => {
+                cstore::DlDef(Def::Trait(did)) => {
                     traits.push(TraitInfo::new(did));
                 }
-                cstore::DlDef(def::DefMod(did)) => {
+                cstore::DlDef(Def::Mod(did)) => {
                     if !external_mods.insert(did) {
                         return;
                     }
index 03508b07b7adce47458452e15fba944e32f5c049..f49b25df66e872341bcb0cbd79ce33cc6c82846b 100644 (file)
@@ -86,7 +86,7 @@
 use fmt_macros::{Parser, Piece, Position};
 use middle::astconv_util::prohibit_type_params;
 use middle::cstore::LOCAL_CRATE;
-use middle::def;
+use middle::def::{self, Def};
 use middle::def_id::DefId;
 use middle::infer;
 use middle::infer::{TypeOrigin, type_variable};
@@ -1416,16 +1416,16 @@ pub fn instantiate_type(&self,
 
     /// Return the dict-like variant corresponding to a given `Def`.
     pub fn def_struct_variant(&self,
-                              def: def::Def,
+                              def: Def,
                               span: Span)
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
-            def::DefVariant(enum_id, variant_id, _) => {
+            Def::Variant(enum_id, variant_id) => {
                 let adt = self.tcx().lookup_adt_def(enum_id);
                 (adt, adt.variant_with_id(variant_id))
             }
-            def::DefTy(did, _) | def::DefStruct(did) => {
+            Def::Struct(did) | Def::TyAlias(did) => {
                 let typ = self.tcx().lookup_item_type(did);
                 if let ty::TyStruct(adt, _) = typ.ty.sty {
                     (adt, adt.struct_variant())
@@ -3167,7 +3167,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
         // Find the relevant variant
         let def = lookup_full_def(tcx, path.span, expr.id);
-        if def == def::DefErr {
+        if def == Def::Err {
             check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
             return;
         }
@@ -3337,7 +3337,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
           } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
+                    base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -3349,7 +3349,7 @@ fn check_expr_struct<'a, 'tcx>(fcx: &FnCtxt<'a,'tcx>,
           if let Some((opt_ty, segments, def)) =
                   resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
                                           expr.span, expr.id) {
-              if def != def::DefErr {
+              if def != Def::Err {
                   let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
                                                                                 expr.span,
                                                                                 def);
@@ -3758,7 +3758,7 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                              node_id: ast::NodeId)
                                              -> Option<(Option<Ty<'tcx>>,
                                                         &'a [hir::PathSegment],
-                                                        def::Def)>
+                                                        Def)>
 {
 
     // If fully resolved already, we don't have to do anything.
@@ -4263,29 +4263,30 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 // Returns the type parameter count and the type for the given definition.
 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 sp: Span,
-                                                defn: def::Def)
+                                                defn: Def)
                                                 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
     match defn {
-        def::DefLocal(_, nid) | def::DefUpvar(_, nid, _, _) => {
+        Def::Local(_, nid) | Def::Upvar(_, nid, _, _) => {
             let typ = fcx.local_ty(sp, nid);
             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
              ty::GenericPredicates::empty())
         }
-        def::DefFn(id, _) | def::DefMethod(id) |
-        def::DefStatic(id, _) | def::DefVariant(_, id, _) |
-        def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id) => {
+        Def::Fn(id) | Def::Method(id) |
+        Def::Static(id, _) | Def::Variant(_, id) |
+        Def::Struct(id) | Def::Const(id) | Def::AssociatedConst(id) => {
             (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
         }
-        def::DefTrait(_) |
-        def::DefTy(..) |
-        def::DefAssociatedTy(..) |
-        def::DefPrimTy(_) |
-        def::DefTyParam(..) |
-        def::DefMod(..) |
-        def::DefForeignMod(..) |
-        def::DefLabel(..) |
-        def::DefSelfTy(..) |
-        def::DefErr => {
+        Def::Trait(_) |
+        Def::Enum(..) |
+        Def::TyAlias(..) |
+        Def::AssociatedTy(..) |
+        Def::PrimTy(_) |
+        Def::TyParam(..) |
+        Def::Mod(..) |
+        Def::ForeignMod(..) |
+        Def::Label(..) |
+        Def::SelfTy(..) |
+        Def::Err => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
         }
     }
@@ -4298,7 +4299,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
-                                  def: def::Def,
+                                  def: Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
     debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
@@ -4382,14 +4383,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
-        def::DefSelfTy(..) |
-        def::DefStruct(..) |
-        def::DefVariant(..) |
-        def::DefTy(..) |
-        def::DefAssociatedTy(..) |
-        def::DefTrait(..) |
-        def::DefPrimTy(..) |
-        def::DefTyParam(..) => {
+        Def::SelfTy(..) |
+        Def::Struct(..) |
+        Def::Variant(..) |
+        Def::Enum(..) |
+        Def::TyAlias(..) |
+        Def::AssociatedTy(..) |
+        Def::Trait(..) |
+        Def::PrimTy(..) |
+        Def::TyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
             segment_spaces = vec![None; segments.len() - 1];
@@ -4397,15 +4399,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         // Case 2. Reference to a top-level value.
-        def::DefFn(..) |
-        def::DefConst(..) |
-        def::DefStatic(..) => {
+        Def::Fn(..) |
+        Def::Const(..) |
+        Def::Static(..) => {
             segment_spaces = vec![None; segments.len() - 1];
             segment_spaces.push(Some(subst::FnSpace));
         }
 
         // Case 3. Reference to a method.
-        def::DefMethod(def_id) => {
+        Def::Method(def_id) => {
             let container = fcx.tcx().impl_or_trait_item(def_id).container();
             match container {
                 ty::TraitContainer(trait_did) => {
@@ -4426,7 +4428,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
 
-        def::DefAssociatedConst(def_id) => {
+        Def::AssociatedConst(def_id) => {
             let container = fcx.tcx().impl_or_trait_item(def_id).container();
             match container {
                 ty::TraitContainer(trait_did) => {
@@ -4450,12 +4452,12 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         // Other cases. Various nonsense that really shouldn't show up
         // here. If they do, an error will have been reported
         // elsewhere. (I hope)
-        def::DefMod(..) |
-        def::DefForeignMod(..) |
-        def::DefLocal(..) |
-        def::DefLabel(..) |
-        def::DefUpvar(..) |
-        def::DefErr => {
+        Def::Mod(..) |
+        Def::ForeignMod(..) |
+        Def::Local(..) |
+        Def::Label(..) |
+        Def::Upvar(..) |
+        Def::Err => {
             segment_spaces = vec![None; segments.len()];
         }
     }
@@ -4856,7 +4858,7 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &hir::Block) -> bool {
     // <id> nested anywhere inside the loop?
     (block_query(b, |e| {
         if let hir::ExprBreak(Some(_)) = e.node {
-            lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
+            lookup_full_def(cx, e.span, e.id) == Def::Label(id)
         } else {
             false
         }
index eb204c5641495ed11d248ad1e4be8b3b80468a27..db4f8d3a70c40a08410a39aceb300e0af2c57515 100644 (file)
@@ -60,7 +60,7 @@
 
 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
 use lint;
-use middle::def;
+use middle::def::Def;
 use middle::def_id::DefId;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
@@ -512,10 +512,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
     if let hir::TyPath(None, _) = ast_ty.node {
         let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
         match path_res.base_def {
-            def::DefSelfTy(Some(def_id), None) => {
+            Def::SelfTy(Some(def_id), None) => {
                 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
-            def::DefTyParam(_, _, def_id, _) => {
+            Def::TyParam(_, _, def_id, _) => {
                 path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
             _ => {
@@ -1007,11 +1007,7 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
         name: name,
         disr_val: disr_val,
         fields: fields,
-        kind: match *def {
-            hir::VariantData::Struct(..) => ty::VariantKind::Struct,
-            hir::VariantData::Tuple(..) => ty::VariantKind::Tuple,
-            hir::VariantData::Unit(..) => ty::VariantKind::Unit,
-        }
+        kind: VariantKind::from_variant_data(def),
     }
 }
 
@@ -1922,8 +1918,8 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
                 param.id,
                 param.span,
-                format!("defaults for type parameters are only allowed on type definitions, \
-                         like `struct` or `enum`"));
+                format!("defaults for type parameters are only allowed in `struct`, \
+                         `enum`, `type`, or `trait` definitions."));
         }
     }
 
index 55a1021f0fb9418ca3357292b586d25ec4b27881..fdc23f89de23779c444e63c7f9d1b1c6a9206364 100644 (file)
@@ -2565,24 +2565,6 @@ struct Bar<S, T> { x: Foo<S, T> }
 ```
 "##,
 
-//NB: not currently reachable
-E0247: r##"
-This error indicates an attempt to use a module name where a type is expected.
-For example:
-
-```
-mod MyMod {
-    mod MySubMod { }
-}
-
-fn do_something(x: MyMod::MySubMod) { }
-```
-
-In this example, we're attempting to take a parameter of type `MyMod::MySubMod`
-in the do_something function. This is not legal: `MyMod::MySubMod` is a module
-name, not a type.
-"##,
-
 E0248: r##"
 This error indicates an attempt to use a value where a type is expected. For
 example:
@@ -3438,6 +3420,7 @@ fn main() {
     E0242, // internal error looking up a definition
     E0245, // not a trait
 //  E0246, // invalid recursive type
+//  E0247,
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0328, // cannot implement Unsize explicitly
index acffbeabb24c13bd68e4efe4b390231922b3725a..17d71fa7be9a6b38d585e7d36c978176928e639f 100644 (file)
 pub use rustc::util;
 
 use front::map as hir_map;
-use middle::def;
+use middle::def::Def;
 use middle::infer::{self, TypeOrigin};
 use middle::subst;
 use middle::ty::{self, Ty, TypeFoldable};
@@ -162,7 +162,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
+fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> Def {
     match tcx.def_map.borrow().get(&id) {
         Some(x) => x.full_def(),
         None => {
index 30b478f486e0a8b1f771f0666b9e1824746152cd..9eac2fd41fa1e3a5863979d1a250b12dbe4fa8e2 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_front::hir;
 
 use rustc::middle::cstore::{self, CrateStore};
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::def_id::DefId;
 use rustc::middle::ty;
 use rustc::middle::subst;
@@ -68,46 +68,47 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
 }
 
 fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
-                  def: def::Def) -> Option<Vec<clean::Item>> {
+                  def: Def) -> Option<Vec<clean::Item>> {
     let mut ret = Vec::new();
     let did = def.def_id();
     let inner = match def {
-        def::DefTrait(did) => {
+        Def::Trait(did) => {
             record_extern_fqn(cx, did, clean::TypeTrait);
             clean::TraitItem(build_external_trait(cx, tcx, did))
         }
-        def::DefFn(did, false) => {
-            // If this function is a tuple struct constructor, we just skip it
+        Def::Fn(did) => {
             record_extern_fqn(cx, did, clean::TypeFunction);
             clean::FunctionItem(build_external_function(cx, tcx, did))
         }
-        def::DefStruct(did) => {
+        Def::Struct(did)
+                // If this is a struct constructor, we skip it
+                if tcx.sess.cstore.tuple_struct_definition_if_ctor(did).is_none() => {
             record_extern_fqn(cx, did, clean::TypeStruct);
             ret.extend(build_impls(cx, tcx, did));
             clean::StructItem(build_struct(cx, tcx, did))
         }
-        def::DefTy(did, false) => {
+        Def::TyAlias(did) => {
             record_extern_fqn(cx, did, clean::TypeTypedef);
             ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
-        def::DefTy(did, true) => {
+        Def::Enum(did) => {
             record_extern_fqn(cx, did, clean::TypeEnum);
             ret.extend(build_impls(cx, tcx, did));
             build_type(cx, tcx, did)
         }
         // Assume that the enum type is reexported next to the variant, and
         // variants don't show up in documentation specially.
-        def::DefVariant(..) => return Some(Vec::new()),
-        def::DefMod(did) => {
+        Def::Variant(..) => return Some(Vec::new()),
+        Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeModule);
             clean::ModuleItem(build_module(cx, tcx, did))
         }
-        def::DefStatic(did, mtbl) => {
+        Def::Static(did, mtbl) => {
             record_extern_fqn(cx, did, clean::TypeStatic);
             clean::StaticItem(build_static(cx, tcx, did, mtbl))
         }
-        def::DefConst(did) | def::DefAssociatedConst(did) => {
+        Def::Const(did) | Def::AssociatedConst(did) => {
             record_extern_fqn(cx, did, clean::TypeConst);
             clean::ConstantItem(build_const(cx, tcx, did))
         }
@@ -258,7 +259,7 @@ fn populate_impls(cx: &DocContext, tcx: &ty::ctxt,
                           impls: &mut Vec<clean::Item>) {
             match def {
                 cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
-                cstore::DlDef(def::DefMod(did)) => {
+                cstore::DlDef(Def::Mod(did)) => {
                     for item in tcx.sess.cstore.item_children(did) {
                         populate_impls(cx, tcx, item.def, impls)
                     }
@@ -455,7 +456,7 @@ fn fill_in(cx: &DocContext, tcx: &ty::ctxt, did: DefId,
         let mut visited = HashSet::new();
         for item in tcx.sess.cstore.item_children(did) {
             match item.def {
-                cstore::DlDef(def::DefForeignMod(did)) => {
+                cstore::DlDef(Def::ForeignMod(did)) => {
                     fill_in(cx, tcx, did, items);
                 }
                 cstore::DlDef(def) if item.vis == hir::Public => {
index d2a5fd457d2fba4cdc9183f06796ad1d05ee037b..03e2a7139b278c03c8ff67488a47998a94fc77e9 100644 (file)
@@ -36,7 +36,7 @@
 
 use rustc_trans::back::link;
 use rustc::middle::cstore::{self, CrateStore};
-use rustc::middle::def;
+use rustc::middle::def::Def;
 use rustc::middle::def_id::{DefId, DefIndex};
 use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::middle::ty;
@@ -230,7 +230,7 @@ fn clean(&self, cx: &DocContext) -> ExternalCrate {
         cx.tcx_opt().map(|tcx| {
             for item in tcx.sess.cstore.crate_top_level_items(self.0) {
                 let did = match item.def {
-                    cstore::DlDef(def::DefMod(did)) => did,
+                    cstore::DlDef(Def::Mod(did)) => did,
                     _ => continue
                 };
                 let attrs = inline::load_attrs(cx, tcx, did);
@@ -2607,7 +2607,7 @@ fn resolve_type(cx: &DocContext,
     debug!("resolve_type: def={:?}", def);
 
     let is_generic = match def {
-        def::DefPrimTy(p) => match p {
+        Def::PrimTy(p) => match p {
             hir::TyStr => return Primitive(Str),
             hir::TyBool => return Primitive(Bool),
             hir::TyChar => return Primitive(Char),
@@ -2624,30 +2624,30 @@ fn resolve_type(cx: &DocContext,
             hir::TyFloat(ast::TyF32) => return Primitive(F32),
             hir::TyFloat(ast::TyF64) => return Primitive(F64),
         },
-        def::DefSelfTy(..) if path.segments.len() == 1 => {
+        Def::SelfTy(..) if path.segments.len() == 1 => {
             return Generic(special_idents::type_self.name.to_string());
         }
-        def::DefSelfTy(..) | def::DefTyParam(..) => true,
+        Def::SelfTy(..) | Def::TyParam(..) => true,
         _ => false,
     };
     let did = register_def(&*cx, def);
     ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
 }
 
-fn register_def(cx: &DocContext, def: def::Def) -> DefId {
+fn register_def(cx: &DocContext, def: Def) -> DefId {
     debug!("register_def({:?})", def);
 
     let (did, kind) = match def {
-        def::DefFn(i, _) => (i, TypeFunction),
-        def::DefTy(i, false) => (i, TypeTypedef),
-        def::DefTy(i, true) => (i, TypeEnum),
-        def::DefTrait(i) => (i, TypeTrait),
-        def::DefStruct(i) => (i, TypeStruct),
-        def::DefMod(i) => (i, TypeModule),
-        def::DefStatic(i, _) => (i, TypeStatic),
-        def::DefVariant(i, _, _) => (i, TypeEnum),
-        def::DefSelfTy(Some(def_id), _) => (def_id, TypeTrait),
-        def::DefSelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
+        Def::Fn(i) => (i, TypeFunction),
+        Def::TyAlias(i) => (i, TypeTypedef),
+        Def::Enum(i) => (i, TypeEnum),
+        Def::Trait(i) => (i, TypeTrait),
+        Def::Struct(i) => (i, TypeStruct),
+        Def::Mod(i) => (i, TypeModule),
+        Def::Static(i, _) => (i, TypeStatic),
+        Def::Variant(i, _) => (i, TypeEnum),
+        Def::SelfTy(Some(def_id), _) => (def_id, TypeTrait),
+        Def::SelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
         _ => return def.def_id()
     };
     if did.is_local() { return did }
index 1a4085e30e8f3560857671fe22de472d7b14fdf1..b0df209d3dc526e773eebed0b82a88fcf7b2e1dd 100644 (file)
@@ -456,23 +456,44 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        decl.decl)
             }
             clean::Tuple(ref typs) => {
-                primitive_link(f, clean::PrimitiveTuple,
-                               &*match &**typs {
-                                    [ref one] => format!("({},)", one),
-                                    many => format!("({})", CommaSep(&many)),
-                               })
+                match &**typs {
+                    [] => primitive_link(f, clean::PrimitiveTuple, "()"),
+                    [ref one] => {
+                        try!(primitive_link(f, clean::PrimitiveTuple, "("));
+                        try!(write!(f, "{}", one));
+                        primitive_link(f, clean::PrimitiveTuple, ")")
+                    }
+                    many => {
+                        try!(primitive_link(f, clean::PrimitiveTuple, "("));
+                        try!(write!(f, "{}", CommaSep(&many)));
+                        primitive_link(f, clean::PrimitiveTuple, ")")
+                    }
+                }
             }
             clean::Vector(ref t) => {
-                primitive_link(f, clean::Slice, &format!("[{}]", **t))
+                try!(primitive_link(f, clean::Slice, &format!("[")));
+                try!(write!(f, "{}", t));
+                primitive_link(f, clean::Slice, &format!("]"))
             }
             clean::FixedVector(ref t, ref s) => {
+                try!(primitive_link(f, clean::PrimitiveType::Array, "["));
+                try!(write!(f, "{}", t));
                 primitive_link(f, clean::PrimitiveType::Array,
-                               &format!("[{}; {}]", **t, *s))
+                               &format!("; {}]", *s))
             }
             clean::Bottom => f.write_str("!"),
             clean::RawPointer(m, ref t) => {
-                primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
-                               &format!("*{}{}", RawMutableSpace(m), **t))
+                match **t {
+                    clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
+                        primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
+                                       &format!("*{}{}", RawMutableSpace(m), t))
+                    }
+                    _ => {
+                        try!(primitive_link(f, clean::PrimitiveType::PrimitiveRawPointer,
+                                            &format!("*{}", RawMutableSpace(m))));
+                        write!(f, "{}", t)
+                    }
+                }
             }
             clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => {
                 let lt = match *l {
index 227981d68fbb4c7cacd5021044e75b4ab7f3346d..ffcd22fa8209604daeda1542306d22cc1e13c07a 100644 (file)
@@ -148,7 +148,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
         "".to_string()
     } else {
         format!("<a href='{}{}/index.html'>\
-                 <img src='{}' alt='' width='100'></a>",
+                 <img src='{}' alt='logo' width='100'></a>",
                 page.root_path, layout.krate,
                 layout.logo)
     },
index 0bde582c19f286da7b12798c378e25e4fbb3eefb..c751cdeb6f790d65f1c43a78067d2f554fa16bd5 100644 (file)
@@ -383,7 +383,7 @@ a {
 }
 
 .content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; }
-.content span.struct, .content a.struct, .block a.current.struct { color: #e53700; }
+.content span.struct, .content a.struct, .block a.current.struct { color: #df3600; }
 .content a.type { color: #e57300; }
 .content a.macro { color: #068000; }
 .block a.current.crate { font-weight: 500; }
index e138d62f986c15b559f5528f4231cc1ea6f54208..02bb5221886df4c21e7466d21526f415b6245cb5 100644 (file)
@@ -106,14 +106,14 @@ a {
 }
 
 .docblock a, .stability a {
-    color: #4e8bca;
+    color: #3873AD;
 }
 
 a.test-arrow {
     color: #f5f5f5;
 }
 
-.content span.trait, .content a.trait, .block a.current.trait { color: #8866ff; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
 
 .search-input {
     color: #555;
index e43101b7c9d0d7a2740e78f3ea46824e135b1ecb..43bf86a00399c8da07108937e10afdf3da3a2fd9 100644 (file)
@@ -272,6 +272,35 @@ fn test_resize_policy() {
 /// }
 /// ```
 ///
+/// `HashMap` also implements an [`Entry API`](#method.entry), which allows
+/// for more complex methods of getting, setting, updating and removing keys and
+/// their values:
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// // type inference lets us omit an explicit type signature (which
+/// // would be `HashMap<&str, u8>` in this example).
+/// let mut player_stats = HashMap::new();
+///
+/// fn random_stat_buff() -> u8 {
+///   // could actually return some random value here - let's just return
+///   // some fixed value for now
+///   42
+/// }
+///
+/// // insert a key only if it doesn't already exist
+/// player_stats.entry("health").or_insert(100);
+///
+/// // insert a key using a function that provides a new value only if it
+/// // doesn't already exist
+/// player_stats.entry("defence").or_insert_with(random_stat_buff);
+///
+/// // update a key, guarding against the key possibly not being set
+/// let stat = player_stats.entry("attack").or_insert(100);
+/// *stat += random_stat_buff();
+/// ```
+///
 /// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`.
 /// We must also derive `PartialEq`.
 ///
index c44a4bfe0f16157a6698ffbb5e8e14a89a49037a..ee367193e456b165ec8c70142023c83f7f02b643 100644 (file)
@@ -182,6 +182,13 @@ fn description(&self) -> &str {
     }
 }
 
+#[stable(feature = "str_parse_error2", since = "1.8.0")]
+impl Error for string::ParseError {
+    fn description(&self) -> &str {
+        match *self {}
+    }
+}
+
 // copied from any.rs
 impl Error + 'static {
     /// Returns true if the boxed type is the same as `T`
index d6aa746f4cb5333ed1eec65adf8dd0cb1872be13..9d505607a60c48abac8909ecae77a2690a8b29b8 100644 (file)
@@ -407,7 +407,6 @@ impl CStr {
     /// # fn main() {
     /// use std::ffi::CStr;
     /// use std::os::raw::c_char;
-    /// use std::str;
     ///
     /// extern {
     ///     fn my_string() -> *const c_char;
@@ -415,8 +414,7 @@ impl CStr {
     ///
     /// unsafe {
     ///     let slice = CStr::from_ptr(my_string());
-    ///     println!("string returned: {}",
-    ///              str::from_utf8(slice.to_bytes()).unwrap());
+    ///     println!("string returned: {}", slice.to_str().unwrap());
     /// }
     /// # }
     /// ```
index 635ed91f35da41c5335c36d4c5cd57e569de3d53..414a0ebd11fa27ce0cc8c4b79f68b45a252229cc 100644 (file)
@@ -375,7 +375,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 }
 
 impl OpenOptions {
-    /// Creates a blank net set of options ready for configuration.
+    /// Creates a blank new set of options ready for configuration.
     ///
     /// All options are initially set to `false`.
     ///
@@ -384,7 +384,8 @@ impl OpenOptions {
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().open("foo.txt");
+    /// let mut options = OpenOptions::new();
+    /// let file = options.read(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> OpenOptions {
@@ -413,6 +414,9 @@ pub fn read(&mut self, read: bool) -> &mut OpenOptions {
     /// This option, when true, will indicate that the file should be
     /// `write`-able if opened.
     ///
+    /// If a file already exist, any write calls on the file will overwrite its
+    /// contents, without truncating it.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -429,13 +433,30 @@ pub fn write(&mut self, write: bool) -> &mut OpenOptions {
     ///
     /// This option, when true, means that writes will append to a file instead
     /// of overwriting previous contents.
+    /// Note that setting `.write(true).append(true)` has the same effect as
+    /// setting only `.append(true)`.
+    ///
+    /// For most filesystems the operating system guarantees all writes are
+    /// atomic: no writes get mangled because another process writes at the same
+    /// time.
+    ///
+    /// One maybe obvious note when using append-mode: make sure that all data
+    /// that belongs together, is written the the file in one operation. This
+    /// can be done by concatenating strings before passing them to `write()`,
+    /// or using a buffered writer (with a more than adequately sized buffer)
+    /// and calling `flush()` when the message is complete.
+    ///
+    /// If a file is opened with both read and append access, beware that after
+    /// opening and after every write the position for reading may be set at the
+    /// end of the file. So before writing save the current position (using
+    /// `seek(SeekFrom::Current(0))`, and restore it before the next read.
     ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().write(true).append(true).open("foo.txt");
+    /// let file = OpenOptions::new().append(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, append: bool) -> &mut OpenOptions {
@@ -447,6 +468,8 @@ pub fn append(&mut self, append: bool) -> &mut OpenOptions {
     /// If a file is successfully opened with this option set it will truncate
     /// the file to 0 length if it already exists.
     ///
+    /// The file must be opened with write access for truncate to work.
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -464,18 +487,54 @@ pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
     /// This option indicates whether a new file will be created if the file
     /// does not yet already exist.
     ///
+    /// The file must be opened with write or append access in order to create
+    /// a new file.
+    ///
     /// # Examples
     ///
     /// ```no_run
     /// use std::fs::OpenOptions;
     ///
-    /// let file = OpenOptions::new().create(true).open("foo.txt");
+    /// let file = OpenOptions::new().write(true).create(true).open("foo.txt");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn create(&mut self, create: bool) -> &mut OpenOptions {
         self.0.create(create); self
     }
 
+    /// Sets the option to always create a new file.
+    ///
+    /// This option indicates whether a new file will be created.
+    /// No file is allowed to exist at the target location, also no (dangling)
+    /// symlink.
+    ///
+    /// This option is usefull because it as atomic. Otherwise between checking
+    /// whether a file exists and creating a new one, the file may have been
+    /// created by another process (a TOCTOU race condition / attack).
+    ///
+    /// If `.create_new(true)` is set, `.create()` and `.truncate()` are
+    /// ignored.
+    ///
+    /// The file must be opened with write or append access in order to create
+    /// a new file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(expand_open_options)]
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().write(true)
+    ///                              .create_new(true)
+    ///                              .open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
+        self.0.create_new(create_new); self
+    }
+
     /// Opens a file at `path` with the options specified by `self`.
     ///
     /// # Errors
@@ -483,10 +542,13 @@ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
     /// This function will return an error under a number of different
     /// circumstances, to include but not limited to:
     ///
-    /// * Opening a file that does not exist with read access.
+    /// * Opening a file that does not exist without setting `create` or
+    ///   `create_new`.
     /// * Attempting to open a file with access that the user lacks
     ///   permissions for
     /// * Filesystem-level errors (full disk, etc)
+    /// * Invalid combinations of open options (truncate without write access,
+    ///   no access mode set, etc)
     ///
     /// # Examples
     ///
@@ -2098,61 +2160,114 @@ fn c<T: Clone>(t: &T) -> T { t.clone() }
 
         let mut r = OO::new(); r.read(true);
         let mut w = OO::new(); w.write(true);
-        let mut rw = OO::new(); rw.write(true).read(true);
-
-        match r.open(&tmpdir.join("a")) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-
-        // Perform each one twice to make sure that it succeeds the second time
-        // (where the file exists)
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        assert!(tmpdir.join("b").exists());
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        check!(w.open(&tmpdir.join("b")));
-
+        let mut rw = OO::new(); rw.read(true).write(true);
+        let mut a = OO::new(); a.append(true);
+        let mut ra = OO::new(); ra.read(true).append(true);
+
+        let invalid_options = if cfg!(windows) { "The parameter is incorrect" }
+                              else { "Invalid argument" };
+
+        // Test various combinations of creation modes and access modes.
+        //
+        // Allowed:
+        // creation mode           | read  | write | read-write | append | read-append |
+        // :-----------------------|:-----:|:-----:|:----------:|:------:|:-----------:|
+        // not set (open existing) |   X   |   X   |     X      |   X    |      X      |
+        // create                  |       |   X   |     X      |   X    |      X      |
+        // truncate                |       |   X   |     X      |        |             |
+        // create and truncate     |       |   X   |     X      |        |             |
+        // create_new              |       |   X   |     X      |   X    |      X      |
+        //
+        // tested in reverse order, so 'create_new' creates the file, and 'open existing' opens it.
+
+        // write-only
+        check!(c(&w).create_new(true).open(&tmpdir.join("a")));
+        check!(c(&w).create(true).truncate(true).open(&tmpdir.join("a")));
+        check!(c(&w).truncate(true).open(&tmpdir.join("a")));
+        check!(c(&w).create(true).open(&tmpdir.join("a")));
+        check!(c(&w).open(&tmpdir.join("a")));
+
+        // read-only
+        error!(c(&r).create_new(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).create(true).truncate(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).truncate(true).open(&tmpdir.join("b")), invalid_options);
+        error!(c(&r).create(true).open(&tmpdir.join("b")), invalid_options);
+        check!(c(&r).open(&tmpdir.join("a"))); // try opening the file created with write_only
+
+        // read-write
+        check!(c(&rw).create_new(true).open(&tmpdir.join("c")));
+        check!(c(&rw).create(true).truncate(true).open(&tmpdir.join("c")));
+        check!(c(&rw).truncate(true).open(&tmpdir.join("c")));
         check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        assert!(tmpdir.join("c").exists());
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        check!(rw.open(&tmpdir.join("c")));
-
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        assert!(tmpdir.join("d").exists());
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        check!(c(&w).append(true).open(&tmpdir.join("d")));
-
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        assert!(tmpdir.join("e").exists());
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        check!(c(&rw).append(true).open(&tmpdir.join("e")));
-
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        assert!(tmpdir.join("f").exists());
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
-
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        assert!(tmpdir.join("g").exists());
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
-
-        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
+        check!(c(&rw).open(&tmpdir.join("c")));
+
+        // append
+        check!(c(&a).create_new(true).open(&tmpdir.join("d")));
+        error!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options);
+        error!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options);
+        check!(c(&a).create(true).open(&tmpdir.join("d")));
+        check!(c(&a).open(&tmpdir.join("d")));
+
+        // read-append
+        check!(c(&ra).create_new(true).open(&tmpdir.join("e")));
+        error!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options);
+        error!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options);
+        check!(c(&ra).create(true).open(&tmpdir.join("e")));
+        check!(c(&ra).open(&tmpdir.join("e")));
+
+        // Test opening a file without setting an access mode
+        let mut blank = OO::new();
+         error!(blank.create(true).open(&tmpdir.join("f")), invalid_options);
+
+        // Test write works
+        check!(check!(File::create(&tmpdir.join("h"))).write("foobar".as_bytes()));
+
+        // Test write fails for read-only
         check!(r.open(&tmpdir.join("h")));
         {
             let mut f = check!(r.open(&tmpdir.join("h")));
             assert!(f.write("wut".as_bytes()).is_err());
         }
+
+        // Test write overwrites
+        {
+            let mut f = check!(c(&w).open(&tmpdir.join("h")));
+            check!(f.write("baz".as_bytes()));
+        }
+        {
+            let mut f = check!(c(&r).open(&tmpdir.join("h")));
+            let mut b = vec![0; 6];
+            check!(f.read(&mut b));
+            assert_eq!(b, "bazbar".as_bytes());
+        }
+
+        // Test truncate works
+        {
+            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
+            check!(f.write("foo".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+
+        // Test append works
         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
         {
-            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            let mut f = check!(c(&a).open(&tmpdir.join("h")));
             check!(f.write("bar".as_bytes()));
         }
         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
+
+        // Test .append(true) equals .write(true).append(true)
         {
-            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
+            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            check!(f.write("baz".as_bytes()));
         }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 9);
+    }
+
+    #[test]
+    fn _assert_send_sync() {
+        fn _assert_send_sync<T: Send + Sync>() {}
+        _assert_send_sync::<OpenOptions>();
     }
 
     #[test]
index a9a79fe2c7733f3afc9332c2f99f8f62b4724791..5ec51eaa567331cb3551e859fc332c8e4e653098 100644 (file)
@@ -47,7 +47,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BufReader<R> {
     inner: R,
-    buf: Vec<u8>,
+    buf: Box<[u8]>,
     pos: usize,
     cap: usize,
 }
@@ -92,7 +92,7 @@ pub fn new(inner: R) -> BufReader<R> {
     pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
         BufReader {
             inner: inner,
-            buf: vec![0; cap],
+            buf: vec![0; cap].into_boxed_slice(),
             pos: 0,
             cap: 0,
         }
@@ -300,6 +300,10 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 pub struct BufWriter<W: Write> {
     inner: Option<W>,
     buf: Vec<u8>,
+    // #30888: If the inner writer panics in a call to write, we don't want to
+    // write the buffered data a second time in BufWriter's destructor. This
+    // flag tells the Drop impl if it should skip the flush.
+    panicked: bool,
 }
 
 /// An error returned by `into_inner` which combines an error that
@@ -364,6 +368,7 @@ pub fn with_capacity(cap: usize, inner: W) -> BufWriter<W> {
         BufWriter {
             inner: Some(inner),
             buf: Vec::with_capacity(cap),
+            panicked: false,
         }
     }
 
@@ -372,7 +377,11 @@ fn flush_buf(&mut self) -> io::Result<()> {
         let len = self.buf.len();
         let mut ret = Ok(());
         while written < len {
-            match self.inner.as_mut().unwrap().write(&self.buf[written..]) {
+            self.panicked = true;
+            let r = self.inner.as_mut().unwrap().write(&self.buf[written..]);
+            self.panicked = false;
+
+            match r {
                 Ok(0) => {
                     ret = Err(Error::new(ErrorKind::WriteZero,
                                          "failed to write the buffered data"));
@@ -455,7 +464,10 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
             try!(self.flush_buf());
         }
         if buf.len() >= self.buf.capacity() {
-            self.inner.as_mut().unwrap().write(buf)
+            self.panicked = true;
+            let r = self.inner.as_mut().unwrap().write(buf);
+            self.panicked = false;
+            r
         } else {
             let amt = cmp::min(buf.len(), self.buf.capacity());
             Write::write(&mut self.buf, &buf[..amt])
@@ -489,7 +501,7 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> Drop for BufWriter<W> {
     fn drop(&mut self) {
-        if self.inner.is_some() {
+        if self.inner.is_some() && !self.panicked {
             // dtors should not panic, so we ignore a failed flush
             let _r = self.flush_buf();
         }
@@ -777,6 +789,8 @@ mod tests {
     use prelude::v1::*;
     use io::prelude::*;
     use io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
+    use sync::atomic::{AtomicUsize, Ordering};
+    use thread;
     use test;
 
     /// A dummy reader intended at testing short-reads propagation.
@@ -1065,6 +1079,29 @@ fn flush(&mut self) -> io::Result<()> {
         panic!();
     }
 
+    #[test]
+    fn panic_in_write_doesnt_flush_in_drop() {
+        static WRITES: AtomicUsize = AtomicUsize::new(0);
+
+        struct PanicWriter;
+
+        impl Write for PanicWriter {
+            fn write(&mut self, _: &[u8]) -> io::Result<usize> {
+                WRITES.fetch_add(1, Ordering::SeqCst);
+                panic!();
+            }
+            fn flush(&mut self) -> io::Result<()> { Ok(()) }
+        }
+
+        thread::spawn(|| {
+            let mut writer = BufWriter::new(PanicWriter);
+            writer.write(b"hello world");
+            writer.flush();
+        }).join().err().unwrap();
+
+        assert_eq!(WRITES.load(Ordering::SeqCst), 1);
+    }
+
     #[bench]
     fn bench_buffered_reader(b: &mut test::Bencher) {
         b.iter(|| {
index c043b41ed21f0e3403a5dd2ef76acb4606cc3346..27702e2e59aefdac347ba4fe00f2f61094b6bebc 100644 (file)
@@ -98,7 +98,7 @@ fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
 
     #[cfg(not(target_os = "linux"))]
     fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        haystack.iter().rposition(|&b| b == needle)
+        fallback::memrchr(needle, haystack)
     }
 
     memrchr_specific(needle, haystack)
index 8d21ba8f661c80f53c5e8d694b8f919c77c11ea2..2a3117864d06336584490f11dd4593ad91bedb3a 100644 (file)
@@ -118,8 +118,38 @@ pub trait OpenOptionsExt {
     ///
     /// If a new file is created as part of a `File::open_opts` call then this
     /// specified `mode` will be used as the permission bits for the new file.
+    /// If no `mode` is set, the default of `0o666` will be used.
+    /// The operating system masks out bits with the systems `umask`, to produce
+    /// the final permissions.
     #[stable(feature = "fs_ext", since = "1.1.0")]
     fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
+
+    /// Pass custom flags to the `flags` agument of `open`.
+    ///
+    /// The bits that define the access mode are masked out with `O_ACCMODE`, to
+    /// ensure they do not interfere with the access mode set by Rusts options.
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.write(true);
+    /// if cfg!(unix) {
+    ///     options.custom_flags(libc::O_NOFOLLOW);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    fn custom_flags(&mut self, flags: i32) -> &mut Self;
 }
 
 #[stable(feature = "fs_ext", since = "1.1.0")]
@@ -127,6 +157,10 @@ impl OpenOptionsExt for OpenOptions {
     fn mode(&mut self, mode: raw::mode_t) -> &mut OpenOptions {
         self.as_inner_mut().mode(mode); self
     }
+
+    fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
+    }
 }
 
 // Hm, why are there casts here to the returned type, shouldn't the types always
@@ -281,4 +315,3 @@ fn mode(&mut self, mode: raw::mode_t) -> &mut fs::DirBuilder {
         self
     }
 }
-
index 10fda3fcd7fa5165ce82e70ea0fab45d8517559e..d2d2ce35d84a0adfe401f80935293cb91929f701 100644 (file)
@@ -50,9 +50,15 @@ pub struct DirEntry {
 
 #[derive(Clone)]
 pub struct OpenOptions {
-    flags: c_int,
+    // generic
     read: bool,
     write: bool,
+    append: bool,
+    truncate: bool,
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: i32,
     mode: mode_t,
 }
 
@@ -233,43 +239,60 @@ fn name_bytes(&self) -> &[u8] {
 impl OpenOptions {
     pub fn new() -> OpenOptions {
         OpenOptions {
-            flags: libc::O_CLOEXEC,
+            // generic
             read: false,
             write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
             mode: 0o666,
         }
     }
 
-    pub fn read(&mut self, read: bool) {
-        self.read = read;
-    }
-
-    pub fn write(&mut self, write: bool) {
-        self.write = write;
-    }
-
-    pub fn append(&mut self, append: bool) {
-        self.flag(libc::O_APPEND, append);
-    }
-
-    pub fn truncate(&mut self, truncate: bool) {
-        self.flag(libc::O_TRUNC, truncate);
-    }
-
-    pub fn create(&mut self, create: bool) {
-        self.flag(libc::O_CREAT, create);
-    }
-
-    pub fn mode(&mut self, mode: raw::mode_t) {
-        self.mode = mode as mode_t;
+    pub fn read(&mut self, read: bool) { self.read = read; }
+    pub fn write(&mut self, write: bool) { self.write = write; }
+    pub fn append(&mut self, append: bool) { self.append = append; }
+    pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+
+    pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; }
+    pub fn mode(&mut self, mode: raw::mode_t) { self.mode = mode as mode_t; }
+
+    fn get_access_mode(&self) -> io::Result<c_int> {
+        match (self.read, self.write, self.append) {
+            (true,  false, false) => Ok(libc::O_RDONLY),
+            (false, true,  false) => Ok(libc::O_WRONLY),
+            (true,  true,  false) => Ok(libc::O_RDWR),
+            (false, _,     true)  => Ok(libc::O_WRONLY | libc::O_APPEND),
+            (true,  _,     true)  => Ok(libc::O_RDWR | libc::O_APPEND),
+            (false, false, false) => Err(Error::from_raw_os_error(libc::EINVAL)),
+        }
     }
 
-    fn flag(&mut self, bit: c_int, on: bool) {
-        if on {
-            self.flags |= bit;
-        } else {
-            self.flags &= !bit;
+    fn get_creation_mode(&self) -> io::Result<c_int> {
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(libc::EINVAL));
+                },
         }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => 0,
+                (true,  false, false) => libc::O_CREAT,
+                (false, true,  false) => libc::O_TRUNC,
+                (true,  true,  false) => libc::O_CREAT | libc::O_TRUNC,
+                (_,      _,    true)  => libc::O_CREAT | libc::O_EXCL,
+           })
     }
 }
 
@@ -280,12 +303,10 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
     }
 
     pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
-        let flags = opts.flags | match (opts.read, opts.write) {
-            (true, true) => libc::O_RDWR,
-            (false, true) => libc::O_WRONLY,
-            (true, false) |
-            (false, false) => libc::O_RDONLY,
-        };
+        let flags = libc::O_CLOEXEC |
+                    try!(opts.get_access_mode()) |
+                    try!(opts.get_creation_mode()) |
+                    (opts.custom_flags as c_int & !libc::O_ACCMODE);
         let fd = try!(cvt_r(|| unsafe {
             libc::open(path.as_ptr(), flags, opts.mode as c_int)
         }));
index 34e32d0d5b62af67e27ef641967cc5514fb5ad88..6e8090a223516434662df5b4f5497422cce35a2b 100644 (file)
 pub const OPEN_ALWAYS: DWORD = 4;
 pub const OPEN_EXISTING: DWORD = 3;
 pub const TRUNCATE_EXISTING: DWORD = 5;
-pub const FILE_APPEND_DATA: DWORD = 0x00000004;
+
 pub const FILE_READ_DATA: DWORD = 0x00000001;
 pub const FILE_WRITE_DATA: DWORD = 0x00000002;
-pub const STANDARD_RIGHTS_READ: DWORD = 0x20000;
-pub const STANDARD_RIGHTS_WRITE: DWORD = 0x20000;
-pub const FILE_WRITE_EA: DWORD = 0x00000010;
+pub const FILE_APPEND_DATA: DWORD = 0x00000004;
 pub const FILE_READ_EA: DWORD = 0x00000008;
-pub const SYNCHRONIZE: DWORD = 0x00100000;
-pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
+pub const FILE_WRITE_EA: DWORD = 0x00000010;
+pub const FILE_EXECUTE: DWORD = 0x00000020;
 pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080;
+pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
+
+pub const DELETE: DWORD = 0x00008000;
+pub const READ_CONTROL: DWORD = 0x00020000;
+pub const WRITE_DAC: DWORD = 0x00040000;
+pub const WRITE_OWNER: DWORD = 0x00080000;
+pub const SYNCHRONIZE: DWORD = 0x00100000;
+
+pub const GENERIC_READ: DWORD = 0x80000000;
+pub const GENERIC_WRITE: DWORD = 0x40000000;
+pub const GENERIC_EXECUTE: DWORD = 0x20000000;
+pub const GENERIC_ALL: DWORD = 0x10000000;
+
+pub const STANDARD_RIGHTS_READ: DWORD = READ_CONTROL;
+pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL;
+pub const STANDARD_RIGHTS_EXECUTE: DWORD = READ_CONTROL;
 pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA |
                                      FILE_READ_ATTRIBUTES |
                                      FILE_READ_EA |
                                       FILE_APPEND_DATA |
                                       SYNCHRONIZE;
 
+pub const SECURITY_ANONYMOUS: DWORD = 0 << 16;
+pub const SECURITY_IDENTIFICATION: DWORD = 1 << 16;
+pub const SECURITY_IMPERSONATION: DWORD = 2 << 16;
+pub const SECURITY_DELEGATION: DWORD = 3 << 16;
+pub const SECURITY_CONTEXT_TRACKING: DWORD = 0x00040000;
+pub const SECURITY_EFFECTIVE_ONLY: DWORD = 0x00080000;
+pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
+
 #[repr(C)]
 #[derive(Copy)]
 pub struct WIN32_FIND_DATAW {
index 0d78d4de42b299a2e1dcf4557743250ec5ede742..d060c902fba2fe27a38feef827a2fe6f6cb291ca 100644 (file)
 pub trait OpenOptionsExt {
     /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
     /// with the specified value.
-    fn desired_access(&mut self, access: u32) -> &mut Self;
-
-    /// Overrides the `dwCreationDisposition` argument to the call to
-    /// `CreateFile` with the specified value.
     ///
-    /// This will override any values of the standard `create` flags, for
-    /// example.
-    fn creation_disposition(&mut self, val: u32) -> &mut Self;
-
-    /// Overrides the `dwFlagsAndAttributes` argument to the call to
-    /// `CreateFile` with the specified value.
+    /// This will override the `read`, `write`, and `append` flags on the
+    /// `OpenOptions` structure. This method provides fine-grained control over
+    /// the permissions to read, write and append data, attributes (like hidden
+    /// and system) and extended attributes.
+    ///
+    /// # Examples
     ///
-    /// This will override any values of the standard flags on the
-    /// `OpenOptions` structure.
-    fn flags_and_attributes(&mut self, val: u32) -> &mut Self;
+    /// ```no_run
+    /// #![feature(open_options_ext)]
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// // Open without read and write permission, for example if you only need
+    /// // to call `stat()` on the file
+    /// let file = OpenOptions::new().access_mode(0).open("foo.txt");
+    /// ```
+    fn access_mode(&mut self, access: u32) -> &mut Self;
 
     /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
     /// the specified value.
     ///
-    /// This will override any values of the standard flags on the
-    /// `OpenOptions` structure.
+    /// By default `share_mode` is set to
+    /// `FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE`. Specifying
+    /// less permissions denies others to read from, write to and/or delete the
+    /// file while it is open.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(open_options_ext)]
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// // Do not allow others to read or modify this file while we have it open
+    /// // for writing
+    /// let file = OpenOptions::new().write(true)
+    ///                              .share_mode(0)
+    ///                              .open("foo.txt");
+    /// ```
     fn share_mode(&mut self, val: u32) -> &mut Self;
+
+    /// Sets extra flags for the `dwFileFlags` argument to the call to
+    /// `CreateFile2` (or combines it with `attributes` and `security_qos_flags`
+    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate winapi;
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.create(true).write(true);
+    /// if cfg!(windows) {
+    ///     options.custom_flags(winapi::FILE_FLAG_DELETE_ON_CLOSE);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[unstable(feature = "expand_open_options",
+               reason = "recently added",
+               issue = "30014")]
+    fn custom_flags(&mut self, flags: u32) -> &mut Self;
+
+    /// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
+    /// the specified value (or combines it with `custom_flags` and
+    /// `security_qos_flags` to set the `dwFlagsAndAttributes` for
+    /// `CreateFile`).
+    ///
+    /// If a _new_ file is created because it does not yet exist and
+    ///`.create(true)` or `.create_new(true)` are specified, the new file is
+    /// given the attributes declared with `.attributes()`.
+    ///
+    /// If an _existing_ file is opened with `.create(true).truncate(true)`, its
+    /// existing attributes are preserved and combined with the ones declared
+    /// with `.attributes()`.
+    ///
+    /// In all other cases the attributes get ignored.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// #![feature(open_options_ext)]
+    /// extern crate winapi;
+    /// use std::fs::OpenOptions;
+    /// use std::os::windows::fs::OpenOptionsExt;
+    ///
+    /// let file = OpenOptions::new().write(true).create(true)
+    ///                              .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
+    ///                              .open("foo.txt");
+    /// ```
+    fn attributes(&mut self, val: u32) -> &mut Self;
+
+    /// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
+    /// the specified value (or combines it with `custom_flags` and `attributes`
+    /// to set the `dwFlagsAndAttributes` for `CreateFile`).
+    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
 }
 
 #[unstable(feature = "open_options_ext",
            reason = "may require more thought/methods",
            issue = "27720")]
 impl OpenOptionsExt for OpenOptions {
-    fn desired_access(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().desired_access(access); self
+    fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
+        self.as_inner_mut().access_mode(access); self
     }
-    fn creation_disposition(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().creation_disposition(access); self
+
+    fn share_mode(&mut self, share: u32) -> &mut OpenOptions {
+        self.as_inner_mut().share_mode(share); self
     }
-    fn flags_and_attributes(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().flags_and_attributes(access); self
+
+    fn custom_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
     }
-    fn share_mode(&mut self, access: u32) -> &mut OpenOptions {
-        self.as_inner_mut().share_mode(access); self
+
+    fn attributes(&mut self, attributes: u32) -> &mut OpenOptions {
+        self.as_inner_mut().attributes(attributes); self
+    }
+
+    fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions {
+        self.as_inner_mut().security_qos_flags(flags); self
     }
 }
 
index 9db7ab534590ab23eb55f3e5826d9cdb03d385b1..60e3f7c22bd58c0484be6c0ba684e1e6fb714f0b 100644 (file)
@@ -54,18 +54,22 @@ pub struct DirEntry {
     data: c::WIN32_FIND_DATAW,
 }
 
-#[derive(Clone, Default)]
+#[derive(Clone)]
 pub struct OpenOptions {
-    create: bool,
-    append: bool,
+    // generic
     read: bool,
     write: bool,
+    append: bool,
     truncate: bool,
-    desired_access: Option<c::DWORD>,
-    share_mode: Option<c::DWORD>,
-    creation_disposition: Option<c::DWORD>,
-    flags_and_attributes: Option<c::DWORD>,
-    security_attributes: usize, // *mut T doesn't have a Default impl
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: u32,
+    access_mode: Option<c::DWORD>,
+    attributes: c::DWORD,
+    share_mode: c::DWORD,
+    security_qos_flags: c::DWORD,
+    security_attributes: usize, // FIXME: should be a reference
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
@@ -151,68 +155,86 @@ pub fn metadata(&self) -> io::Result<FileAttr> {
 }
 
 impl OpenOptions {
-    pub fn new() -> OpenOptions { Default::default() }
+    pub fn new() -> OpenOptions {
+        OpenOptions {
+            // generic
+            read: false,
+            write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
+            access_mode: None,
+            share_mode: c::FILE_SHARE_READ | c::FILE_SHARE_WRITE | c::FILE_SHARE_DELETE,
+            attributes: 0,
+            security_qos_flags: 0,
+            security_attributes: 0,
+        }
+    }
+
     pub fn read(&mut self, read: bool) { self.read = read; }
     pub fn write(&mut self, write: bool) { self.write = write; }
     pub fn append(&mut self, append: bool) { self.append = append; }
-    pub fn create(&mut self, create: bool) { self.create = create; }
     pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
-    pub fn creation_disposition(&mut self, val: u32) {
-        self.creation_disposition = Some(val);
-    }
-    pub fn flags_and_attributes(&mut self, val: u32) {
-        self.flags_and_attributes = Some(val);
-    }
-    pub fn desired_access(&mut self, val: u32) {
-        self.desired_access = Some(val);
-    }
-    pub fn share_mode(&mut self, val: u32) {
-        self.share_mode = Some(val);
-    }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+
+    pub fn custom_flags(&mut self, flags: u32) { self.custom_flags = flags; }
+    pub fn access_mode(&mut self, access_mode: u32) { self.access_mode = Some(access_mode); }
+    pub fn share_mode(&mut self, share_mode: u32) { self.share_mode = share_mode; }
+    pub fn attributes(&mut self, attrs: u32) { self.attributes = attrs; }
+    pub fn security_qos_flags(&mut self, flags: u32) { self.security_qos_flags = flags; }
     pub fn security_attributes(&mut self, attrs: c::LPSECURITY_ATTRIBUTES) {
         self.security_attributes = attrs as usize;
     }
 
-    fn get_desired_access(&self) -> c::DWORD {
-        self.desired_access.unwrap_or({
-            let mut base = if self.read {c::FILE_GENERIC_READ} else {0} |
-                           if self.write {c::FILE_GENERIC_WRITE} else {0};
-            if self.append {
-                base &= !c::FILE_WRITE_DATA;
-                base |= c::FILE_APPEND_DATA;
-            }
-            base
-        })
+    fn get_access_mode(&self) -> io::Result<c::DWORD> {
+        const ERROR_INVALID_PARAMETER: i32 = 87;
+
+        match (self.read, self.write, self.append, self.access_mode) {
+            (_, _, _, Some(mode)) => Ok(mode),
+            (true,  false, false, None) => Ok(c::GENERIC_READ),
+            (false, true,  false, None) => Ok(c::GENERIC_WRITE),
+            (true,  true,  false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE),
+            (false, _,     true,  None) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA),
+            (true,  _,     true,  None) => Ok(c::GENERIC_READ |
+                                              (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)),
+            (false, false, false, None) => Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER)),
+        }
     }
 
-    fn get_share_mode(&self) -> c::DWORD {
-        // libuv has a good comment about this, but the basic idea is that
-        // we try to emulate unix semantics by enabling all sharing by
-        // allowing things such as deleting a file while it's still open.
-        self.share_mode.unwrap_or(c::FILE_SHARE_READ |
-                                  c::FILE_SHARE_WRITE |
-                                  c::FILE_SHARE_DELETE)
-    }
-
-    fn get_creation_disposition(&self) -> c::DWORD {
-        self.creation_disposition.unwrap_or({
-            match (self.create, self.truncate) {
-                (true, true) => c::CREATE_ALWAYS,
-                (true, false) => c::OPEN_ALWAYS,
-                (false, false) => c::OPEN_EXISTING,
-                (false, true) => {
-                    if self.write && !self.append {
-                        c::CREATE_ALWAYS
-                    } else {
-                        c::TRUNCATE_EXISTING
-                    }
-                }
-            }
-        })
+    fn get_creation_mode(&self) -> io::Result<c::DWORD> {
+        const ERROR_INVALID_PARAMETER: i32 = 87;
+
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(ERROR_INVALID_PARAMETER));
+                },
+        }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => c::OPEN_EXISTING,
+                (true,  false, false) => c::OPEN_ALWAYS,
+                (false, true,  false) => c::TRUNCATE_EXISTING,
+                (true,  true,  false) => c::CREATE_ALWAYS,
+                (_,      _,    true)  => c::CREATE_NEW,
+           })
     }
 
     fn get_flags_and_attributes(&self) -> c::DWORD {
-        self.flags_and_attributes.unwrap_or(c::FILE_ATTRIBUTE_NORMAL)
+        self.custom_flags |
+        self.attributes |
+        self.security_qos_flags |
+        if self.security_qos_flags != 0 { c::SECURITY_SQOS_PRESENT } else { 0 } |
+        if self.create_new { c::FILE_FLAG_OPEN_REPARSE_POINT } else { 0 }
     }
 }
 
@@ -221,8 +243,8 @@ fn open_reparse_point(path: &Path, write: bool) -> io::Result<File> {
         let mut opts = OpenOptions::new();
         opts.read(!write);
         opts.write(write);
-        opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT |
-                                  c::FILE_FLAG_BACKUP_SEMANTICS);
+        opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT |
+                          c::FILE_FLAG_BACKUP_SEMANTICS);
         File::open(path, &opts)
     }
 
@@ -230,10 +252,10 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
         let path = try!(to_u16s(path));
         let handle = unsafe {
             c::CreateFileW(path.as_ptr(),
-                           opts.get_desired_access(),
-                           opts.get_share_mode(),
+                           try!(opts.get_access_mode()),
+                           opts.share_mode,
                            opts.security_attributes as *mut _,
-                           opts.get_creation_disposition(),
+                           try!(opts.get_creation_mode()),
                            opts.get_flags_and_attributes(),
                            ptr::null_mut())
         };
@@ -533,7 +555,10 @@ pub fn stat(p: &Path) -> io::Result<FileAttr> {
     // metadata information is.
     if attr.is_reparse_point() {
         let mut opts = OpenOptions::new();
-        opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
+        // No read or write permissions are necessary
+        opts.access_mode(0);
+        // This flag is so we can open directories too
+        opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
         let file = try!(File::open(p, &opts));
         file.file_attr()
     } else {
@@ -577,9 +602,10 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
 
 pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     let mut opts = OpenOptions::new();
-    opts.read(true);
+    // No read or write permissions are necessary
+    opts.access_mode(0);
     // This flag is so we can open directories too
-    opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
+    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
     let f = try!(File::open(p, &opts));
     get_path(&f)
 }
index 19236f2cd98a80302e463ffd5d9112ac111f42c4..8d6c0df981f23d09eaa9f4c56b9800c3656fe70a 100644 (file)
@@ -164,16 +164,31 @@ impl Eq for Span {}
 
 impl Encodable for Span {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        try!(s.emit_u32(self.lo.0));
-        s.emit_u32(self.hi.0)
+        s.emit_struct("Span", 2, |s| {
+            try!(s.emit_struct_field("lo", 0, |s| {
+                self.lo.encode(s)
+            }));
+
+            s.emit_struct_field("hi", 1, |s| {
+                self.hi.encode(s)
+            })
+        })
     }
 }
 
 impl Decodable for Span {
     fn decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
-        let lo = BytePos(try! { d.read_u32() });
-        let hi = BytePos(try! { d.read_u32() });
-        Ok(mk_sp(lo, hi))
+        d.read_struct("Span", 2, |d| {
+            let lo = try!(d.read_struct_field("lo", 0, |d| {
+                BytePos::decode(d)
+            }));
+
+            let hi = try!(d.read_struct_field("hi", 1, |d| {
+                BytePos::decode(d)
+            }));
+
+            Ok(mk_sp(lo, hi))
+        })
     }
 }
 
diff --git a/src/test/auxiliary/issue-30535.rs b/src/test/auxiliary/issue-30535.rs
new file mode 100644 (file)
index 0000000..8d44e8d
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type="lib"]
+
+pub enum Foo {
+    FooV { data: () }
+}
diff --git a/src/test/auxiliary/issue_30123_aux.rs b/src/test/auxiliary/issue_30123_aux.rs
new file mode 100644 (file)
index 0000000..f60311a
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+use std::marker::PhantomData;
+
+pub struct Directed;
+pub struct Undirected;
+
+pub struct Graph<N, E, Ty = Directed> {
+    nodes: Vec<PhantomData<N>>,
+    edges: Vec<PhantomData<E>>,
+    ty: PhantomData<Ty>,
+}
+
+
+impl<N, E> Graph<N, E, Directed> {
+    pub fn new() -> Self {
+        Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData}
+    }
+}
+
+impl<N, E> Graph<N, E, Undirected> {
+    pub fn new_undirected() -> Self {
+        Graph{nodes: Vec::new(), edges: Vec::new(), ty: PhantomData}
+    }
+}
diff --git a/src/test/auxiliary/variant-namespacing.rs b/src/test/auxiliary/variant-namespacing.rs
new file mode 100644 (file)
index 0000000..d7fd296
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub enum XE {
+    XStruct { a: u8 },
+    XTuple(u8),
+    XUnit,
+}
index b862fc1a1f461b00f3f670173fe10e8882fec305..5f8948ac5f1e9e41efa0e2eb9fb2c9bc940d699f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-msvc everything is the system allocator on msvc
+// ignore-windows everything is the system allocator on windows
 // ignore-musl no dylibs on musl yet
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
index e75cb2a75cf580036e5492dbbb6a21460fed593b..b29797f3295262b8daa1716169f730b5968913d9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-msvc everything is the system allocator on msvc
+// ignore-windows everything is the system allocator on windows
 // ignore-musl no dylibs on musl right now
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
diff --git a/src/test/compile-fail/dep-graph-assoc-type-trans.rs b/src/test/compile-fail/dep-graph-assoc-type-trans.rs
new file mode 100644 (file)
index 0000000..d1ecff5
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that when a trait impl changes, fns whose body uses that trait
+// must also be recompiled.
+
+// compile-flags: -Z incr-comp
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+fn main() { }
+
+pub trait Foo: Sized {
+    type T;
+    fn method(self) { }
+}
+
+mod x {
+    use Foo;
+
+    #[rustc_if_this_changed]
+    impl Foo for char { type T = char; }
+
+    impl Foo for u32 { type T = u32; }
+}
+
+mod y {
+    use Foo;
+
+    #[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR OK
+    #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK
+    pub fn use_char_assoc() {
+        // Careful here: in the representation, <char as Foo>::T gets
+        // normalized away, so at a certain point we had no edge to
+        // trans.  (But now trans just depends on typeck.)
+        let x: <char as Foo>::T = 'a';
+    }
+
+    pub fn take_foo<T:Foo>(t: T) { }
+}
index 83e924fe06d7dfd223f57744b53fe32a95a9f0a5..b38fdad9809ed1cb4b57f80a9d6d88e8d163216b 100644 (file)
@@ -40,9 +40,8 @@ pub fn with_char() {
         char::method('a');
     }
 
-    // FIXME(#30741) tcx fulfillment cache not tracked
-    #[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR no path
-    #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR OK
+    #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK
     pub fn take_foo_with_char() {
         take_foo::<char>('a');
     }
@@ -53,9 +52,8 @@ pub fn with_u32() {
         u32::method(22);
     }
 
-    // FIXME(#30741) tcx fulfillment cache not tracked
-    #[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR no path
-    #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR no path
+    #[rustc_then_this_would_need(TypeckItemBody)] //~ ERROR OK
+    #[rustc_then_this_would_need(TransCrateItem)] //~ ERROR OK
     pub fn take_foo_with_u32() {
         take_foo::<u32>(22);
     }
index 6ae0dad0e7bfbd485a4370d0b2fd06f86c770423..61e4a1ea3975ccd9d2f966421bd4ef2a92ad871d 100644 (file)
@@ -29,9 +29,8 @@ fn main() {
     let e3 = E::Empty3; //~ ERROR `E::Empty3` is the name of a struct or struct variant
     let e3 = E::Empty3(); //~ ERROR `E::Empty3` is the name of a struct or struct variant
 
-    // FIXME: non-local struct kind should be known early (e.g. kept in `DefStruct`)
-    // let xe1 = XEmpty1; // ERROR `XEmpty1` is the name of a struct or struct variant
-    let xe1 = XEmpty1(); //~ ERROR expected function, found `empty_struct::XEmpty1`
+    let xe1 = XEmpty1; //~ ERROR `XEmpty1` is the name of a struct or struct variant
+    let xe1 = XEmpty1(); //~ ERROR `XEmpty1` is the name of a struct or struct variant
     let xe3 = XE::Empty3; //~ ERROR no associated item named `Empty3` found for type
     let xe3 = XE::Empty3(); //~ ERROR no associated item named `Empty3` found for type
 }
index 27c97a3a5509601919d1e96958428120d2702f6d..4dd256c68bf759697ebc553273f7a888770a4f8a 100644 (file)
@@ -39,6 +39,6 @@ fn main() {
         XEmpty1 => () // Not an error, `XEmpty1` is interpreted as a new binding
     }
     match xe3 {
-        XE::XEmpty3 => () //~ ERROR no associated item named `XEmpty3` found for type
+        XE::XEmpty3 => () //~ ERROR `XE::XEmpty3` does not name a tuple variant or a tuple struct
     }
 }
index 3436e2a2cd752c298ea13b6971583909d6967784..ac6fbc7e06d5b68d60ff9fe3ad9c2d577904db17 100644 (file)
@@ -34,6 +34,6 @@ fn main() {
         Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
     }
     match xe1 {
-        XEmpty1(..) => () //~ ERROR `XEmpty1` does not name a tuple variant or a tuple struct
+        XEmpty1(..) => () //~ ERROR unresolved enum variant, struct or const `XEmpty1`
     }
 }
index ca51a1cfc2186f64214843b591385cb82fb8ab92..c973049184fc4424cdc966c25df6da3fde5ac6e3 100644 (file)
@@ -36,6 +36,6 @@ fn main() {
         E::Empty3(..) => () //~ ERROR `E::Empty3` does not name a tuple variant or a tuple struct
     }
     match xe3 {
-        XE::XEmpty3(..) => () //~ ERROR no associated item named `XEmpty3` found for type
+        XE::XEmpty3(..) => () //~ ERROR `XE::XEmpty3` does not name a tuple variant or a tuple
     }
 }
index f6c62bb855720c8956f3b855a7e719cf2d4556e9..708eea39a9571b73dd58d24b5ebc4cd13cef3501 100644 (file)
@@ -14,7 +14,7 @@ mod a {
     impl S { }
 }
 
-fn foo(_: a::S) { //~ ERROR: type `S` is private
+fn foo(_: a::S) { //~ ERROR: struct `S` is private
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-30123.rs b/src/test/compile-fail/issue-30123.rs
new file mode 100644 (file)
index 0000000..cfd3cd3
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+// aux-build:issue_30123_aux.rs
+
+extern crate issue_30123_aux;
+use issue_30123_aux::*;
+
+fn main() {
+    let ug = Graph::<i32, i32>::new_undirected();
+    //~^ ERR no associated item named `new_undirected` found for type
+}
diff --git a/src/test/compile-fail/issue-30535.rs b/src/test/compile-fail/issue-30535.rs
new file mode 100644 (file)
index 0000000..93f3086
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-30535.rs
+
+extern crate issue_30535 as foo;
+
+fn bar(
+    _: foo::Foo::FooV //~ ERROR value `foo::Foo::FooV` used as a type
+) {}
+
+fn main() {}
index cd320ba148aba8fe02323db6fa3fcbae88ac67f3..451b30629b625f5795bfd3733df37bdc505db090 100644 (file)
@@ -18,5 +18,4 @@ fn forever() -> ! {
 }
 
 fn main() {
-  if 1 == 2 { forever(); }
 }
diff --git a/src/test/compile-fail/loop-proper-liveness.rs b/src/test/compile-fail/loop-proper-liveness.rs
new file mode 100644 (file)
index 0000000..e411313
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+fn test1() {
+    // In this test the outer 'a loop may terminate without `x` getting initialised. Although the
+    // `x = loop { ... }` statement is reached, the value itself ends up never being computed and
+    // thus leaving `x` uninit.
+    let x: i32;
+    'a: loop {
+        x = loop { break 'a };
+    }
+    println!("{:?}", x); //~ ERROR use of possibly uninitialized variable
+}
+
+// test2 and test3 should not fail.
+fn test2() {
+    // In this test the `'a` loop will never terminate thus making the use of `x` unreachable.
+    let x: i32;
+    'a: loop {
+        x = loop { continue 'a };
+    }
+    println!("{:?}", x);
+}
+
+fn test3() {
+    let x: i32;
+    // Similarly, the use of variable `x` is unreachable.
+    'a: loop {
+        x = loop { return };
+    }
+    println!("{:?}", x);
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/loop-properly-diverging-2.rs b/src/test/compile-fail/loop-properly-diverging-2.rs
new file mode 100644 (file)
index 0000000..c22091c
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+fn forever2() -> i32 {
+  let x: i32 = loop { break }; //~ ERROR mismatched types
+  x
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/loop-properly-diverging.rs b/src/test/compile-fail/loop-properly-diverging.rs
new file mode 100644 (file)
index 0000000..01dfbcc
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn forever2() -> ! { //~ ERROR computation may converge in a function marked as diverging
+  loop { break }
+}
+
+fn main() {}
index 7c8b91741ea5bdec4735fe43d464d9dfe2e6f943..593068c2aea9dcdc2e0b95e88d66fdc8b0036a74 100644 (file)
@@ -164,7 +164,7 @@ pub mod mytest {
     // Even though the inner `A` struct is a publicly exported item (usable from
     // external crates through `foo::foo`, it should not be accessible through
     // its definition path (which has the private `i` module).
-    use self::foo::i::A; //~ ERROR: type `A` is inaccessible
+    use self::foo::i::A; //~ ERROR: struct `A` is inaccessible
                          //~^ NOTE: module `i` is private
 
     pub mod foo {
index aae09cc0eae5cb985376d02a0697dced7c56e5a4..2ff48b73e294c415bcb02f51f05046d8dbb02f95 100644 (file)
@@ -28,7 +28,7 @@ pub struct B {
 }
 
 fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) {
-    //~^ ERROR: type `A` is private
+    //~^ ERROR: struct `A` is private
     //~^^ ERROR: struct `A` is private
 
     a.a;
diff --git a/src/test/compile-fail/variant-namespacing.rs b/src/test/compile-fail/variant-namespacing.rs
new file mode 100644 (file)
index 0000000..75869d7
--- /dev/null
@@ -0,0 +1,49 @@
+// 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.
+
+// aux-build:variant-namespacing.rs
+
+extern crate variant_namespacing;
+pub use variant_namespacing::XE::*;
+//~^ ERROR import `XStruct` conflicts with type in this module
+//~| ERROR import `XStruct` conflicts with value in this module
+//~| ERROR import `XTuple` conflicts with type in this module
+//~| ERROR import `XTuple` conflicts with value in this module
+//~| ERROR import `XUnit` conflicts with type in this module
+//~| ERROR import `XUnit` conflicts with value in this module
+pub use E::*;
+//~^ ERROR import `Struct` conflicts with type in this module
+//~| ERROR import `Struct` conflicts with value in this module
+//~| ERROR import `Tuple` conflicts with type in this module
+//~| ERROR import `Tuple` conflicts with value in this module
+//~| ERROR import `Unit` conflicts with type in this module
+//~| ERROR import `Unit` conflicts with value in this module
+
+enum E {
+    Struct { a: u8 },
+    Tuple(u8),
+    Unit,
+}
+
+type Struct = u8;
+type Tuple = u8;
+type Unit = u8;
+type XStruct = u8;
+type XTuple = u8;
+type XUnit = u8;
+
+const Struct: u8 = 0;
+const Tuple: u8 = 0;
+const Unit: u8 = 0;
+const XStruct: u8 = 0;
+const XTuple: u8 = 0;
+const XUnit: u8 = 0;
+
+fn main() {}
index cccb7e500213f4871ce96b61639ae27d4fbfbe75..214a2a371baaf63d882403b03dc8b588e511d5e4 100644 (file)
@@ -16,6 +16,7 @@
 extern crate xcrate_unit_struct;
 
 fn main() {
-    let _ = xcrate_unit_struct::StructWithFields; //~ ERROR: unresolved name
+    let _ = xcrate_unit_struct::StructWithFields;
+    //~^ ERROR: `xcrate_unit_struct::StructWithFields` is the name of a struct or struct variant
     let _ = xcrate_unit_struct::Struct;
 }
index 7b2130cd4ed96bdc2dc402c67b677da4907bdfe5..98e112a374423910cf249c8170e6a6e123a7d5c6 100644 (file)
@@ -7,7 +7,7 @@ all: $(TMPDIR)/$(call BIN,bar)
 
 ifdef IS_MSVC
 $(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
-       $(CC) bar.c $(TMPDIR)/foo.lib $(call OUT_EXE,bar)
+       $(CC) bar.c $(TMPDIR)/foo.dll.lib $(call OUT_EXE,bar)
 else
 $(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
        $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR)
index 3d44b3c256efcaa4da06c40f260b2f88fd0e88ac..47264e82165b4a96b80bba72fc96c0ac0214212f 100644 (file)
@@ -4,11 +4,10 @@
 ifneq ($(shell uname),FreeBSD)
 all:
        $(RUSTC) foo.rs
-       cp $(TMPDIR)/libfoo.a $(call NATIVE_STATICLIB,foo2)
-       $(CC) bar.c $(call NATIVE_STATICLIB,foo2) $(call OUT_EXE,bar) \
+       $(CC) bar.c $(call STATICLIB,foo) $(call OUT_EXE,bar) \
                $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
-       rm $(call STATICLIB,foo*)
+       rm $(call STATICLIB,foo)
        $(call RUN,bar)
 
 else
index 72c161abe9113f10665f6ea3449b843b4adecf55..0f61f5de938bc37d6bf5fbfae13b58e533ad5c1c 100644 (file)
@@ -5,7 +5,7 @@ CC := $(CC:-g=)
 
 all:
        $(RUSTC) foo.rs -C lto
-       $(CC) bar.c $(TMPDIR)/libfoo.a \
+       $(CC) bar.c $(call STATICLIB,foo) \
                $(call OUT_EXE,bar) \
                $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
index 6cfa7043a2e382b53adf69da58d03782dbe1ab19..c2715027bc1f904470285ddc0ce97fde9df967a2 100644 (file)
@@ -4,8 +4,8 @@ all:
        $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib
        $(call REMOVE_RLIBS,bar)
        $(call REMOVE_DYLIBS,bar)
-       rm $(TMPDIR)/libbar.a
-       rm -f $(TMPDIR)/bar.{exp,lib,pdb}
+       rm $(call STATICLIB,bar)
+       rm -f $(TMPDIR)/bar.{dll.exp,dll.lib,pdb}
        # Check that $(TMPDIR) is empty.
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
@@ -78,7 +78,7 @@ all:
        rm $(TMPDIR)/$(call BIN,foo)
        $(RUSTC) foo.rs --crate-type=dylib --emit=link=$(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
-       rm -f $(TMPDIR)/foo.{exp,lib,pdb}
+       rm -f $(TMPDIR)/foo.{dll.exp,dll.lib,pdb}
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
@@ -133,7 +133,7 @@ all:
        rm $(TMPDIR)/bar.ll
        rm $(TMPDIR)/bar.s
        rm $(TMPDIR)/bar.o
-       rm $(TMPDIR)/libbar.a
+       rm $(call STATICLIB,bar)
        mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc
        # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later
        # comparison.
index 8bd05dc201fcfa1bf0b97ad3aef3aac29d029536..6409aa66ae061879f2055606e83b573b8dc75bce 100644 (file)
@@ -2,7 +2,7 @@
 
 TO_LINK := $(call DYLIB,bar)
 ifdef IS_MSVC
-LINK_ARG = $(TO_LINK:dll=lib)
+LINK_ARG = $(TO_LINK:dll=dll.lib)
 else
 LINK_ARG = $(TO_LINK)
 endif
index 52ad8b1709338c48297bbdc093eb8e8427caddda..aed7e5a8c13a6eab6ec4be3dedefb77b761755e6 100644 (file)
@@ -10,9 +10,9 @@
 
 #![feature(alloc_jemalloc, alloc_system)]
 
-#[cfg(not(any(target_env = "msvc", target_os = "bitrig", target_os = "openbsd")))]
+#[cfg(not(any(windows, target_os = "bitrig", target_os = "openbsd")))]
 extern crate alloc_jemalloc;
-#[cfg(any(target_env = "msvc", target_os = "bitrig", target_os = "openbsd"))]
+#[cfg(any(windows, target_os = "bitrig", target_os = "openbsd"))]
 extern crate alloc_system;
 
 fn main() {
index c8a9aeb706e8ce7951a8196d743bed79a0527297..3744aafdc5b2845ff999390444f26d7ffb5a7a5f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // no-prefer-dynamic
-// ignore-msvc no jemalloc on msvc
+// ignore-windows no jemalloc on windows
 // ignore-bitrig no jemalloc on bitrig
 // ignore-openbsd no jemalloc on openbsd
 
index 62e90d7a6e22b0f105b51812c5a42e59aad350b4..605ca6b65e2cff94f7077cd8ef9e3609d77ecea2 100644 (file)
@@ -8,8 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// aux-build:empty-struct.rs
+
 #![feature(associated_consts)]
 
+extern crate empty_struct;
+use empty_struct::XEmpty2 as XFoo;
+
 struct Foo;
 
 enum Bar {
@@ -30,6 +35,10 @@ impl HasBar for Foo {
     const THEBAR: Bar = Bar::Var1;
 }
 
+impl HasBar for XFoo {
+    const THEBAR: Bar = Bar::Var1;
+}
+
 fn main() {
     // Inherent impl
     assert!(match Bar::Var2 {
@@ -53,4 +62,16 @@ fn main() {
         <Foo as HasBar>::THEBAR => true,
         _ => false,
     });
+    assert!(match Bar::Var1 {
+        XFoo::THEBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var1 {
+        <XFoo>::THEBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var1 {
+        <XFoo as HasBar>::THEBAR => true,
+        _ => false,
+    });
 }
index b4ce1b97a4c00f09dae359ee38d8abbccc125d24..8d6f4d4c30a286dba66eab4ecc09db217c57fb26 100644 (file)
@@ -95,8 +95,7 @@ fn xcrate() {
     let e2: XEmpty2 = XEmpty2 {};
     let e2: XEmpty2 = XEmpty2;
     let e3: XE = XE::XEmpty3 {};
-    // FIXME: Commented out tests are waiting for PR 30882 (fixes for variant namespaces)
-    // let e4: XE = XE::XEmpty4 {};
+    let e4: XE = XE::XEmpty4 {};
     let e4: XE = XE::XEmpty4;
 
     match e1 {
@@ -109,10 +108,10 @@ fn xcrate() {
         XE::XEmpty3 {} => {}
         _ => {}
     }
-    // match e4 {
-    //     XE::XEmpty4 {} => {}
-    //     _ => {}
-    // }
+    match e4 {
+        XE::XEmpty4 {} => {}
+        _ => {}
+    }
 
     match e1 {
         XEmpty1 { .. } => {}
@@ -124,18 +123,18 @@ fn xcrate() {
         XE::XEmpty3 { .. } => {}
         _ => {}
     }
-    // match e4 {
-    //     XE::XEmpty4 { .. } => {}
-    //     _ => {}
-    // }
+    match e4 {
+        XE::XEmpty4 { .. } => {}
+        _ => {}
+    }
 
     match e2 {
         XEmpty2 => {}
     }
-    // match e4 {
-    //     XE::XEmpty4 => {}
-    //     _ => {}
-    // }
+    match e4 {
+        XE::XEmpty4 => {}
+        _ => {}
+    }
 
     let e11: XEmpty1 = XEmpty1 { ..e1 };
     let e22: XEmpty2 = XEmpty2 { ..e2 };
diff --git a/src/test/run-pass/mir_temp_promotions.rs b/src/test/run-pass/mir_temp_promotions.rs
new file mode 100644 (file)
index 0000000..de83c1f
--- /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(rustc_attrs)]
+
+#[rustc_mir]
+fn test1(f: f32) -> bool {
+    // test that we properly promote temporaries to allocas when a temporary is assigned to
+    // multiple times (assignment is still happening once ∀ possible dataflows).
+    !(f.is_nan() || f.is_infinite())
+}
+
+fn main() {
+    assert_eq!(test1(0.0), true);
+}
diff --git a/src/test/run-pass/zero-sized-binary-heap-push.rs b/src/test/run-pass/zero-sized-binary-heap-push.rs
new file mode 100644 (file)
index 0000000..0866a76
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::BinaryHeap;
+use std::iter::Iterator;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = BinaryHeap::with_capacity(len);
+        assert_eq!(tester.len(), 0);
+        assert!(tester.capacity() >= len);
+        for bit in 0..len {
+            tester.push(());
+        }
+        assert_eq!(tester.len(), len);
+        assert_eq!(tester.iter().count(), len);
+        tester.clear();
+    }
+}
diff --git a/src/test/run-pass/zero-sized-btreemap-insert.rs b/src/test/run-pass/zero-sized-btreemap-insert.rs
new file mode 100644 (file)
index 0000000..aff124c
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cmp::{Ord, Ordering, PartialOrd};
+use std::collections::BTreeMap;
+use std::iter::Iterator;
+
+#[derive(Eq, Hash, Debug, Ord, PartialEq, PartialOrd)]
+struct Zst;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = BTreeMap::new();
+        assert_eq!(tester.len(), 0);
+        for bit in 0..len {
+            tester.insert(Zst, ());
+        }
+        assert_eq!(tester.len(), if len == 0 { 0 } else { 1 });
+        assert_eq!(tester.iter().count(), if len == 0 { 0 } else { 1 });
+        assert_eq!(tester.get(&Zst).is_some(), len > 0);
+        tester.clear();
+    }
+}
diff --git a/src/test/run-pass/zero-sized-linkedlist-push.rs b/src/test/run-pass/zero-sized-linkedlist-push.rs
new file mode 100644 (file)
index 0000000..9c42485
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::LinkedList;
+use std::iter::Iterator;
+
+fn main() {
+    const N: usize = 8;
+
+    // Test that for all possible sequences of push_front / push_back,
+    // we end up with a LinkedList of the correct size
+
+    for len in 0..N {
+        let mut tester = LinkedList::new();
+        assert_eq!(tester.len(), 0);
+        assert_eq!(tester.front(), None);
+        for case in 0..(1 << len) {
+            assert_eq!(tester.len(), 0);
+            for bit in 0..len {
+                if case & (1 << bit) != 0 {
+                    tester.push_front(());
+                } else {
+                    tester.push_back(());
+                }
+            }
+            assert_eq!(tester.len(), len);
+            assert_eq!(tester.iter().count(), len);
+            tester.clear();
+        }
+    }
+}
diff --git a/src/test/run-pass/zero-sized-vec-push.rs b/src/test/run-pass/zero-sized-vec-push.rs
new file mode 100644 (file)
index 0000000..e472e93
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::iter::Iterator;
+use std::vec::Vec;
+
+fn main() {
+    const N: usize = 8;
+
+    for len in 0..N {
+        let mut tester = Vec::with_capacity(len);
+        assert_eq!(tester.len(), 0);
+        assert!(tester.capacity() >= len);
+        for bit in 0..len {
+            tester.push(());
+        }
+        assert_eq!(tester.len(), len);
+        assert_eq!(tester.iter().count(), len);
+        tester.clear();
+    }
+}