]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #42919 - zackmdavis:once_again_we_heard_you_the_first_time, r=eddyb
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>
Thu, 29 Jun 2017 08:40:07 +0000 (08:40 +0000)
committerGitHub <noreply@github.com>
Thu, 29 Jun 2017 08:40:07 +0000 (08:40 +0000)
make lint on-by-default/implied-by messages appear only once

From review discussion on #38103 (https://github.com/rust-lang/rust/pull/38103#discussion_r94845060).

![we_heard](https://user-images.githubusercontent.com/1076988/27564103-6284b78e-5a8a-11e7-9d35-f7f297ca9573.png)

r? @nikomatsakis

210 files changed:
src/Cargo.lock
src/liballoc/allocator.rs
src/liballoc/btree/map.rs
src/liballoc/btree/set.rs
src/liballoc/fmt.rs
src/liballoc/lib.rs
src/liballoc/range.rs
src/liballoc/string.rs
src/liballoc/vec.rs
src/liballoc/vec_deque.rs
src/libcollections/lib.rs
src/libcore/cmp.rs
src/libcore/fmt/mod.rs
src/libcore/mem.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/ops/mod.rs
src/libcore/ops/range.rs
src/libcore/ptr.rs
src/libcore/slice/rotate.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/mod.rs
src/librustc/lint/context.rs
src/librustc/middle/effect.rs
src/librustc/middle/intrinsicck.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/context.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
src/librustc_const_eval/pattern.rs
src/librustc_data_structures/accumulate_vec.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_errors/emitter.rs
src/librustc_lint/builtin.rs
src/librustc_lint/types.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/schema.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/erase_regions.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_passes/ast_validation.rs
src/librustc_privacy/lib.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/collector.rs
src/librustc_trans/common.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans/trans_item.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/mod.rs
src/librustc_typeck/variance/solve.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/markdown.rs
src/librustdoc/test.rs
src/libstd/collections/mod.rs
src/libstd/env.rs
src/libstd/f32.rs
src/libstd/f64.rs
src/libstd/ffi/os_str.rs
src/libstd/process.rs
src/libstd/sys/redox/net/tcp.rs
src/libstd/sys/redox/pipe.rs
src/libstd/thread/mod.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax/test.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/libtest/lib.rs
src/test/compile-fail/E0604.rs [new file with mode: 0644]
src/test/compile-fail/E0605.rs [new file with mode: 0644]
src/test/compile-fail/E0606.rs [new file with mode: 0644]
src/test/compile-fail/E0607.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-path-2.rs
src/test/compile-fail/block-must-not-have-result-do.rs [deleted file]
src/test/compile-fail/block-must-not-have-result-res.rs [deleted file]
src/test/compile-fail/block-must-not-have-result-while.rs [deleted file]
src/test/compile-fail/cast-from-nil.rs
src/test/compile-fail/cast-to-bare-fn.rs
src/test/compile-fail/cast-to-nil.rs
src/test/compile-fail/closure-no-fn-3.rs
src/test/compile-fail/coerce-to-bang-cast.rs
src/test/compile-fail/consider-removing-last-semi.rs [deleted file]
src/test/compile-fail/fat-ptr-cast.rs
src/test/compile-fail/feature-gate-allow_fail.rs [new file with mode: 0644]
src/test/compile-fail/for-loop-has-unit-body.rs [deleted file]
src/test/compile-fail/invalid-intrinsic.rs
src/test/compile-fail/issue-10991.rs
src/test/compile-fail/issue-11714.rs [deleted file]
src/test/compile-fail/issue-13428.rs [deleted file]
src/test/compile-fail/issue-13624.rs [deleted file]
src/test/compile-fail/issue-20862.rs [deleted file]
src/test/compile-fail/issue-22289.rs
src/test/compile-fail/issue-22312.rs
src/test/compile-fail/issue-22645.rs [deleted file]
src/test/compile-fail/issue-23046.rs
src/test/compile-fail/issue-2995.rs
src/test/compile-fail/issue-3563.rs [deleted file]
src/test/compile-fail/issue-38954.rs
src/test/compile-fail/issue-42312.rs [new file with mode: 0644]
src/test/compile-fail/issue-5500.rs [deleted file]
src/test/compile-fail/nonscalar-cast.rs
src/test/compile-fail/on-unimplemented/multiple-impls.rs
src/test/compile-fail/on-unimplemented/on-impl.rs
src/test/compile-fail/patkind-litrange-no-expr.rs [new file with mode: 0644]
src/test/compile-fail/tag-variant-cast-non-nullary.rs
src/test/compile-fail/uninhabited-enum-cast.rs
src/test/compile-fail/variance-region-bounds.rs [deleted file]
src/test/compile-fail/variance-trait-bounds.rs
src/test/compile-fail/variance-types-bounds.rs
src/test/run-pass/allocator-alloc-one.rs [new file with mode: 0644]
src/test/run-pass/associated-types-sugar-path.rs
src/test/run-pass/deriving-hash.rs
src/test/run-pass/dynamic-drop.rs
src/test/run-pass/env.rs [new file with mode: 0644]
src/test/run-pass/issue-37725.rs [new file with mode: 0644]
src/test/run-pass/macro-pat-neg-lit.rs [new file with mode: 0644]
src/test/run-pass/process-envs.rs
src/test/run-pass/test-allow-fail-attr.rs [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-do.rs [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-do.stderr [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-res.rs [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-res.stderr [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-while.rs [new file with mode: 0644]
src/test/ui/block-result/block-must-not-have-result-while.stderr [new file with mode: 0644]
src/test/ui/block-result/consider-removing-last-semi.rs [new file with mode: 0644]
src/test/ui/block-result/consider-removing-last-semi.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-11714.rs [new file with mode: 0644]
src/test/ui/block-result/issue-11714.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-13428.rs [new file with mode: 0644]
src/test/ui/block-result/issue-13428.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-13624.rs [new file with mode: 0644]
src/test/ui/block-result/issue-13624.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-20862.rs [new file with mode: 0644]
src/test/ui/block-result/issue-20862.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-22645.rs [new file with mode: 0644]
src/test/ui/block-result/issue-22645.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-3563.rs [new file with mode: 0644]
src/test/ui/block-result/issue-3563.stderr [new file with mode: 0644]
src/test/ui/block-result/issue-5500.rs [new file with mode: 0644]
src/test/ui/block-result/issue-5500.stderr [new file with mode: 0644]
src/test/ui/block-result/unexpected-return-on-unit.rs [new file with mode: 0644]
src/test/ui/block-result/unexpected-return-on-unit.stderr [new file with mode: 0644]
src/test/ui/coercion-missing-tail-expected-type.stderr
src/test/ui/lint/outer-forbid.rs [new file with mode: 0644]
src/test/ui/lint/outer-forbid.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/cast-rfc0401.stderr
src/test/ui/mismatched_types/for-loop-has-unit-body.rs [new file with mode: 0644]
src/test/ui/mismatched_types/for-loop-has-unit-body.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/issue-19109.stderr
src/test/ui/mismatched_types/issue-26480.stderr
src/test/ui/resolve/token-error-correct-3.stderr
src/tools/cargo
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs

index dd6e72a56149e48099804eb7c20ad711bc77ca06..386450f4a65685379154a3f8e8c8a23e08137178 100644 (file)
@@ -129,7 +129,7 @@ dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -157,7 +157,7 @@ dependencies = [
 [[package]]
 name = "cargo"
 version = "0.21.0"
-source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a"
+source = "git+https://github.com/rust-lang/cargo#abf01e1eddb3145c83f71b469ea7bee37141e5e1"
 replace = "cargo 0.21.0"
 
 [[package]]
@@ -170,8 +170,8 @@ dependencies = [
  "cargotest 0.1.0",
  "crates-io 0.10.0",
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -188,7 +188,7 @@ dependencies = [
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -201,8 +201,8 @@ dependencies = [
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -224,7 +224,7 @@ dependencies = [
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -301,12 +301,12 @@ dependencies = [
 name = "crates-io"
 version = "0.10.0"
 dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -316,19 +316,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "curl"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.3.12"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -365,7 +366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "docopt"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -474,7 +475,7 @@ dependencies = [
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -482,10 +483,10 @@ name = "git2-curl"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -582,7 +583,7 @@ dependencies = [
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -609,7 +610,7 @@ version = "0.6.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -798,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num_cpus"
-version = "1.5.1"
+version = "1.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -944,11 +945,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "racer"
-version = "2.0.8"
+version = "2.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1023,17 +1025,17 @@ dependencies = [
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1079,10 +1081,10 @@ dependencies = [
 
 [[package]]
 name = "rls-vfs"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1472,7 +1474,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.1.3"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1486,8 +1488,8 @@ dependencies = [
  "serde_derive 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1588,6 +1590,18 @@ name = "shell-escape"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "socket2"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "stable_deref_trait"
 version = "1.0.0"
@@ -1706,7 +1720,7 @@ dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1729,7 +1743,7 @@ dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1757,7 +1771,7 @@ version = "0.0.0"
 
 [[package]]
 name = "term"
-version = "0.4.5"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1855,7 +1869,7 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1916,7 +1930,7 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1930,7 +1944,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2035,12 +2049,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f"
 "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
-"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac"
+"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7"
+"checksum curl-sys 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd8b8d593de3bbf49252b92f398ef47f0c6c1ebdfd0f9282b9b9348aad8d71c"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e"
 "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
-"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440"
+"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
@@ -2084,7 +2098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
 "checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d"
 "checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
-"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a"
+"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
 "checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41"
 "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
@@ -2099,7 +2113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
 "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd"
+"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
@@ -2109,10 +2123,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e"
 "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
-"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854"
+"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7"
 "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf"
+"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
@@ -2125,6 +2139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
 "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
+"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
@@ -2136,7 +2151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
 "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
-"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
+"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
@@ -2146,7 +2161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f"
-"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a"
+"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
 "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
 "checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
@@ -2155,7 +2170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c"
+"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
index 9bddce29957e1a514b5ad5d8f93ca323fc8a2fcd..bf38629ed38a7a344eb5214842a49c340428fab1 100644 (file)
@@ -873,7 +873,7 @@ fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
     {
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) }
+            unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) }
         } else {
             Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
         }
index a51c70159db4d788c2a5454e161f22fe92627393..5243fb6ae0e061688eaf6f10a91d755b4fde6859 100644 (file)
 use core::hash::{Hash, Hasher};
 use core::iter::{FromIterator, Peekable, FusedIterator};
 use core::marker::PhantomData;
-use core::ops::Index;
+use core::ops::{Index, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::{fmt, intrinsics, mem, ptr};
 
 use borrow::Borrow;
-use Bound::{Excluded, Included, Unbounded};
-use range::RangeArgument;
 
 use super::node::{self, Handle, NodeRef, marker};
 use super::search;
index d32460da9392342e12834e28d1e5684956297b0a..c755d2d8b8538909d37587e1f524b4d95917baef 100644 (file)
 use core::fmt::Debug;
 use core::fmt;
 use core::iter::{Peekable, FromIterator, FusedIterator};
-use core::ops::{BitOr, BitAnd, BitXor, Sub};
+use core::ops::{BitOr, BitAnd, BitXor, Sub, RangeArgument};
 
 use borrow::Borrow;
 use btree_map::{BTreeMap, Keys};
 use super::Recover;
-use range::RangeArgument;
 
 // FIXME(conventions): implement bounded iterators
 
index 1bd95fb82aa4d68874485f79c1613c099cf616c7..4847b21c0b3b5d4c9f9d87653befd5d5b5cca94e 100644 (file)
 
 use string;
 
-/// The format function takes a precompiled format string and a list of
-/// arguments, to return the resulting formatted string.
+/// The `format` function takes an `Arguments` struct and returns the resulting
+/// formatted string.
 ///
-/// # Arguments
-///
-///   * args - a structure of arguments generated via the `format_args!` macro.
+/// The `Arguments` instance can be created with the `format_args!` macro.
 ///
 /// # Examples
 ///
index ca52943ea97e32b57a7279fc5b8fb57e2ba0aeee..6f4e300fd3cc9d814550fb4d38bd4b00f9f0ddc8 100644 (file)
@@ -203,56 +203,7 @@ mod std {
     pub use core::ops;      // RangeFull
 }
 
-/// An endpoint of a range of keys.
-///
-/// # Examples
-///
-/// `Bound`s are range endpoints:
-///
-/// ```
-/// #![feature(collections_range)]
-///
-/// use std::collections::range::RangeArgument;
-/// use std::collections::Bound::*;
-///
-/// assert_eq!((..100).start(), Unbounded);
-/// assert_eq!((1..12).start(), Included(&1));
-/// assert_eq!((1..12).end(), Excluded(&12));
-/// ```
-///
-/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
-/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
-///
-/// ```
-/// use std::collections::BTreeMap;
-/// use std::collections::Bound::{Excluded, Included, Unbounded};
-///
-/// let mut map = BTreeMap::new();
-/// map.insert(3, "a");
-/// map.insert(5, "b");
-/// map.insert(8, "c");
-///
-/// for (key, value) in map.range((Excluded(3), Included(8))) {
-///     println!("{}: {}", key, value);
-/// }
-///
-/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
-/// ```
-///
-/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range
-#[stable(feature = "collections_bound", since = "1.17.0")]
-#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
-pub enum Bound<T> {
-    /// An inclusive bound.
-    #[stable(feature = "collections_bound", since = "1.17.0")]
-    Included(T),
-    /// An exclusive bound.
-    #[stable(feature = "collections_bound", since = "1.17.0")]
-    Excluded(T),
-    /// An infinite endpoint. Indicates that there is no bound in this direction.
-    #[stable(feature = "collections_bound", since = "1.17.0")]
-    Unbounded,
-}
+pub use core::ops::Bound;
 
 /// An intermediate trait for specialization of `Extend`.
 #[doc(hidden)]
index f862da0d61e012ed816811947a14f3fcab5005a5..0a058c47a50b252ed6c16386041b04d9838a78fa 100644 (file)
 #![unstable(feature = "collections_range",
             reason = "waiting for dust to settle on inclusive ranges",
             issue = "30877")]
+#![rustc_deprecated(reason = "moved to core::ops", since = "1.19.0")]
 
 //! Range syntax.
 
-use core::ops::{RangeFull, Range, RangeTo, RangeFrom, RangeInclusive, RangeToInclusive};
-use Bound::{self, Excluded, Included, Unbounded};
-
-/// `RangeArgument` is implemented by Rust's built-in range types, produced
-/// by range syntax like `..`, `a..`, `..b` or `c..d`.
-pub trait RangeArgument<T: ?Sized> {
-    /// Start index bound.
-    ///
-    /// Returns the start value as a `Bound`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(alloc)]
-    /// #![feature(collections_range)]
-    ///
-    /// extern crate alloc;
-    ///
-    /// # fn main() {
-    /// use alloc::range::RangeArgument;
-    /// use alloc::Bound::*;
-    ///
-    /// assert_eq!((..10).start(), Unbounded);
-    /// assert_eq!((3..10).start(), Included(&3));
-    /// # }
-    /// ```
-    fn start(&self) -> Bound<&T>;
-
-    /// End index bound.
-    ///
-    /// Returns the end value as a `Bound`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(alloc)]
-    /// #![feature(collections_range)]
-    ///
-    /// extern crate alloc;
-    ///
-    /// # fn main() {
-    /// use alloc::range::RangeArgument;
-    /// use alloc::Bound::*;
-    ///
-    /// assert_eq!((3..).end(), Unbounded);
-    /// assert_eq!((3..10).end(), Excluded(&10));
-    /// # }
-    /// ```
-    fn end(&self) -> Bound<&T>;
-}
-
-// FIXME add inclusive ranges to RangeArgument
-
-impl<T: ?Sized> RangeArgument<T> for RangeFull {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Unbounded
-    }
-}
-
-impl<T> RangeArgument<T> for RangeFrom<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Unbounded
-    }
-}
-
-impl<T> RangeArgument<T> for RangeTo<T> {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Excluded(&self.end)
-    }
-}
-
-impl<T> RangeArgument<T> for Range<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Excluded(&self.end)
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> RangeArgument<T> for RangeInclusive<T> {
-    fn start(&self) -> Bound<&T> {
-        Included(&self.start)
-    }
-    fn end(&self) -> Bound<&T> {
-        Included(&self.end)
-    }
-}
-
-#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-impl<T> RangeArgument<T> for RangeToInclusive<T> {
-    fn start(&self) -> Bound<&T> {
-        Unbounded
-    }
-    fn end(&self) -> Bound<&T> {
-        Included(&self.end)
-    }
-}
-
-impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
-    fn start(&self) -> Bound<&T> {
-        match *self {
-            (Included(ref start), _) => Included(start),
-            (Excluded(ref start), _) => Excluded(start),
-            (Unbounded, _)           => Unbounded,
-        }
-    }
-
-    fn end(&self) -> Bound<&T> {
-        match *self {
-            (_, Included(ref end)) => Included(end),
-            (_, Excluded(ref end)) => Excluded(end),
-            (_, Unbounded)         => Unbounded,
-        }
-    }
-}
-
-impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
-    fn start(&self) -> Bound<&T> {
-        self.0
-    }
-
-    fn end(&self) -> Bound<&T> {
-        self.1
-    }
-}
+pub use core::ops::RangeArgument;
index 79d1ccf637d3753a1cff9a3dd5e8813c713a50a0..1f0894d39d4d23a525ff4acef0382865a7b5dc69 100644 (file)
 use core::fmt;
 use core::hash;
 use core::iter::{FromIterator, FusedIterator};
-use core::ops::{self, Add, AddAssign, Index, IndexMut};
+use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ptr;
 use core::str::pattern::Pattern;
 use std_unicode::lossy;
 use std_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
 
 use borrow::{Cow, ToOwned};
-use range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
 use str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars};
 use vec::Vec;
 use boxed::Box;
index 5d1999a42629a2c54fe4bf5f56419ca5f3322cdc..e118d406ecf095cbcd91392e6971c920f74546e3 100644 (file)
@@ -74,7 +74,8 @@
 use core::mem;
 #[cfg(not(test))]
 use core::num::Float;
-use core::ops::{InPlace, Index, IndexMut, Place, Placer};
+use core::ops::{InPlace, Index, IndexMut, Place, Placer, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops;
 use core::ptr;
 use core::ptr::Shared;
@@ -84,8 +85,6 @@
 use borrow::Cow;
 use boxed::Box;
 use raw_vec::RawVec;
-use super::range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
 
 /// A contiguous growable array type, written `Vec<T>` but pronounced 'vector'.
 ///
index 18175a5d01bd2bc7bb13400a2a7aedae265d6437..d1d334267bccf8dc4fb86aaad33f94ef6ea7ad45 100644 (file)
@@ -21,7 +21,8 @@
 use core::fmt;
 use core::iter::{repeat, FromIterator, FusedIterator};
 use core::mem;
-use core::ops::{Index, IndexMut, Place, Placer, InPlace};
+use core::ops::{Index, IndexMut, Place, Placer, InPlace, RangeArgument};
+use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ptr;
 use core::ptr::Shared;
 use core::slice;
@@ -31,8 +32,6 @@
 
 use raw_vec::RawVec;
 
-use super::range::RangeArgument;
-use Bound::{Excluded, Included, Unbounded};
 use super::vec::Vec;
 
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
index de5d6df328cbd4fd7ca975e115c925b21c8b7fbe..0a939831622f5c1c926f34a1e8004cfc38701284 100644 (file)
@@ -46,6 +46,7 @@
 pub use alloc::borrow;
 pub use alloc::fmt;
 pub use alloc::linked_list;
+#[allow(deprecated)]
 pub use alloc::range;
 pub use alloc::slice;
 pub use alloc::str;
index 6f35d0417f18b1986f6db9042df62c09b625fa2b..33d2f729e1a1d20f1defa588b5e444968e305809 100644 (file)
@@ -335,7 +335,6 @@ pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
 /// Example usage:
 ///
 /// ```
-/// #![feature(reverse_cmp_key)]
 /// use std::cmp::Reverse;
 ///
 /// let mut v = vec![1, 2, 3, 4, 5, 6];
@@ -343,10 +342,10 @@ pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
 /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
 /// ```
 #[derive(PartialEq, Eq, Debug)]
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 pub struct Reverse<T>(pub T);
 
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 impl<T: PartialOrd> PartialOrd for Reverse<T> {
     #[inline]
     fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
@@ -363,7 +362,7 @@ fn ge(&self, other: &Self) -> bool { other.0 >= self.0 }
     fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
 }
 
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 impl<T: Ord> Ord for Reverse<T> {
     #[inline]
     fn cmp(&self, other: &Reverse<T>) -> Ordering {
index 8c3d3ce7d886b085c7b7964e726176475bdfbfff..bcc6d53c81d3bb9764bd94e4cdac15b339d44b31 100644 (file)
@@ -897,14 +897,11 @@ pub trait UpperExp {
     fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
-/// The `write` function takes an output stream, a precompiled format string,
-/// and a list of arguments. The arguments will be formatted according to the
-/// specified format string into the output stream provided.
+/// The `write` function takes an output stream, and an `Arguments` struct
+/// that can be precompiled with the `format_args!` macro.
 ///
-/// # Arguments
-///
-///   * output - the buffer to write output to
-///   * args - the precompiled arguments generated by `format_args!`
+/// The arguments will be formatted according to the specified format string
+/// into the output stream provided.
 ///
 /// # Examples
 ///
index bba42752f50c646db08b7240f745252c11f867c4..6c1e8e8960f7549f4b2f50f23e59714ae18375e3 100644 (file)
@@ -506,59 +506,7 @@ pub unsafe fn uninitialized<T>() -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
     unsafe {
-        // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
-        // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
-        // Haswell E processors. LLVM is more able to optimize if we give a struct a
-        // #[repr(simd)], even if we don't actually use this struct directly.
-        //
-        // FIXME repr(simd) broken on emscripten and redox
-        #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
-        struct Block(u64, u64, u64, u64);
-        struct UnalignedBlock(u64, u64, u64, u64);
-
-        let block_size = size_of::<Block>();
-
-        // Get raw pointers to the bytes of x & y for easier manipulation
-        let x = x as *mut T as *mut u8;
-        let y = y as *mut T as *mut u8;
-
-        // Loop through x & y, copying them `Block` at a time
-        // The optimizer should unroll the loop fully for most types
-        // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
-        let len = size_of::<T>();
-        let mut i = 0;
-        while i + block_size <= len {
-            // Create some uninitialized memory as scratch space
-            // Declaring `t` here avoids aligning the stack when this loop is unused
-            let mut t: Block = uninitialized();
-            let t = &mut t as *mut _ as *mut u8;
-            let x = x.offset(i as isize);
-            let y = y.offset(i as isize);
-
-            // Swap a block of bytes of x & y, using t as a temporary buffer
-            // This should be optimized into efficient SIMD operations where available
-            ptr::copy_nonoverlapping(x, t, block_size);
-            ptr::copy_nonoverlapping(y, x, block_size);
-            ptr::copy_nonoverlapping(t, y, block_size);
-            i += block_size;
-        }
-
-
-        if i < len {
-            // Swap any remaining bytes, using aligned types to copy
-            // where appropriate (this information is lost by conversion
-            // to *mut u8, so restore it manually here)
-            let mut t: UnalignedBlock = uninitialized();
-            let rem = len - i;
-
-            let t = &mut t as *mut _ as *mut u8;
-            let x = x.offset(i as isize);
-            let y = y.offset(i as isize);
-
-            ptr::copy_nonoverlapping(x, t, rem);
-            ptr::copy_nonoverlapping(y, x, rem);
-            ptr::copy_nonoverlapping(t, y, rem);
-        }
+        ptr::swap_nonoverlapping(x, y, 1);
     }
 }
 
index cb28035682d650607409d522448243413a03630b..ebc30dc8b61fb0fd390e16a745728c89d60cdc3f 100644 (file)
@@ -205,18 +205,25 @@ fn signum(self) -> f32 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        #[repr(C)]
+        union F32Bytes {
+            f: f32,
+            b: u32
+        }
+        unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
index ac6b1e67cd2785b17154e76062210bb6f6f76f8c..1a1fe4d86e0d093ccb3dab01139374948a88023b 100644 (file)
@@ -205,18 +205,23 @@ fn signum(self) -> f64 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        #[repr(C)]
+        union F64Bytes {
+            f: f64,
+            b: u64
+        }
+        unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
index a78f4fe28a6b411078325ada32db8f4381561c3c..34f00850579e8c3ee62b798360d439b9b43fbf89 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
 
+#[stable(feature = "range_argument", since = "1.19.0")]
+pub use self::range::{RangeArgument, Bound};
+
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 pub use self::range::{RangeInclusive, RangeToInclusive};
 
index 33258b7a875c599aa584d85db0a3d1965ab979c6..65e09da4fff05c3362f96fefb240c08bb9f98f52 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use fmt;
+use ops::Bound::{Included, Excluded, Unbounded};
 
 /// An unbounded range. Use `..` (two dots) for its shorthand.
 ///
@@ -71,7 +72,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 ///     assert_eq!(arr[1..3], [  1,2  ]);  // Range
 /// }
 /// ```
-#[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
     /// The lower bound of the range (inclusive).
@@ -134,7 +136,8 @@ pub fn contains(&self, item: Idx) -> bool {
 ///     assert_eq!(arr[1..3], [  1,2  ]);
 /// }
 /// ```
-#[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
     /// The lower bound of the range (inclusive).
@@ -250,17 +253,16 @@ pub fn contains(&self, item: Idx) -> bool {
 ///     assert_eq!(arr[1...2], [  1,2  ]);  // RangeInclusive
 /// }
 /// ```
-#[derive(Clone, PartialEq, Eq, Hash)]  // not Copy -- see #27186
+#[derive(Clone, PartialEq, Eq, Hash)]
+// not Copy -- see #27186
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 pub struct RangeInclusive<Idx> {
     /// The lower bound of the range (inclusive).
-    #[unstable(feature = "inclusive_range",
-               reason = "recently added, follows RFC",
+    #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
                issue = "28237")]
     pub start: Idx,
     /// The upper bound of the range (inclusive).
-    #[unstable(feature = "inclusive_range",
-               reason = "recently added, follows RFC",
+    #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
                issue = "28237")]
     pub end: Idx,
 }
@@ -333,8 +335,7 @@ pub fn contains(&self, item: Idx) -> bool {
 #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
 pub struct RangeToInclusive<Idx> {
     /// The upper bound of the range (inclusive)
-    #[unstable(feature = "inclusive_range",
-               reason = "recently added, follows RFC",
+    #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC",
                issue = "28237")]
     pub end: Idx,
 }
@@ -365,3 +366,158 @@ pub fn contains(&self, item: Idx) -> bool {
 
 // RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
 // because underflow would be possible with (..0).into()
+
+/// `RangeArgument` is implemented by Rust's built-in range types, produced
+/// by range syntax like `..`, `a..`, `..b` or `c..d`.
+#[stable(feature = "range_argument", since = "1.19.0")]
+pub trait RangeArgument<T: ?Sized> {
+    /// Start index bound.
+    ///
+    /// Returns the start value as a `Bound`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ops::RangeArgument;
+    /// use std::ops::Bound::*;
+    ///
+    /// assert_eq!((..10).start(), Unbounded);
+    /// assert_eq!((3..10).start(), Included(&3));
+    /// ```
+    #[stable(feature = "range_argument", since = "1.19.0")]
+    fn start(&self) -> Bound<&T>;
+
+    /// End index bound.
+    ///
+    /// Returns the end value as a `Bound`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ops::RangeArgument;
+    /// use std::ops::Bound::*;
+    ///
+    /// assert_eq!((3..).end(), Unbounded);
+    /// assert_eq!((3..10).end(), Excluded(&10));
+    /// ```
+    #[stable(feature = "range_argument", since = "1.19.0")]
+    fn end(&self) -> Bound<&T>;
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T: ?Sized> RangeArgument<T> for RangeFull {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Unbounded
+    }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for RangeFrom<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Unbounded
+    }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for RangeTo<T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(&self.end)
+    }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for Range<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Excluded(&self.end)
+    }
+}
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> RangeArgument<T> for RangeInclusive<T> {
+    fn start(&self) -> Bound<&T> {
+        Included(&self.start)
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(&self.end)
+    }
+}
+
+#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
+impl<T> RangeArgument<T> for RangeToInclusive<T> {
+    fn start(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end(&self) -> Bound<&T> {
+        Included(&self.end)
+    }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
+    fn start(&self) -> Bound<&T> {
+        match *self {
+            (Included(ref start), _) => Included(start),
+            (Excluded(ref start), _) => Excluded(start),
+            (Unbounded, _) => Unbounded,
+        }
+    }
+
+    fn end(&self) -> Bound<&T> {
+        match *self {
+            (_, Included(ref end)) => Included(end),
+            (_, Excluded(ref end)) => Excluded(end),
+            (_, Unbounded) => Unbounded,
+        }
+    }
+}
+
+#[stable(feature = "range_argument", since = "1.19.0")]
+impl<'a, T: ?Sized + 'a> RangeArgument<T> for (Bound<&'a T>, Bound<&'a T>) {
+    fn start(&self) -> Bound<&T> {
+        self.0
+    }
+
+    fn end(&self) -> Bound<&T> {
+        self.1
+    }
+}
+
+/// An endpoint of a range of keys.
+///
+/// # Examples
+///
+/// `Bound`s are range endpoints:
+///
+/// ```
+/// use std::ops::RangeArgument;
+/// use std::ops::Bound::*;
+///
+/// assert_eq!((..100).start(), Unbounded);
+/// assert_eq!((1..12).start(), Included(&1));
+/// assert_eq!((1..12).end(), Excluded(&12));
+/// ```
+#[stable(feature = "collections_bound", since = "1.17.0")]
+#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
+pub enum Bound<T> {
+    /// An inclusive bound.
+    #[stable(feature = "collections_bound", since = "1.17.0")]
+    Included(T),
+    /// An exclusive bound.
+    #[stable(feature = "collections_bound", since = "1.17.0")]
+    Excluded(T),
+    /// An infinite endpoint. Indicates that there is no bound in this direction.
+    #[stable(feature = "collections_bound", since = "1.17.0")]
+    Unbounded,
+}
index 54ae9e0d628d59c78f365378c931ec1548a076a4..92470299366ce9fbc9df72695221151007495019 100644 (file)
@@ -117,6 +117,90 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     mem::forget(tmp);
 }
 
+/// Swaps a sequence of values at two mutable locations of the same type.
+///
+/// # Safety
+///
+/// The two arguments must each point to the beginning of `count` locations
+/// of valid memory, and the two memory ranges must not overlap.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// #![feature(swap_nonoverlapping)]
+///
+/// use std::ptr;
+///
+/// let mut x = [1, 2, 3, 4];
+/// let mut y = [7, 8, 9];
+///
+/// unsafe {
+///     ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2);
+/// }
+///
+/// assert_eq!(x, [7, 8, 3, 4]);
+/// assert_eq!(y, [1, 2, 9]);
+/// ```
+#[inline]
+#[unstable(feature = "swap_nonoverlapping", issue = "42818")]
+pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+    let x = x as *mut u8;
+    let y = y as *mut u8;
+    let len = mem::size_of::<T>() * count;
+    swap_nonoverlapping_bytes(x, y, len)
+}
+
+#[inline]
+unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+    // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
+    // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
+    // Haswell E processors. LLVM is more able to optimize if we give a struct a
+    // #[repr(simd)], even if we don't actually use this struct directly.
+    //
+    // FIXME repr(simd) broken on emscripten and redox
+    #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
+    struct Block(u64, u64, u64, u64);
+    struct UnalignedBlock(u64, u64, u64, u64);
+
+    let block_size = mem::size_of::<Block>();
+
+    // Loop through x & y, copying them `Block` at a time
+    // The optimizer should unroll the loop fully for most types
+    // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+    let mut i = 0;
+    while i + block_size <= len {
+        // Create some uninitialized memory as scratch space
+        // Declaring `t` here avoids aligning the stack when this loop is unused
+        let mut t: Block = mem::uninitialized();
+        let t = &mut t as *mut _ as *mut u8;
+        let x = x.offset(i as isize);
+        let y = y.offset(i as isize);
+
+        // Swap a block of bytes of x & y, using t as a temporary buffer
+        // This should be optimized into efficient SIMD operations where available
+        copy_nonoverlapping(x, t, block_size);
+        copy_nonoverlapping(y, x, block_size);
+        copy_nonoverlapping(t, y, block_size);
+        i += block_size;
+    }
+
+    if i < len {
+        // Swap any remaining bytes
+        let mut t: UnalignedBlock = mem::uninitialized();
+        let rem = len - i;
+
+        let t = &mut t as *mut _ as *mut u8;
+        let x = x.offset(i as isize);
+        let y = y.offset(i as isize);
+
+        copy_nonoverlapping(x, t, rem);
+        copy_nonoverlapping(y, x, rem);
+        copy_nonoverlapping(t, y, rem);
+    }
+}
+
 /// Replaces the value at `dest` with `src`, returning the old
 /// value, without dropping either.
 ///
index 3b9ae5652c5d1cf05005fe788a24af41f9bffdd7..e4a4e33c1729efb94bd924b552915d048480d6c5 100644 (file)
@@ -76,7 +76,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
             break;
         }
 
-        ptr_swap_n(
+        ptr::swap_nonoverlapping(
             mid.offset(-(left as isize)),
             mid.offset((right-delta) as isize),
             delta);
@@ -103,10 +103,3 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
         ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right);
     }
 }
-
-unsafe fn ptr_swap_n<T>(a: *mut T, b: *mut T, n: usize) {
-    for i in 0..n {
-        // These are nonoverlapping, so use mem::swap instead of ptr::swap
-        mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize));
-    }
-}
index 62bedcdfcbe610b534042aa06bbe568745b2858e..873d39ec9e9fb0fb6cd7d16a198d27390b146958 100644 (file)
@@ -2170,12 +2170,12 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
                 //       mut iter => {
                 //         [opt_ident]: loop {
-                //           let mut _next;
+                //           let mut __next;
                 //           match ::std::iter::Iterator::next(&mut iter) {
-                //             ::std::option::Option::Some(val) => _next = val,
+                //             ::std::option::Option::Some(val) => __next = val,
                 //             ::std::option::Option::None => break
                 //           };
-                //           let <pat> = _next;
+                //           let <pat> = __next;
                 //           StmtExpr(<body>);
                 //         }
                 //       }
@@ -2188,7 +2188,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 let iter = self.str_to_ident("iter");
 
-                let next_ident = self.str_to_ident("_next");
+                let next_ident = self.str_to_ident("__next");
                 let next_pat = self.pat_ident_binding_mode(e.span,
                                                            next_ident,
                                                            hir::BindByValue(hir::MutMutable));
@@ -2237,13 +2237,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
 
-                // `let mut _next`
+                // `let mut __next`
                 let next_let = self.stmt_let_pat(e.span,
                     None,
                     next_pat,
                     hir::LocalSource::ForLoopDesugar);
 
-                // `let <pat> = _next`
+                // `let <pat> = __next`
                 let pat = self.lower_pat(pat);
                 let pat_let = self.stmt_let_pat(e.span,
                     Some(next_expr),
index a1875cd46a0cb85932408b67796861d2c989d3bb..02a36a372d9ef3354aab83d9e93dcb9afa1039fc 100644 (file)
@@ -594,8 +594,12 @@ pub fn is_argument(&self, id: NodeId) -> bool {
     /// last good node id we found. Note that reaching the crate root (id == 0),
     /// is not an error, since items in the crate module have the crate root as
     /// parent.
-    fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
-        where F: Fn(&Node<'hir>) -> bool
+    fn walk_parent_nodes<F, F2>(&self,
+                                start_id: NodeId,
+                                found: F,
+                                bail_early: F2)
+        -> Result<NodeId, NodeId>
+        where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool
     {
         let mut id = start_id;
         loop {
@@ -616,6 +620,8 @@ fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, Nod
                 Some(ref node) => {
                     if found(node) {
                         return Ok(parent_node);
+                    } else if bail_early(node) {
+                        return Err(parent_node);
                     }
                 }
                 None => {
@@ -626,6 +632,56 @@ fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, Nod
         }
     }
 
+    /// Retrieve the NodeId for `id`'s enclosing method, unless there's a
+    /// `while` or `loop` before reacing it, as block tail returns are not
+    /// available in them.
+    ///
+    /// ```
+    /// fn foo(x: usize) -> bool {
+    ///     if x == 1 {
+    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///     } else {  // to this, it will return `foo`'s `NodeId`.
+    ///         false
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// ```
+    /// fn foo(x: usize) -> bool {
+    ///     loop {
+    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///     }         // to this, it will return `None`.
+    ///     false
+    /// }
+    /// ```
+    pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
+        let match_fn = |node: &Node| {
+            match *node {
+                NodeItem(_) |
+                NodeForeignItem(_) |
+                NodeTraitItem(_) |
+                NodeImplItem(_) => true,
+                _ => false,
+            }
+        };
+        let match_non_returning_block = |node: &Node| {
+            match *node {
+                NodeExpr(ref expr) => {
+                    match expr.node {
+                        ExprWhile(..) | ExprLoop(..) => true,
+                        _ => false,
+                    }
+                }
+                _ => false,
+            }
+        };
+
+        match self.walk_parent_nodes(id, match_fn, match_non_returning_block) {
+            Ok(id) => Some(id),
+            Err(_) => None,
+        }
+    }
+
     /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
     /// parent item is in this map. The "parent item" is the closest parent node
     /// in the AST which is recorded by the map and is an item, either an item
@@ -637,7 +693,7 @@ pub fn get_parent(&self, id: NodeId) -> NodeId {
             NodeTraitItem(_) |
             NodeImplItem(_) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => id,
             Err(id) => id,
         }
@@ -649,7 +705,7 @@ pub fn get_module_parent(&self, id: NodeId) -> DefId {
         let id = match self.walk_parent_nodes(id, |node| match *node {
             NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => id,
             Err(id) => id,
         };
@@ -668,7 +724,7 @@ pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> {
             NodeImplItem(_) |
             NodeBlock(_) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => Some(id),
             Err(_) => None,
         }
index 4e78d79ef87378e8d1376a1f4a5b368d7fe7facb..4f365a97f4ceba1719af50f475bf9b06e1068263 100644 (file)
@@ -524,10 +524,9 @@ fn hash_stable<W: StableHasherResult>(&self,
                 region.hash_stable(hcx, hasher);
                 pointee_ty.hash_stable(hcx, hasher);
             }
-            TyFnDef(def_id, substs, ref sig) => {
+            TyFnDef(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
-                sig.hash_stable(hcx, hasher);
             }
             TyFnPtr(ref sig) => {
                 sig.hash_stable(hcx, hasher);
index 7361d66428f6d94cb052590dbe07fd6828ae652f..a684881c0912abbb7ee967433d60d15c5ab6ecbd 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hir::{self, map, Local, Pat, Body};
+use hir::{self, Local, Pat, Body};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::InferCtxt;
 use infer::type_variable::TypeVariableOrigin;
@@ -88,7 +88,7 @@ fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
         }
     }
 
-    pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
+    pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) {
         let ty = self.resolve_type_vars_if_possible(&ty);
         let name = self.extract_type_name(&ty);
 
@@ -103,11 +103,9 @@ pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
             found_arg_pattern: None,
         };
 
-        // #40294: cause.body_id can also be a fn declaration.
-        // Currently, if it's anything other than NodeExpr, we just ignore it
-        match self.tcx.hir.find(body_id.node_id) {
-            Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr),
-            _ => ()
+        if let Some(body_id) = body_id {
+            let expr = self.tcx.hir.expect_expr(body_id.node_id);
+            local_visitor.visit_expr(expr);
         }
 
         if let Some(pattern) = local_visitor.found_arg_pattern {
index f96e8c389d68d87db962994d2941e56309572e54..d5020b12ee00e12c5e86295d92ad75a9a8219c03 100644 (file)
@@ -1369,7 +1369,11 @@ pub fn closure_kind(&self,
         Some(self.tcx.closure_kind(def_id))
     }
 
-    pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+    /// Obtain the signature of a function or closure.
+    /// For closures, unlike `tcx.fn_sig(def_id)`, this method will
+    /// work during the type-checking of the enclosing function and
+    /// return the closure signature in its partially inferred state.
+    pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
         if let Some(tables) = self.in_progress_tables {
             if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                 if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
@@ -1378,7 +1382,7 @@ pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
             }
         }
 
-        self.tcx.closure_type(def_id)
+        self.tcx.fn_sig(def_id)
     }
 }
 
index 1a0ab8c413d342f7d37d27e306d9bf9ed847dde8..8202c6106d14753e67db667eaeba4e2582f91a57 100644 (file)
@@ -291,16 +291,13 @@ pub fn register_removed(&mut self, name: &str, reason: &str) {
         self.by_name.insert(name.into(), Removed(reason.into()));
     }
 
-    #[allow(unused_variables)]
-    fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
-                 -> Result<LintId, FindLintError>
-    {
+    fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
         match self.by_name.get(lint_name) {
             Some(&Id(lint_id)) => Ok(lint_id),
             Some(&Renamed(_, lint_id)) => {
                 Ok(lint_id)
             },
-            Some(&Removed(ref reason)) => {
+            Some(&Removed(_)) => {
                 Err(FindLintError::Removed)
             },
             None => Err(FindLintError::NotFound)
@@ -313,7 +310,7 @@ pub fn process_command_line(&mut self, sess: &Session) {
                                     &lint_name[..], level);
 
             let lint_flag_val = Symbol::intern(&lint_name);
-            match self.find_lint(&lint_name[..], sess, None) {
+            match self.find_lint(&lint_name[..]) {
                 Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
                 Err(FindLintError::Removed) => { }
                 Err(_) => {
@@ -724,21 +721,22 @@ fn with_lint_attrs<F>(&mut self,
         let mut pushed = 0;
 
         for result in gather_attrs(attrs) {
-            let v = match result {
+            let (is_group, lint_level_spans) = match result {
                 Err(span) => {
                     span_err!(self.sess(), span, E0452,
                               "malformed lint attribute");
                     continue;
                 }
                 Ok((lint_name, level, span)) => {
-                    match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) {
-                        Ok(lint_id) => vec![(lint_id, level, span)],
+                    match self.lints().find_lint(&lint_name.as_str()) {
+                        Ok(lint_id) => (false, vec![(lint_id, level, span)]),
                         Err(FindLintError::NotFound) => {
                             match self.lints().lint_groups.get(&*lint_name.as_str()) {
-                                Some(&(ref v, _)) => v.iter()
+                                Some(&(ref v, _)) => (true,
+                                                      v.iter()
                                                       .map(|lint_id: &LintId|
                                                            (*lint_id, level, span))
-                                                      .collect(),
+                                                      .collect()),
                                 None => {
                                     // The lint or lint group doesn't exist.
                                     // This is an error, but it was handled
@@ -754,14 +752,18 @@ fn with_lint_attrs<F>(&mut self,
 
             let lint_attr_name = result.expect("lint attribute should be well-formed").0;
 
-            for (lint_id, level, span) in v {
+            for (lint_id, level, span) in lint_level_spans {
                 let (now, now_source) = self.lint_sess().get_source(lint_id);
                 if now == Forbid && level != Forbid {
-                    let lint_name = lint_id.to_string();
+                    let forbidden_lint_name = match now_source {
+                        LintSource::Default => lint_id.to_string(),
+                        LintSource::Node(name, _) => name.to_string(),
+                        LintSource::CommandLine(name) => name.to_string(),
+                    };
                     let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
                                                             "{}({}) overruled by outer forbid({})",
-                                                            level.as_str(), lint_name,
-                                                            lint_name);
+                                                            level.as_str(), lint_attr_name,
+                                                            forbidden_lint_name);
                     diag_builder.span_label(span, "overruled by previous forbid");
                     match now_source {
                         LintSource::Default => &mut diag_builder,
@@ -772,7 +774,10 @@ fn with_lint_attrs<F>(&mut self,
                         LintSource::CommandLine(_) => {
                             diag_builder.note("`forbid` lint level was set on command line")
                         }
-                    }.emit()
+                    }.emit();
+                    if is_group { // don't set a separate error for every lint in the group
+                        break;
+                    }
                 } else if now != level {
                     let cx = self.lint_sess_mut();
                     cx.stack.push((lint_id, (now, now_source)));
@@ -1420,7 +1425,7 @@ impl Decodable for LintId {
     fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
         let s = d.read_str()?;
         ty::tls::with(|tcx| {
-            match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
+            match tcx.sess.lint_store.borrow().find_lint(&s) {
                 Ok(id) => Ok(id),
                 Err(_) => panic!("invalid lint-id `{}`", s),
             }
index 74e1225f3948b92e9ab52e93f016ba48271a3d9e..eab5a8f910331184187caac0a7dd822df61afd86 100644 (file)
@@ -12,7 +12,7 @@
 //! `unsafe`.
 use self::RootUnsafeContext::*;
 
-use ty::{self, Ty, TyCtxt};
+use ty::{self, TyCtxt};
 use lint;
 
 use syntax::ast;
@@ -40,14 +40,6 @@ enum RootUnsafeContext {
     UnsafeBlock(ast::NodeId),
 }
 
-fn type_is_unsafe_function(ty: Ty) -> bool {
-    match ty.sty {
-        ty::TyFnDef(.., f) |
-        ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe,
-        _ => false,
-    }
-}
-
 struct EffectCheckVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
@@ -174,10 +166,11 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         match expr.node {
             hir::ExprMethodCall(..) => {
                 let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
-                let base_type = self.tcx.type_of(def_id);
-                debug!("effect: method call case, base type is {:?}",
-                        base_type);
-                if type_is_unsafe_function(base_type) {
+                let sig = self.tcx.fn_sig(def_id);
+                debug!("effect: method call case, signature is {:?}",
+                        sig);
+
+                if sig.0.unsafety == hir::Unsafety::Unsafe {
                     self.require_unsafe(expr.span,
                                         "invocation of unsafe method")
                 }
@@ -186,8 +179,13 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
                 let base_type = self.tables.expr_ty_adjusted(base);
                 debug!("effect: call case, base type is {:?}",
                         base_type);
-                if type_is_unsafe_function(base_type) {
-                    self.require_unsafe(expr.span, "call to unsafe function")
+                match base_type.sty {
+                    ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                        if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
+                            self.require_unsafe(expr.span, "call to unsafe function")
+                        }
+                    }
+                    _ => {}
                 }
             }
             hir::ExprUnary(hir::UnDeref, ref base) => {
index f180ae53b8ae1926868ad9794595f772c8e31f85..fde207e4b2f79f75922a2fb36ef74ce9739ad07b 100644 (file)
@@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        let intrinsic = match self.tcx.type_of(def_id).sty {
-            ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic,
-            _ => return false
-        };
-        intrinsic && self.tcx.item_name(def_id) == "transmute"
+        self.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
+        self.tcx.item_name(def_id) == "transmute"
     }
 
     fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
@@ -153,22 +150,14 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         } else {
             Def::Err
         };
-        match def {
-            Def::Fn(did) if self.def_id_is_transmute(did) => {
+        if let Def::Fn(did) = def {
+            if self.def_id_is_transmute(did) {
                 let typ = self.tables.node_id_to_type(expr.id);
-                let typ = self.tcx.lift_to_global(&typ).unwrap();
-                match typ.sty {
-                    ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => {
-                        let from = sig.inputs().skip_binder()[0];
-                        let to = *sig.output().skip_binder();
-                        self.check_transmute(expr.span, from, to);
-                    }
-                    _ => {
-                        span_bug!(expr.span, "transmute wasn't a bare fn?!");
-                    }
-                }
+                let sig = typ.fn_sig(self.tcx);
+                let from = sig.inputs().skip_binder()[0];
+                let to = *sig.output().skip_binder();
+                self.check_transmute(expr.span, from, to);
             }
-            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
index 247fb079fe7ee68d0d3ac4204d299cf81ea550dc..e2e3d520d4777d96ade68f088a78af54cc46b95f 100644 (file)
@@ -45,7 +45,8 @@
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_fulfillment_errors(&self,
-                                     errors: &Vec<FulfillmentError<'tcx>>) {
+                                     errors: &Vec<FulfillmentError<'tcx>>,
+                                     body_id: Option<hir::BodyId>) {
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
             predicate: ty::Predicate<'tcx>,
@@ -105,7 +106,7 @@ struct ErrorDescriptor<'tcx> {
 
         for (error, suppressed) in errors.iter().zip(is_suppressed) {
             if !suppressed {
-                self.report_fulfillment_error(error);
+                self.report_fulfillment_error(error, body_id);
             }
         }
     }
@@ -148,7 +149,8 @@ fn error_implies(&self,
         false
     }
 
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
+                                body_id: Option<hir::BodyId>) {
         debug!("report_fulfillment_errors({:?})", error);
         match error.code {
             FulfillmentErrorCode::CodeSelectionError(ref e) => {
@@ -158,7 +160,7 @@ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
                 self.report_projection_error(&error.obligation, e);
             }
             FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation);
+                self.maybe_report_ambiguity(&error.obligation, body_id);
             }
             FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
                 self.report_mismatched_types(&error.obligation.cause,
@@ -869,14 +871,14 @@ pub fn report_object_safety_error(self,
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>,
+                              body_id: Option<hir::BodyId>) {
         // Unable to successfully determine, probably means
         // insufficient type information, but could mean
         // ambiguous impls. The latter *ought* to be a
         // coherence violation, so we don't report it here.
 
         let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
-        let body_id = hir::BodyId { node_id: obligation.cause.body_id };
         let span = obligation.cause.span;
 
         debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
@@ -953,7 +955,7 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
                     let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
                     // both must be type variables, or the other would've been instantiated
                     assert!(a.is_ty_var() && b.is_ty_var());
-                    self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
+                    self.need_type_info(body_id,
                                         obligation.cause.span,
                                         a);
                 }
@@ -1088,7 +1090,7 @@ fn note_obligation_cause_code<T>(&self,
             ObligationCauseCode::VariableType(_) => {
                 err.note("all local variables must have a statically known size");
             }
-            ObligationCauseCode::ReturnType => {
+            ObligationCauseCode::SizedReturnType => {
                 err.note("the return type of a function must have a \
                           statically known size");
             }
@@ -1133,6 +1135,8 @@ fn note_obligation_cause_code<T>(&self,
                               but not on the corresponding trait method",
                              predicate));
             }
+            ObligationCauseCode::ReturnType(_) |
+            ObligationCauseCode::BlockTailExpression(_) => (),
         }
     }
 
index e9196cd12431bc825b13e3ffde7bf5edd5a883f4..c128438aea0d48305eefb929b832f155082140c9 100644 (file)
@@ -118,27 +118,32 @@ pub enum ObligationCauseCode<'tcx> {
     /// Obligation incurred due to an object cast.
     ObjectCastObligation(/* Object type */ Ty<'tcx>),
 
-    /// Various cases where expressions must be sized/copy/etc:
-    AssignmentLhsSized,        // L = X implies that L is Sized
-    StructInitializerSized,    // S { ... } must be Sized
-    VariableType(ast::NodeId), // Type of each variable must be Sized
-    ReturnType,                // Return type must be Sized
-    RepeatVec,                 // [T,..n] --> T must be Copy
-
-    // Types of fields (other than the last) in a struct must be sized.
+    // Various cases where expressions must be sized/copy/etc:
+    /// L = X implies that L is Sized
+    AssignmentLhsSized,
+    /// S { ... } must be Sized
+    StructInitializerSized,
+    /// Type of each variable must be Sized
+    VariableType(ast::NodeId),
+    /// Return type must be Sized
+    SizedReturnType,
+    /// [T,..n] --> T must be Copy
+    RepeatVec,
+
+    /// Types of fields (other than the last) in a struct must be sized.
     FieldSized,
 
-    // Constant expressions must be sized.
+    /// Constant expressions must be sized.
     ConstSized,
 
-    // static items must have `Sync` type
+    /// static items must have `Sync` type
     SharedStatic,
 
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
     ImplDerivedObligation(DerivedObligationCause<'tcx>),
 
-    // error derived when matching traits/impls; see ObligationCause for more details
+    /// error derived when matching traits/impls; see ObligationCause for more details
     CompareImplMethodObligation {
         item_name: ast::Name,
         impl_item_def_id: DefId,
@@ -146,37 +151,43 @@ pub enum ObligationCauseCode<'tcx> {
         lint_id: Option<ast::NodeId>,
     },
 
-    // Checking that this expression can be assigned where it needs to be
+    /// Checking that this expression can be assigned where it needs to be
     // FIXME(eddyb) #11161 is the original Expr required?
     ExprAssignable,
 
-    // Computing common supertype in the arms of a match expression
+    /// Computing common supertype in the arms of a match expression
     MatchExpressionArm { arm_span: Span,
                          source: hir::MatchSource },
 
-    // Computing common supertype in an if expression
+    /// Computing common supertype in an if expression
     IfExpression,
 
-    // Computing common supertype of an if expression with no else counter-part
+    /// Computing common supertype of an if expression with no else counter-part
     IfExpressionWithNoElse,
 
-    // `where a == b`
+    /// `where a == b`
     EquatePredicate,
 
-    // `main` has wrong type
+    /// `main` has wrong type
     MainFunctionType,
 
-    // `start` has wrong type
+    /// `start` has wrong type
     StartFunctionType,
 
-    // intrinsic has wrong type
+    /// intrinsic has wrong type
     IntrinsicType,
 
-    // method receiver
+    /// method receiver
     MethodReceiver,
 
-    // `return` with no expression
+    /// `return` with no expression
     ReturnNoExpression,
+
+    /// `return` with an expression
+    ReturnType(ast::NodeId),
+
+    /// Block implicit return
+    BlockTailExpression(ast::NodeId),
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -498,7 +509,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ) {
             Ok(predicates) => predicates,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors);
+                infcx.report_fulfillment_errors(&errors, None);
                 // An unnormalized env is better than nothing.
                 return elaborated_env;
             }
@@ -597,7 +608,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("normalize_and_test_predicates(predicates={:?})",
            predicates);
 
-    tcx.infer_ctxt().enter(|infcx| {
+    let result = tcx.infer_ctxt().enter(|infcx| {
         let param_env = ty::ParamEnv::empty(Reveal::All);
         let mut selcx = SelectionContext::new(&infcx);
         let mut fulfill_cx = FulfillmentContext::new();
@@ -613,7 +624,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
 
         fulfill_cx.select_all_or_error(&infcx).is_ok()
-    })
+    });
+    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}",
+           predicates, result);
+    result
 }
 
 /// Given a trait `trait_ref`, iterates the vtable entries
index 0e3a53129d157fe2af455cacd25a59597c87b22f..c6c052fa4b1bc100b8bd034126464cd2d71d4bc8 100644 (file)
@@ -260,7 +260,7 @@ fn virtual_call_violation_for_method(self,
 
         // The `Self` type is erased, so it should not appear in list of
         // arguments or return type apart from the receiver.
-        let ref sig = self.type_of(method.def_id).fn_sig();
+        let ref sig = self.fn_sig(method.def_id);
         for input_ty in &sig.skip_binder().inputs()[1..] {
             if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
index 787452121d375c841f51665ea8b23706ded59789..c356e53234d9c3e3248eb17138fce58c9f012e19 100644 (file)
@@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
     -> Progress<'tcx>
 {
     let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
-    let sig = fn_type.fn_sig();
+    let sig = fn_type.fn_sig(selcx.tcx());
+    let Normalized {
+        value: sig,
+        obligations
+    } = normalize_with_depth(selcx,
+                             obligation.param_env,
+                             obligation.cause.clone(),
+                             obligation.recursion_depth+1,
+                             &sig);
+
     confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
         .with_addl_obligations(fn_pointer_vtable.nested)
+        .with_addl_obligations(obligations)
 }
 
 fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
@@ -1149,7 +1159,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
     -> Progress<'tcx>
 {
     let closure_typer = selcx.closure_typer();
-    let closure_type = closure_typer.closure_type(vtable.closure_def_id)
+    let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
         .subst(selcx.tcx(), vtable.substs.substs);
     let Normalized {
         value: closure_type,
index 10710d963a0156731420bb942f34badff52ddd87..a66b6b863541e2446170291ace748b925f95c010 100644 (file)
@@ -1404,19 +1404,15 @@ fn assemble_fn_pointer_candidates(&mut self,
             }
 
             // provide an impl, but only for suitable `fn` pointers
-            ty::TyFnDef(.., ty::Binder(ty::FnSig {
-                unsafety: hir::Unsafety::Normal,
-                abi: Abi::Rust,
-                variadic: false,
-                ..
-            })) |
-            ty::TyFnPtr(ty::Binder(ty::FnSig {
-                unsafety: hir::Unsafety::Normal,
-                abi: Abi::Rust,
-                variadic: false,
-                ..
-            })) => {
-                candidates.vec.push(FnPointerCandidate);
+            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                if let ty::Binder(ty::FnSig {
+                    unsafety: hir::Unsafety::Normal,
+                    abi: Abi::Rust,
+                    variadic: false,
+                    ..
+                }) = self_ty.fn_sig(self.tcx()) {
+                    candidates.vec.push(FnPointerCandidate);
+                }
             }
 
             _ => { }
@@ -2348,7 +2344,7 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
 
         // ok to skip binder; it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let sig = self_ty.fn_sig();
+        let sig = self_ty.fn_sig(self.tcx());
         let trait_ref =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
                                                          self_ty,
@@ -2356,11 +2352,18 @@ fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
                                                          util::TupleArgumentsFlag::Yes)
             .map_bound(|(trait_ref, _)| trait_ref);
 
+        let Normalized { value: trait_ref, obligations } =
+            project::normalize_with_depth(self,
+                                          obligation.param_env,
+                                          obligation.cause.clone(),
+                                          obligation.recursion_depth + 1,
+                                          &trait_ref);
+
         self.confirm_poly_trait_refs(obligation.cause.clone(),
                                      obligation.param_env,
                                      obligation.predicate.to_poly_trait_ref(),
                                      trait_ref)?;
-        Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
+        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
     }
 
     fn confirm_closure_candidate(&mut self,
@@ -2799,7 +2802,7 @@ fn closure_trait_ref_unnormalized(&mut self,
                                       substs: ty::ClosureSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let closure_type = self.infcx.closure_type(closure_def_id)
+        let closure_type = self.infcx.fn_sig(closure_def_id)
             .subst(self.tcx(), substs.substs);
         let ty::Binder((trait_ref, _)) =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
index 4abb0cb549db45add7ce5f917660a282bc030f72..0d6df78c2ac5b88a0b4dd62a74b5768226a157b7 100644 (file)
@@ -191,7 +191,8 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
             super::StructInitializerSized => Some(super::StructInitializerSized),
             super::VariableType(id) => Some(super::VariableType(id)),
-            super::ReturnType => Some(super::ReturnType),
+            super::ReturnType(id) => Some(super::ReturnType(id)),
+            super::SizedReturnType => Some(super::SizedReturnType),
             super::RepeatVec => Some(super::RepeatVec),
             super::FieldSized => Some(super::FieldSized),
             super::ConstSized => Some(super::ConstSized),
@@ -213,34 +214,19 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
                     lint_id: lint_id,
                 })
             }
-            super::ExprAssignable => {
-                Some(super::ExprAssignable)
-            }
+            super::ExprAssignable => Some(super::ExprAssignable),
             super::MatchExpressionArm { arm_span, source } => {
                 Some(super::MatchExpressionArm { arm_span: arm_span,
                                                  source: source })
             }
-            super::IfExpression => {
-                Some(super::IfExpression)
-            }
-            super::IfExpressionWithNoElse => {
-                Some(super::IfExpressionWithNoElse)
-            }
-            super::EquatePredicate => {
-                Some(super::EquatePredicate)
-            }
-            super::MainFunctionType => {
-                Some(super::MainFunctionType)
-            }
-            super::StartFunctionType => {
-                Some(super::StartFunctionType)
-            }
-            super::IntrinsicType => {
-                Some(super::IntrinsicType)
-            }
-            super::MethodReceiver => {
-                Some(super::MethodReceiver)
-            }
+            super::IfExpression => Some(super::IfExpression),
+            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
+            super::EquatePredicate => Some(super::EquatePredicate),
+            super::MainFunctionType => Some(super::MainFunctionType),
+            super::StartFunctionType => Some(super::StartFunctionType),
+            super::IntrinsicType => Some(super::IntrinsicType),
+            super::MethodReceiver => Some(super::MethodReceiver),
+            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
         }
     }
 }
@@ -492,12 +478,14 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             super::AssignmentLhsSized |
             super::StructInitializerSized |
             super::VariableType(_) |
-            super::ReturnType |
+            super::ReturnType(_) |
+            super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized |
             super::ConstSized |
             super::SharedStatic |
+            super::BlockTailExpression(_) |
             super::CompareImplMethodObligation { .. } => self.clone(),
 
             super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)),
@@ -537,12 +525,14 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             super::AssignmentLhsSized |
             super::StructInitializerSized |
             super::VariableType(_) |
-            super::ReturnType |
+            super::ReturnType(_) |
+            super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized |
             super::ConstSized |
             super::SharedStatic |
+            super::BlockTailExpression(_) |
             super::CompareImplMethodObligation { .. } => false,
 
             super::ProjectionWf(proj) => proj.visit_with(visitor),
index 2d81606329e57d89e530101e7a1cb116b85a7f59..5f869fc5567ee186d58a7641505634de882a94b9 100644 (file)
@@ -1378,9 +1378,8 @@ pub fn mk_bool(self) -> Ty<'tcx> {
     }
 
     pub fn mk_fn_def(self, def_id: DefId,
-                     substs: &'tcx Substs<'tcx>,
-                     fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyFnDef(def_id, substs, fty))
+                     substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyFnDef(def_id, substs))
     }
 
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
index 3d2cc4c598a22ea66677cc53010e271920c0c3e2..68f85ba7d33e23dc87beb3ab93134b71352c6edd 100644 (file)
@@ -68,6 +68,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             // view of possibly unifying
             simplify_type(tcx, mt.ty, can_simplify_params)
         }
+        ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) => {
             Some(ClosureSimplifiedType(def_id))
         }
@@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyTuple(ref tys, _) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
+        ty::TyFnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
         }
         ty::TyProjection(_) | ty::TyParam(_) => {
index 46afa6ee7d011d48053d892c02cd4cdc1ec65b83..d5aa9f55ff0c4e34beb5942070f79ba6bee1f78b 100644 (file)
@@ -155,9 +155,8 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
                 self.add_tys(&ts[..]);
             }
 
-            &ty::TyFnDef(_, substs, f) => {
+            &ty::TyFnDef(_, substs) => {
                 self.add_substs(substs);
-                self.add_fn_sig(f);
             }
 
             &ty::TyFnPtr(f) => {
index 09a3bcd06138056afaa89b6641d415a5b8ab4c56..b9896e0cecf5dac93d19cebe75950af51194daf8 100644 (file)
@@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
                                       .filter_map(|ty| characteristic_def_id_of_type(ty))
                                       .next(),
 
-        ty::TyFnDef(def_id, ..) |
+        ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) => Some(def_id),
 
         ty::TyBool |
index 524cf57472bc86dca71d4210e93381decd9df056..a6c59d4c2235436fc1e6f739b02c34ea76fa2bfc 100644 (file)
@@ -875,13 +875,12 @@ fn default() -> Self {
     /// for trans. This is also the only query that can fetch non-local MIR, at present.
     [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,
 
-    /// Records the type of each closure. The def ID is the ID of the
+    /// Type of each closure. The def ID is the ID of the
     /// expression defining the closure.
     [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
 
-    /// Records the type of each closure. The def ID is the ID of the
-    /// expression defining the closure.
-    [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
+    /// The signature of functions and closures.
+    [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     [] coerce_unsized_info: ItemSignature(DefId)
index 13e46a265c6953c6d6305910975cb274ea6ba49c..548ee7bcbe503eb743630f388d4ec970fd177046 100644 (file)
@@ -206,7 +206,7 @@ pub fn signature<'a, 'tcx>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>) -> String {
                 // late-bound regions, and we don't want method signatures to show up
                 // `as for<'r> fn(&'r MyType)`.  Pretty-printing handles late-bound
                 // regions just fine, showing `fn(&MyType)`.
-                format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder())
+                format!("{}", tcx.fn_sig(self.def_id).skip_binder())
             }
             ty::AssociatedKind::Type => format!("type {};", self.name.to_string()),
             ty::AssociatedKind::Const => {
@@ -481,6 +481,18 @@ pub fn is_primitive_ty(&self) -> bool {
             _ => false,
         }
     }
+
+    pub fn is_suggestable(&self) -> bool {
+        match self.sty {
+            TypeVariants::TyAnon(..) |
+            TypeVariants::TyFnDef(..) |
+            TypeVariants::TyFnPtr(..) |
+            TypeVariants::TyDynamic(..) |
+            TypeVariants::TyClosure(..) |
+            TypeVariants::TyProjection(..) => false,
+            _ => true,
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'tcx> {
index d4f06a902eeaa46221b45ead63abfcb74ea69cb0..2e9780572c9b40bfa8d4ac2a1b1aafee64fb9835 100644 (file)
@@ -291,7 +291,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -308,7 +308,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             }
         }
 
-        (&ty::TyFnDef(a_def_id, a_substs, a_fty),
-         &ty::TyFnDef(b_def_id, b_substs, b_fty))
+        (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
-            let substs = relate_substs(relation, None, a_substs, b_substs)?;
-            let fty = relation.relate(&a_fty, &b_fty)?;
-            Ok(tcx.mk_fn_def(a_def_id, substs, fty))
+            let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
+            Ok(tcx.mk_fn_def(a_def_id, substs))
         }
 
         (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
index 1e2689243903e3a7c2f81f186d78ea4b2f09f0d9..d05262965d7fd6daf8505f23bcdd7bb51c842c8b 100644 (file)
@@ -531,10 +531,8 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::TyDynamic(ref trait_ty, ref region) =>
                 ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
             ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
-            ty::TyFnDef(def_id, substs, f) => {
-                ty::TyFnDef(def_id,
-                            substs.fold_with(folder),
-                            f.fold_with(folder))
+            ty::TyFnDef(def_id, substs) => {
+                ty::TyFnDef(def_id, substs.fold_with(folder))
             }
             ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)),
             ty::TyRef(ref r, tm) => {
@@ -568,9 +566,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             ty::TyDynamic(ref trait_ty, ref reg) =>
                 trait_ty.visit_with(visitor) || reg.visit_with(visitor),
             ty::TyTuple(ts, _) => ts.visit_with(visitor),
-            ty::TyFnDef(_, substs, ref f) => {
-                substs.visit_with(visitor) || f.visit_with(visitor)
-            }
+            ty::TyFnDef(_, substs) => substs.visit_with(visitor),
             ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
index 6923a6d21d63f1dec1cc499cffd9154338189b66..ed3312d88a38420babc569919be055fe161b30f3 100644 (file)
@@ -14,7 +14,7 @@
 use hir::map::DefPathHash;
 
 use middle::region;
-use ty::subst::Substs;
+use ty::subst::{Substs, Subst};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
 use ty::subst::Kind;
@@ -138,7 +138,7 @@ pub enum TypeVariants<'tcx> {
 
     /// The anonymous type of a function declaration/definition. Each
     /// function has a unique type.
-    TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>),
+    TyFnDef(DefId, &'tcx Substs<'tcx>),
 
     /// A pointer to a function.  Written as `fn() -> i32`.
     TyFnPtr(PolyFnSig<'tcx>),
@@ -1329,9 +1329,12 @@ pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
         }
     }
 
-    pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
+    pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
         match self.sty {
-            TyFnDef(.., f) | TyFnPtr(f) => f,
+            TyFnDef(def_id, substs) => {
+                tcx.fn_sig(def_id).subst(tcx, substs)
+            }
+            TyFnPtr(f) => f,
             _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
index 1bbc767348563142d80d820066eb1ebdcbaf13dd..98ef7918fef82ac263afe005a05ddd94a86e0e93 100644 (file)
@@ -679,7 +679,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
             TyAnon(def_id, _) |
-            TyFnDef(def_id, ..) => self.def_id(def_id),
+            TyFnDef(def_id, _) => self.def_id(def_id),
             TyAdt(d, _) => self.def_id(d.did),
             TyFnPtr(f) => {
                 self.hash(f.unsafety());
index d7954953aba856902fb1829b0d8d30db6f60d71e..71844abfe534c14b8e6cf5dcd0f6e97de1325467 100644 (file)
@@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyTuple(ts, _) => {
             stack.extend(ts.iter().cloned().rev());
         }
-        ty::TyFnDef(_, substs, ft) => {
+        ty::TyFnDef(_, substs) => {
             stack.extend(substs.types().rev());
-            push_sig_subtypes(stack, ft);
         }
         ty::TyFnPtr(ft) => {
             push_sig_subtypes(stack, ft);
index 1fa63577196664437c73e45b208bdfdc6a5ec56a..eb6bffc29c56171ecc37cd1d07a7cc0571defb39 100644 (file)
@@ -753,8 +753,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 }
                 write!(f, ")")
             }
-            TyFnDef(def_id, substs, ref bare_fn) => {
-                write!(f, "{} {{", bare_fn.0)?;
+            TyFnDef(def_id, substs) => {
+                ty::tls::with(|tcx| {
+                    let mut sig = tcx.fn_sig(def_id);
+                    if let Some(substs) = tcx.lift(&substs) {
+                        sig = sig.subst(tcx, substs);
+                    }
+                    write!(f, "{} {{", sig.0)
+                })?;
                 parameterized(f, substs, def_id, &[])?;
                 write!(f, "}}")
             }
index 2c55460fb301b3ed55fab6c16e2eea04560e2ae1..4bef191b113bd66816416df4614fe65146c6c794 100644 (file)
@@ -161,18 +161,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            terminator: &'a Option<mir::Terminator<'tcx>>)
                            -> Option<(&'a [mir::Operand<'tcx>], Span)> {
     if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator {
-        if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind
-        {
-            if let mir::Operand::Constant(ref func) = *oper
-            {
-                if let ty::TyFnDef(def_id, _, sig) = func.ty.sty
-                {
-                    let abi = sig.abi();
+        if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind {
+            if let mir::Operand::Constant(ref func) = *oper {
+                if let ty::TyFnDef(def_id, _) = func.ty.sty {
+                    let abi = tcx.fn_sig(def_id).abi();
                     let name = tcx.item_name(def_id);
-                    if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-                        if name == "rustc_peek" {
-                            return Some((args, source_info.span));
-                        }
+                    if abi == Abi::RustIntrinsic &&  name == "rustc_peek" {
+                        return Some((args, source_info.span));
                     }
                 }
             }
index d175920e8a6baf895abb18522c26e55295cf5954..0a966b0c170712dceabb786c3b72e1e8f81bcc7f 100644 (file)
@@ -12,7 +12,7 @@
 
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
 use rustc::mir::{Field, BorrowKind, Mutability};
-use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region};
+use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
@@ -549,8 +549,8 @@ fn lower_variant_or_leaf(
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.variants.len() > 1 {
                     let substs = match ty.sty {
-                        TypeVariants::TyAdt(_, substs) => substs,
-                        TypeVariants::TyFnDef(_, substs, _) => substs,
+                        ty::TyAdt(_, substs) |
+                        ty::TyFnDef(_, substs) => substs,
                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
                     };
                     PatternKind::Variant {
index c03c2890ba34c6cb4723c3eb00ed514a8bf2e5a5..eacd394ad5ea14bb5bd316112b417e37cf23bb2e 100644 (file)
 //!
 //! The N above is determined by Array's implementor, by way of an associatated constant.
 
-use std::ops::{Deref, DerefMut};
+use std::ops::{Deref, DerefMut, RangeArgument};
 use std::iter::{self, IntoIterator, FromIterator};
 use std::slice;
 use std::vec;
-use std::collections::range::RangeArgument;
 
 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
 
index 078bb801751d0b2bf4bd54d43a2c4f8944888ed1..a9abdf1377e9dff62dc8e1b3bd9d91fa7f39daf8 100644 (file)
 use std::marker::Unsize;
 use std::iter::Extend;
 use std::ptr::{self, drop_in_place, Shared};
-use std::ops::{Deref, DerefMut, Range};
+use std::ops::{Deref, DerefMut, Range, RangeArgument};
+use std::ops::Bound::{Excluded, Included, Unbounded};
 use std::hash::{Hash, Hasher};
 use std::slice;
 use std::fmt;
 use std::mem;
-use std::collections::range::RangeArgument;
-use std::collections::Bound::{Excluded, Included, Unbounded};
 use std::mem::ManuallyDrop;
 
 pub unsafe trait Array {
index 29ac650aa7053110e374dfa6859919913b9cf067..3bf926fa8bf38a78c6a258096aaf3036e0ae3b0c 100644 (file)
@@ -8,12 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::range::RangeArgument;
 use std::fmt::Debug;
 use std::iter::{self, FromIterator};
 use std::slice;
 use std::marker::PhantomData;
-use std::ops::{Index, IndexMut, Range};
+use std::ops::{Index, IndexMut, Range, RangeArgument};
 use std::fmt;
 use std::vec;
 use std::u32;
index d63b4c9c31b5bc8081c76593cd2e927a4d9de09d..0bbda547761cc5fd3cc1246b02a966c618f3422c 100644 (file)
@@ -25,7 +25,6 @@
 #![deny(warnings)]
 
 #![feature(shared)]
-#![feature(collections_range)]
 #![feature(nonzero)]
 #![feature(unboxed_closures)]
 #![feature(fn_traits)]
index 2d25d12d3a96e437ffec77d1a8b655498207ab18..4b71aa6b85f1c91c24f8dd0ea3a19fed0da9bf70 100644 (file)
@@ -47,7 +47,12 @@ fn emit(&mut self, db: &DiagnosticBuilder) {
                // don't display multiline suggestions as labels
                sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
                 let substitution = &sugg.substitution_parts[0].substitutions[0];
-                let msg = format!("help: {} `{}`", sugg.msg, substitution);
+                let msg = if substitution.len() == 0 {
+                    // This substitution is only removal, don't show it
+                    format!("help: {}", sugg.msg)
+                } else {
+                    format!("help: {} `{}`", sugg.msg, substitution)
+                };
                 primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
             } else {
                 // if there are multiple suggestions, print them all in full
index 9800012917c504475cc494efa845d302c6b47f1f..2b33150902532536d219720d89c2034c2efd8e4e 100644 (file)
@@ -684,13 +684,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
         // These may occur in patterns
         // and can maybe contain float literals
         ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
-        // These may occur in patterns
-        // and can't contain float literals
-        ExprKind::Path(..) => (),
-        // If something unhandled is encountered, we need to expand the
-        // search or ignore more ExprKinds.
-        _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
-                       expr.node),
+        // Other kinds of exprs can't occur in patterns so we don't have to check them
+        // (ast_validation will emit an error if they occur)
+        _ => (),
     }
 }
 
@@ -1154,24 +1150,16 @@ fn get_transmute_from_to<'a, 'tcx>
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
-                let typ = cx.tables.node_id_to_type(expr.id);
-                match typ.sty {
-                    ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => {
-                        let from = bare_fn.inputs().skip_binder()[0];
-                        let to = *bare_fn.output().skip_binder();
-                        return Some((&from.sty, &to.sty));
-                    }
-                    _ => (),
-                }
+                let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx);
+                let from = sig.inputs().skip_binder()[0];
+                let to = *sig.output().skip_binder();
+                return Some((&from.sty, &to.sty));
             }
             None
         }
 
         fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
-            match cx.tcx.type_of(def_id).sty {
-                ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (),
-                _ => return false,
-            }
+            cx.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
             cx.tcx.item_name(def_id) == "transmute"
         }
     }
index 32bde42b5261f64b4d6c25ffa0317698bb3d235c..ac3977bd216e7a4587f293ffb4c961635c391766 100644 (file)
@@ -659,7 +659,7 @@ fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
 
     fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
         let def_id = self.cx.tcx.hir.local_def_id(id);
-        let sig = self.cx.tcx.type_of(def_id).fn_sig();
+        let sig = self.cx.tcx.fn_sig(def_id);
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
index c49712086d52c2aff46e5483d7629f275535cbce..502eab44dac52d7c116aa6103b77fae04bc15079 100644 (file)
@@ -106,7 +106,7 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
     closure_kind => { cdata.closure_kind(def_id.index) }
-    closure_type => { cdata.closure_ty(def_id.index, tcx) }
+    fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
index 728ab30bb17dc6a63e1fc649f5a07271a9f60952..3e6d06ec86ff89530f3ca014e92db8f870300997 100644 (file)
@@ -1084,14 +1084,20 @@ pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind {
         }
     }
 
-    pub fn closure_ty(&self,
-                      closure_id: DefIndex,
-                      tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                      -> ty::PolyFnSig<'tcx> {
-        match self.entry(closure_id).kind {
-            EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
+    pub fn fn_sig(&self,
+                  id: DefIndex,
+                  tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                  -> ty::PolyFnSig<'tcx> {
+        let sig = match self.entry(id).kind {
+            EntryKind::Fn(data) |
+            EntryKind::ForeignFn(data) => data.decode(self).sig,
+            EntryKind::Method(data) => data.decode(self).fn_data.sig,
+            EntryKind::Variant(data) |
+            EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(),
+            EntryKind::Closure(data) => data.decode(self).sig,
             _ => bug!(),
-        }
+        };
+        sig.decode((self, tcx))
     }
 
     #[inline]
index 2a504c4c07794ed25114833a5d67895a67befebc..e9701b95002d4dc5d4706ffe6e1c94c29a7051cb 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
                             EncodedMetadata, EncodedMetadataHashes,
                             EncodedMetadataHash};
+use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
 use rustc::ich::Fingerprint;
@@ -499,6 +500,11 @@ fn encode_enum_variant_info(&mut self,
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             struct_ctor: None,
+            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+                Some(self.lazy(&tcx.fn_sig(def_id)))
+            } else {
+                None
+            }
         };
 
         let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap();
@@ -518,7 +524,11 @@ fn encode_enum_variant_info(&mut self,
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -617,6 +627,11 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             struct_ctor: Some(def_id.index),
+            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+                Some(self.lazy(&tcx.fn_sig(def_id)))
+            } else {
+                None
+            }
         };
 
         let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
@@ -641,7 +656,11 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -695,7 +714,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                     };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: arg_names
+                        arg_names: arg_names,
+                        sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -732,7 +752,11 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                 }
             },
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if trait_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -747,6 +771,8 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
+        let tcx = self.tcx;
+
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.hir.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
@@ -768,6 +794,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
                     FnData {
                         constness: sig.constness,
                         arg_names: self.encode_fn_arg_names_for_body(body),
+                        sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -806,7 +833,11 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if impl_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -881,6 +912,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 let data = FnData {
                     constness: constness,
                     arg_names: self.encode_fn_arg_names_for_body(body),
+                    sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
 
                 EntryKind::Fn(self.lazy(&data))
@@ -910,6 +942,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: struct_ctor,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemUnion(..) => {
@@ -920,6 +953,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: None,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemDefaultImpl(..) => {
@@ -1037,7 +1071,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 hir::ItemEnum(..) |
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
-                hir::ItemTrait(..) => self.encode_variances_of(def_id),
+                hir::ItemFn(..) => self.encode_variances_of(def_id),
                 _ => LazySeq::empty(),
             },
             generics: match item.node {
@@ -1175,7 +1209,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
 
         let data = ClosureData {
             kind: tcx.closure_kind(def_id),
-            ty: self.lazy(&tcx.closure_type(def_id)),
+            sig: self.lazy(&tcx.fn_sig(def_id)),
         };
 
         Entry {
@@ -1363,6 +1397,7 @@ fn encode_info_for_foreign_item(&mut self,
                 let data = FnData {
                     constness: hir::Constness::NotConst,
                     arg_names: self.encode_fn_arg_names(names),
+                    sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
                 EntryKind::ForeignFn(self.lazy(&data))
             }
@@ -1381,7 +1416,10 @@ fn encode_info_for_foreign_item(&mut self,
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: match nitem.node {
+                hir::ForeignItemFn(..) => self.encode_variances_of(def_id),
+                _ => LazySeq::empty(),
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
index 1337f90efa74d56c9ff900887e928ef67f8848ee..9ef5b9408303d7f886ad74a3a145e2a872d6665b 100644 (file)
@@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> {
     Type,
     Enum(ReprOptions),
     Field,
-    Variant(Lazy<VariantData>),
-    Struct(Lazy<VariantData>, ReprOptions),
-    Union(Lazy<VariantData>, ReprOptions),
-    Fn(Lazy<FnData>),
-    ForeignFn(Lazy<FnData>),
+    Variant(Lazy<VariantData<'tcx>>),
+    Struct(Lazy<VariantData<'tcx>>, ReprOptions),
+    Union(Lazy<VariantData<'tcx>>, ReprOptions),
+    Fn(Lazy<FnData<'tcx>>),
+    ForeignFn(Lazy<FnData<'tcx>>),
     Mod(Lazy<ModData>),
     MacroDef(Lazy<MacroDef>),
     Closure(Lazy<ClosureData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
     DefaultImpl(Lazy<ImplData<'tcx>>),
-    Method(Lazy<MethodData>),
+    Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
     AssociatedConst(AssociatedContainer, u8),
 }
@@ -439,27 +439,33 @@ pub struct MacroDef {
 impl_stable_hash_for!(struct MacroDef { body, legacy });
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct FnData {
+pub struct FnData<'tcx> {
     pub constness: hir::Constness,
     pub arg_names: LazySeq<ast::Name>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
-impl_stable_hash_for!(struct FnData { constness, arg_names });
+impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct VariantData {
+pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
     pub discr: ty::VariantDiscr,
 
     /// If this is a struct's only variant, this
     /// is the index of the "struct ctor" item.
     pub struct_ctor: Option<DefIndex>,
+
+    /// If this is a tuple struct or variant
+    /// ctor, this is its "function" signature.
+    pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct VariantData {
+impl_stable_hash_for!(struct VariantData<'tcx> {
     ctor_kind,
     discr,
-    struct_ctor
+    struct_ctor,
+    ctor_sig
 });
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -543,16 +549,16 @@ pub fn defaultness(&self) -> hir::Defaultness {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct MethodData {
-    pub fn_data: FnData,
+pub struct MethodData<'tcx> {
+    pub fn_data: FnData<'tcx>,
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
-impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
+impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub kind: ty::ClosureKind,
-    pub ty: Lazy<ty::PolyFnSig<'tcx>>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
-impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });
index b7abc707a380dd8ec2c6058aa2b33cbc4517b372..326c1df69ebebd364c4990d2cadccd097c64985c 100644 (file)
@@ -205,11 +205,14 @@ pub fn into_expr(&mut self,
                 // FIXME(canndrew): This is_never should probably be an is_uninhabited
                 let diverges = expr.ty.is_never();
                 let intrinsic = match ty.sty {
-                    ty::TyFnDef(def_id, _, ref f) if
-                        f.abi() == Abi::RustIntrinsic ||
-                        f.abi() == Abi::PlatformIntrinsic =>
-                    {
-                        Some(this.hir.tcx().item_name(def_id).as_str())
+                    ty::TyFnDef(def_id, _)  => {
+                        let f = ty.fn_sig(this.hir.tcx());
+                        if f.abi() == Abi::RustIntrinsic ||
+                           f.abi() == Abi::PlatformIntrinsic {
+                            Some(this.hir.tcx().item_name(def_id).as_str())
+                        } else {
+                            None
+                        }
                     }
                     _ => None
                 };
index 474feefabbb88dcc12d14967818e0217031e5805..0010f312ef9852e13bfe166f4c0a0c6768fa76cb 100644 (file)
@@ -19,7 +19,6 @@
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::cast::CastKind as TyCastKind;
-use rustc::ty::subst::Subst;
 use rustc::hir;
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
@@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     });
     Expr {
         temp_lifetime: temp_lifetime,
-        ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs),
+        ty: cx.tcx().mk_fn_def(def_id, substs),
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
index 54779cbe30126c9484c1034c8f519691c66cf58d..11ad5d1509d29bcd17b2cd0bb1c541986de4cf31 100644 (file)
@@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             // types in the MIR. They will be substituted again with
             // the param-substs, but because they are concrete, this
             // will not do any harm.
-            let sig = tcx.erase_late_bound_regions(&ty.fn_sig());
+            let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
             let arg_tys = sig.inputs();
 
             build_call_shim(
@@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     } else {
         Substs::identity_for_item(tcx, def_id)
     };
-    let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
-    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let sig = tcx.fn_sig(def_id).subst(tcx, substs);
+    let sig = tcx.erase_late_bound_regions(&sig);
     let span = tcx.def_span(def_id);
 
     let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
@@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             call_kind={:?}, untuple_args={:?})",
            def_id, rcvr_adjustment, call_kind, untuple_args);
 
-    let fn_ty = tcx.type_of(def_id);
-    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let sig = tcx.fn_sig(def_id);
+    let sig = tcx.erase_late_bound_regions(&sig);
     let span = tcx.def_span(def_id);
 
     debug!("build_call_shim: sig={:?}", sig);
@@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
 {
     let tcx = infcx.tcx;
     let def_id = tcx.hir.local_def_id(ctor_id);
-    let sig = match tcx.type_of(def_id).sty {
-        ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
-            .expect("LBR in ADT constructor signature"),
-        _ => bug!("unexpected type for ctor {:?}", def_id)
-    };
+    let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id))
+        .expect("LBR in ADT constructor signature");
     let sig = tcx.erase_regions(&sig);
 
     let (adt_def, substs) = match sig.output().sty {
index e809695c18043e971fb06d55c8f6b6692ab15b9a..eb283df869f127197e6a3948cca892ba9cde32b2 100644 (file)
@@ -67,12 +67,13 @@ fn visit_closure_substs(&mut self,
     }
 
     fn visit_statement(&mut self,
-                       _block: BasicBlock,
+                       block: BasicBlock,
                        statement: &mut Statement<'tcx>,
-                       _location: Location) {
+                       location: Location) {
         if let StatementKind::EndRegion(_) = statement.kind {
             statement.kind = StatementKind::Nop;
         }
+        self.super_statement(block, statement, location);
     }
 }
 
index 0ac35a5fdd4722bd625317bfba4afe3e03643731..5f80c7bee147832ca51ef19283df30b27a76e3f5 100644 (file)
@@ -87,7 +87,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                 let terminator = bb_data.terminator();
                 if let TerminatorKind::Call {
                     func: Operand::Constant(ref f), .. } = terminator.kind {
-                    if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                    if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
                         callsites.push_back(CallSite {
                             callee: callee_def_id,
                             substs: substs,
@@ -131,7 +131,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                     let terminator = bb_data.terminator();
                     if let TerminatorKind::Call {
                         func: Operand::Constant(ref f), .. } = terminator.kind {
-                        if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                        if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
                             // Don't inline the same function multiple times.
                             if callsite.callee != callee_def_id {
                                 callsites.push_back(CallSite {
@@ -270,8 +270,9 @@ fn should_inline(&self,
                 }
 
                 TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
-                    if let ty::TyFnDef(.., f) = f.ty.sty {
+                    if let ty::TyFnDef(def_id, _) = f.ty.sty {
                         // Don't give intrinsics the extra penalty for calls
+                        let f = tcx.fn_sig(def_id);
                         if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
                             cost += INSTR_COST;
                         } else {
index 05a6cdd57ffceed98be29fe1f1ce1fbcfb22dd43..68b687a2e6182c8ba34fddadcfc442e1ded1b03f 100644 (file)
@@ -750,8 +750,8 @@ fn visit_terminator_kind(&mut self,
 
             let fn_ty = func.ty(self.mir, self.tcx);
             let (is_shuffle, is_const_fn) = match fn_ty.sty {
-                ty::TyFnDef(def_id, _, f) => {
-                    (f.abi() == Abi::PlatformIntrinsic &&
+                ty::TyFnDef(def_id, _) => {
+                    (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic &&
                      self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"),
                      self.tcx.is_const_fn(def_id))
                 }
@@ -996,7 +996,7 @@ fn run_pass<'a, 'tcx>(&self,
                                               tcx.require_lang_item(lang_items::SyncTraitLangItem),
                                               cause);
                 if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                    infcx.report_fulfillment_errors(&err);
+                    infcx.report_fulfillment_errors(&err, None);
                 }
             });
         }
index efde39ad6a4c11323dd44b88c964910f2bc39efc..7e6fccf30192ce626dbc072efd9b4948bf41b747 100644 (file)
@@ -462,7 +462,7 @@ fn check_terminator(&mut self,
                 let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.sty {
-                    ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig,
+                    ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx),
                     _ => {
                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
                         return;
index 7c443a4ac7520d0701df6d7a29f61de18074204a..6ad03186dc778136cc8ca6402207cd463cb325da 100644 (file)
@@ -93,6 +93,17 @@ fn no_questions_in_bounds(&self, bounds: &TyParamBounds, where_: &str, is_trait:
             }
         }
     }
+
+    /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
+    fn check_expr_within_pat(&self, expr: &Expr) {
+        match expr.node {
+            ExprKind::Lit(..) | ExprKind::Path(..) => {}
+            ExprKind::Unary(UnOp::Neg, ref inner)
+                if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
+            _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
+                                                         in patterns")
+        }
+    }
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
@@ -308,6 +319,21 @@ fn visit_generics(&mut self, g: &'a Generics) {
         }
         visit::walk_generics(self, g)
     }
+
+    fn visit_pat(&mut self, pat: &'a Pat) {
+        match pat.node {
+            PatKind::Lit(ref expr) => {
+                self.check_expr_within_pat(expr);
+            }
+            PatKind::Range(ref start, ref end, _) => {
+                self.check_expr_within_pat(start);
+                self.check_expr_within_pat(end);
+            }
+            _ => {}
+        }
+
+        visit::walk_pat(self, pat)
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate) {
index fb7258d42662253c012e2e08890af8e59236c773..9eb96fea52778e6677d09a28deacfd1ee99d15fe 100644 (file)
@@ -400,7 +400,13 @@ fn predicates(&mut self) -> &mut Self {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.ev.tcx.type_of(self.item_def_id).visit_with(self);
+        let ty = self.ev.tcx.type_of(self.item_def_id);
+        ty.visit_with(self);
+        if let ty::TyFnDef(def_id, _) = ty.sty {
+            if def_id == self.item_def_id {
+                self.ev.tcx.fn_sig(def_id).visit_with(self);
+            }
+        }
         self
     }
 
@@ -910,7 +916,13 @@ fn predicates(&mut self) -> &mut Self {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.tcx.type_of(self.item_def_id).visit_with(self);
+        let ty = self.tcx.type_of(self.item_def_id);
+        ty.visit_with(self);
+        if let ty::TyFnDef(def_id, _) = ty.sty {
+            if def_id == self.item_def_id {
+                self.tcx.fn_sig(def_id).visit_with(self);
+            }
+        }
         self
     }
 
index 8e14335ceacb9950a2d8ffe9cddc52114db062bc..10b66fb1991087a351150bcc8ec921a8cd7ce349 100644 (file)
@@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         assert!(!item_type.has_erasable_regions());
         hasher.visit_ty(item_type);
 
+        // If this is a function, we hash the signature as well.
+        // This is not *strictly* needed, but it may help in some
+        // situations, see the `run-make/a-b-a-linker-guard` test.
+        if let ty::TyFnDef(..) = item_type.sty {
+            item_type.fn_sig(tcx).visit_with(&mut hasher);
+        }
+
         // also include any type parameters (for generic items)
         if let Some(substs) = substs {
             assert!(!substs.has_erasable_regions());
index d723cf325718ea86de681f451e32c53091ffad08..a76abcf7b49a69ab5e187c19bd9385f6ee344c05 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::Substs;
 use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
@@ -304,6 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         scx.tcx().hir.krate().visit_all_item_likes(&mut visitor);
     }
 
+    // We can only translate items that are instantiable - items all of
+    // whose predicates hold. Luckily, items that aren't instantiable
+    // can't actually be used, so we can just skip translating them.
+    roots.retain(|root| root.is_instantiable(scx.tcx()));
+
     roots
 }
 
@@ -587,7 +592,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                           is_direct_call: bool,
                           output: &mut Vec<TransItem<'tcx>>)
 {
-    if let ty::TyFnDef(def_id, substs, _) = ty.sty {
+    if let ty::TyFnDef(def_id, substs) = ty.sty {
         let instance = monomorphize::resolve(scx, def_id, substs);
         visit_instance_use(scx, instance, is_direct_call, output);
     }
@@ -937,14 +942,9 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
                     let instance =
                         monomorphize::resolve(scx, method.def_id, callee_substs);
 
-                    let predicates = tcx.predicates_of(instance.def_id()).predicates
-                        .subst(tcx, instance.substs);
-                    if !traits::normalize_and_test_predicates(tcx, predicates) {
-                        continue;
-                    }
-
-                    if should_trans_locally(tcx, &instance) {
-                        output.push(create_fn_trans_item(instance));
+                    let trans_item = create_fn_trans_item(instance);
+                    if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) {
+                        output.push(trans_item);
                     }
                 }
             }
index a6f3fb709a01b67f5cc4532f74e4d7809041c005..9b0803908b162582e1dc86bbdc152f4b4f3a4dc5 100644 (file)
@@ -495,12 +495,12 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            -> ty::PolyFnSig<'tcx>
 {
     match ty.sty {
-        ty::TyFnDef(_, _, sig) => sig,
+        ty::TyFnDef(..) |
         // Shims currently have type TyFnPtr. Not sure this should remain.
-        ty::TyFnPtr(sig) => sig,
+        ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
         ty::TyClosure(def_id, substs) => {
             let tcx = ccx.tcx();
-            let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
+            let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
 
             let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
             let env_ty = match tcx.closure_kind(def_id) {
index 95ceec610eaa37894e49b62ccfe4a4fa9810714b..0cc1993601119597c7d2e553f9abd8126a1d70d8 100644 (file)
@@ -488,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     debug!("type_metadata: {:?}", t);
 
-    let sty = &t.sty;
     let ptr_metadata = |ty: Ty<'tcx>| {
         match ty.sty {
             ty::TySlice(typ) => {
@@ -518,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
     };
 
-    let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
+    let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
         ty::TyNever    |
         ty::TyBool     |
         ty::TyChar     |
@@ -557,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 Err(metadata) => return metadata,
             }
         }
-        ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
             let fn_metadata = subroutine_type_metadata(cx,
                                                        unique_type_id,
-                                                       sig,
+                                                       t.fn_sig(cx.tcx()),
                                                        usage_site_span).metadata;
             match debug_context(cx).type_map
                                    .borrow()
@@ -610,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    usage_site_span).finalize(cx)
         }
         _ => {
-            bug!("debuginfo: unexpected type in type_metadata: {:?}", sty)
+            bug!("debuginfo: unexpected type in type_metadata: {:?}", t)
         }
     };
 
index 13ff6646e666256f40772cb96a7d8934e6cb52d7..bfca4fec706eda94267e9779c79320c94d18866a 100644 (file)
@@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 push_type_params(cx, principal.substs, output);
             }
         },
-        ty::TyFnDef(.., sig) |
-        ty::TyFnPtr(sig) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            let sig = t.fn_sig(cx.tcx());
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
index de908bb24a7abb522a1d99f9bd15a557f327188d..9956c28e6412139d2f2fc2fddc106b74b020a104 100644 (file)
@@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
     let ccx = bcx.ccx;
     let tcx = ccx.tcx();
 
-    let (def_id, substs, sig) = match callee_ty.sty {
-        ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig),
+    let (def_id, substs) = match callee_ty.sty {
+        ty::TyFnDef(def_id, substs) => (def_id, substs),
         _ => bug!("expected fn item type, found {}", callee_ty)
     };
 
+    let sig = callee_ty.fn_sig(tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
@@ -986,7 +987,7 @@ macro_rules! require_simd {
 
 
     let tcx = bcx.tcx();
-    let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig());
+    let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
     // every intrinsic takes a SIMD vector as its first argument
index 859c6574787acdba8c39dfca2cd554601557f032..d480f249b4485f2df20dc99918a1f4717e37ecae 100644 (file)
@@ -34,7 +34,6 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
-#![feature(command_envs)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
index 8863c7ffae6f4f38c959059ed0891b728fc75639..16972a1b1ae249a9683776534d2e241de7a85c66 100644 (file)
@@ -404,20 +404,18 @@ fn trans_terminator(&mut self,
                 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
                 let callee = self.trans_operand(&bcx, func);
 
-                let (instance, mut llfn, sig) = match callee.ty.sty {
-                    ty::TyFnDef(def_id, substs, sig) => {
+                let (instance, mut llfn) = match callee.ty.sty {
+                    ty::TyFnDef(def_id, substs) => {
                         (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)),
-                         None,
-                         sig)
+                         None)
                     }
-                    ty::TyFnPtr(sig) => {
-                        (None,
-                         Some(callee.immediate()),
-                         sig)
+                    ty::TyFnPtr(_) => {
+                        (None, Some(callee.immediate()))
                     }
                     _ => bug!("{} is not callable", callee.ty)
                 };
                 let def = instance.map(|i| i.def);
+                let sig = callee.ty.fn_sig(bcx.tcx());
                 let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
                 let abi = sig.abi;
 
index 16ef32ccf5777b7a6c121c3564dd898ecca3de3e..fcb4b25e6fe88d6a8bf6d6f7584ade9bad7ef86c 100644 (file)
@@ -334,7 +334,7 @@ fn trans(&mut self) -> Result<Const<'tcx>, ConstEvalErr<'tcx>> {
                     let fn_ty = func.ty(self.mir, tcx);
                     let fn_ty = self.monomorphize(&fn_ty);
                     let (def_id, substs) = match fn_ty.sty {
-                        ty::TyFnDef(def_id, substs, _) => (def_id, substs),
+                        ty::TyFnDef(def_id, substs) => (def_id, substs),
                         _ => span_bug!(span, "calling {:?} (of type {}) in constant",
                                        func, fn_ty)
                     };
@@ -560,7 +560,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
-                            ty::TyFnDef(def_id, substs, _) => {
+                            ty::TyFnDef(def_id, substs) => {
                                 callee::resolve_and_get_fn(self.ccx, def_id, substs)
                             }
                             _ => {
@@ -579,7 +579,7 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
                                     .find(|it| it.kind == ty::AssociatedKind::Method)
                                     .unwrap().def_id;
                                 // Now create its substs [Closure, Tuple]
-                                let input = tcx.closure_type(def_id)
+                                let input = tcx.fn_sig(def_id)
                                     .subst(tcx, substs.substs).input(0);
                                 let input = tcx.erase_late_bound_regions_and_normalize(&input);
                                 let substs = tcx.mk_substs([operand.ty, input]
index 61e537c9cc0c9488f5e1e85e5a646a2cd214b6c7..4bd5091a4f35f8069ea4225e58a17a3a07916468 100644 (file)
@@ -180,7 +180,7 @@ pub fn trans_rvalue_operand(&mut self,
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
-                            ty::TyFnDef(def_id, substs, _) => {
+                            ty::TyFnDef(def_id, substs) => {
                                 OperandValue::Immediate(
                                     callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
                             }
index d27eeb2b64667b712d8f1939cae832eb3a828dab..1f6a262162d3950021550cba8a44dce92be8777d 100644 (file)
@@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let self_ty = tcx.mk_closure_from_closure_substs(
         closure_did, substs);
 
-    let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs);
+    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
@@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>(
     } else {
         let item_type = def_ty(scx, def_id, substs);
         let def = match item_type.sty {
-            ty::TyFnDef(_, _, f) if
-                f.abi() == Abi::RustIntrinsic ||
-                f.abi() == Abi::PlatformIntrinsic =>
+            ty::TyFnDef(..) if {
+                    let f = item_type.fn_sig(scx.tcx());
+                    f.abi() == Abi::RustIntrinsic ||
+                    f.abi() == Abi::PlatformIntrinsic
+                } =>
             {
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def_id)
index 0dc2bc85e30e63d4722daf3d5eedf2acb812eb34..2a6e7c5ace6cf0a8962960d08015c4f65208a37c 100644 (file)
@@ -25,8 +25,9 @@
 use monomorphize::Instance;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Subst, Substs};
 use syntax::ast::{self, NodeId};
 use syntax::attr;
 use syntax_pos::Span;
@@ -250,6 +251,44 @@ pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Link
         }
     }
 
+    /// Returns whether this instance is instantiable - whether it has no unsatisfied
+    /// predicates.
+    ///
+    /// In order to translate an item, all of its predicates must hold, because
+    /// otherwise the item does not make sense. Type-checking ensures that
+    /// the predicates of every item that is *used by* a valid item *do*
+    /// hold, so we can rely on that.
+    ///
+    /// However, we translate collector roots (reachable items) and functions
+    /// in vtables when they are seen, even if they are not used, and so they
+    /// might not be instantiable. For example, a programmer can define this
+    /// public function:
+    ///
+    ///     pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    ///         <&mut () as Clone>::clone(&s);
+    ///     }
+    ///
+    /// That function can't be translated, because the method `<&mut () as Clone>::clone`
+    /// does not exist. Luckily for us, that function can't ever be used,
+    /// because that would require for `&'a mut (): Clone` to hold, so we
+    /// can just not emit any code, or even a linker reference for it.
+    ///
+    /// Similarly, if a vtable method has such a signature, and therefore can't
+    /// be used, we can just not emit it and have a placeholder (a null pointer,
+    /// which will never be accessed) in its place.
+    pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+        debug!("is_instantiable({:?})", self);
+        let (def_id, substs) = match *self {
+            TransItem::Fn(ref instance) => (instance.def_id(), instance.substs),
+            TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
+            // global asm never has predicates
+            TransItem::GlobalAsm(..) => return true
+        };
+
+        let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs);
+        traits::normalize_and_test_predicates(tcx, predicates)
+    }
+
     pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         let hir_map = &tcx.hir;
 
@@ -401,8 +440,9 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
                         output);
                 }
             },
-            ty::TyFnDef(.., sig) |
-            ty::TyFnPtr(sig) => {
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) => {
+                let sig = t.fn_sig(self.tcx);
                 if sig.unsafety() == hir::Unsafety::Unsafe {
                     output.push_str("unsafe ");
                 }
index bdd8169b84fe7ffcdf58726dee2875c8356fb1c2..68726a7b1c4ebe111a7c53f35cf7ca2d63bd0774 100644 (file)
@@ -619,7 +619,7 @@ fn check_pat_tuple_struct(&self,
         // Type check the path.
         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
         // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig().output();
+        let pat_ty = pat_ty.fn_sig(tcx).output();
         let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type");
         self.demand_eqtype(pat.span, expected, pat_ty);
 
index 385ed7eb0e3842c750999ba88f79f1e0614103ae..a0801a7486654580f86ef2e6a8e5717fba2c6342 100644 (file)
@@ -108,7 +108,7 @@ fn try_overloaded_call_step(&self,
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id).is_none() {
-                    let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs);
+                    let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
                     let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                    infer::FnCall,
                                                                    &closure_ty)
@@ -196,8 +196,8 @@ fn confirm_builtin_call(&self,
                             expected: Expectation<'tcx>)
                             -> Ty<'tcx> {
         let (fn_sig, def_span) = match callee_ty.sty {
-            ty::TyFnDef(def_id, .., sig) => {
-                (sig, self.tcx.hir.span_if_local(def_id))
+            ty::TyFnDef(def_id, _) => {
+                (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
             }
             ty::TyFnPtr(sig) => (sig, None),
             ref t => {
index 91aeade65aa4c2b57a5ffd1f7d263845c769cc69..46d304976dc635b11585a36ba061e301b90b9cba 100644 (file)
 
 use super::{Diverges, FnCtxt};
 
-use lint;
+use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
+use lint;
 use rustc::hir;
+use rustc::session::Session;
 use rustc::traits;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::cast::{CastKind, CastTy};
@@ -112,6 +114,18 @@ enum CastError {
     NonScalar,
 }
 
+fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
+                                              span: Span,
+                                              expr_ty: Ty<'tcx>,
+                                              cast_ty: Ty<'tcx>,
+                                              fcx: &FnCtxt<'a, 'gcx, 'tcx>)
+                                              -> DiagnosticBuilder<'a> {
+    type_error_struct!(sess, span, expr_ty, E0606,
+                       "casting `{}` as `{}` is invalid",
+                       fcx.ty_to_string(expr_ty),
+                       fcx.ty_to_string(cast_ty))
+}
+
 impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
     pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                expr: &'tcx hir::Expr,
@@ -146,14 +160,9 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
             CastError::NeedDeref => {
                 let error_span = self.span;
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 let cast_ty = fcx.ty_to_string(self.cast_ty);
-                let mut err = fcx.type_error_struct(error_span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   cast_ty)
-                                       },
-                                       self.expr_ty);
                 err.span_label(error_span,
                                format!("cannot cast `{}` as `{}`",
                                         fcx.ty_to_string(self.expr_ty),
@@ -166,13 +175,8 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             }
             CastError::NeedViaThinPtr |
             CastError::NeedViaPtr => {
-                let mut err = fcx.type_error_struct(self.span,
-                                                    |actual| {
-                                                        format!("casting `{}` as `{}` is invalid",
-                                                                actual,
-                                                                fcx.ty_to_string(self.cast_ty))
-                                                    },
-                                                    self.expr_ty);
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 if self.cast_ty.is_uint() {
                     err.help(&format!("cast through {} first",
                                       match e {
@@ -184,13 +188,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                 err.emit();
             }
             CastError::NeedViaInt => {
-                fcx.type_error_struct(self.span,
-                                      |actual| {
-                                          format!("casting `{}` as `{}` is invalid",
-                                                  actual,
-                                                  fcx.ty_to_string(self.cast_ty))
-                                      },
-                                      self.expr_ty)
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
                    .help(&format!("cast through {} first",
                                   match e {
                                       CastError::NeedViaInt => "an integer",
@@ -198,6 +196,15 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                                   }))
                    .emit();
             }
+            CastError::IllegalCast => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .emit();
+            }
+            CastError::DifferingKinds => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .note("vtable kinds may not match")
+                    .emit();
+            }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
                     .span_label(self.span, "unsupported cast")
@@ -205,51 +212,23 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                     .emit();
             }
             CastError::CastToChar => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("only `u8` can be cast as `char`, not `{}`",
-                                                   actual)
-                                       },
-                                       self.expr_ty);
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
+                                 "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit();
             }
             CastError::NonScalar => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("non-scalar cast: `{}` as `{}`",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty);
-            }
-            CastError::IllegalCast => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty);
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
+                                 "non-primitive cast: `{}` as `{}`",
+                                 self.expr_ty,
+                                 fcx.ty_to_string(self.cast_ty))
+                                .note("an `as` expression can only be used to convert between \
+                                       primitive types. Consider using the `From` trait")
+                                .emit();
             }
             CastError::SizedUnsizedCast => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("cannot cast thin pointer `{}` to fat pointer \
-                                                    `{}`",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty)
-            }
-            CastError::DifferingKinds => {
-                fcx.type_error_struct(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty)
-                    .note("vtable kinds may not match")
-                    .emit();
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607,
+                                 "cannot cast thin pointer `{}` to fat pointer `{}`",
+                                 self.expr_ty,
+                                 fcx.ty_to_string(self.cast_ty)).emit();
             }
         }
     }
@@ -377,8 +356,9 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError>
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
             // Function item types may need to be reified before casts.
             (None, Some(t_cast)) => {
-                if let ty::TyFnDef(.., f) = self.expr_ty.sty {
+                if let ty::TyFnDef(..) = self.expr_ty.sty {
                     // Attempt a coercion to a fn pointer type.
+                    let f = self.expr_ty.fn_sig(fcx.tcx);
                     let res = fcx.try_coerce(self.expr,
                                              self.expr_ty,
                                              self.expr_diverges,
index 30ac7b4bfb9be8d14a4c069e48c6b81184598324..81aa59e956abf40cb8fca6dc9612caae4fb9ec95 100644 (file)
@@ -210,13 +210,13 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         }
 
         match a.sty {
-            ty::TyFnDef(.., a_f) => {
+            ty::TyFnDef(..) => {
                 // Function items are coercible to any closure
                 // type; function pointers are not (that would
                 // require double indirection).
                 // Additionally, we permit coercion of function
                 // items to drop the unsafe qualifier.
-                self.coerce_from_fn_item(a, a_f, b)
+                self.coerce_from_fn_item(a, b)
             }
             ty::TyFnPtr(a_f) => {
                 // We permit coercion of fn pointers to drop the
@@ -600,7 +600,6 @@ fn coerce_from_fn_pointer(&self,
 
     fn coerce_from_fn_item(&self,
                            a: Ty<'tcx>,
-                           fn_ty_a: ty::PolyFnSig<'tcx>,
                            b: Ty<'tcx>)
                            -> CoerceResult<'tcx> {
         //! Attempts to coerce from the type of a Rust function item
@@ -612,9 +611,17 @@ fn coerce_from_fn_item(&self,
 
         match b.sty {
             ty::TyFnPtr(_) => {
-                let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
-                self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b,
-                    simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))
+                let a_sig = a.fn_sig(self.tcx);
+                let InferOk { value: a_sig, mut obligations } =
+                    self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
+
+                let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
+                let InferOk { value, obligations: o2 } =
+                    self.coerce_from_safe_fn(a_fn_pointer, a_sig, b,
+                        simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?;
+
+                obligations.extend(o2);
+                Ok(InferOk { value, obligations })
             }
             _ => self.unify_and(a, b, identity),
         }
@@ -639,7 +646,7 @@ fn coerce_closure_to_fn(&self,
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
                 //     `fn(arg0,arg1,...) -> _`
-                let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
+                let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
                 let converted_sig = sig.map_bound(|s| {
                     let params_iter = match s.inputs()[0].sty {
                         ty::TyTuple(params, _) => {
@@ -775,42 +782,41 @@ fn try_find_coercion_lub<E>(&self,
 
         // Special-case that coercion alone cannot handle:
         // Two function item types of differing IDs or Substs.
-        match (&prev_ty.sty, &new_ty.sty) {
-            (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
-                // The signature must always match.
-                let fty = self.at(cause, self.param_env)
-                              .trace(prev_ty, new_ty)
-                              .lub(&a_fty, &b_fty)
-                              .map(|ok| self.register_infer_ok_obligations(ok))?;
-
-                if a_def_id == b_def_id {
-                    // Same function, maybe the parameters match.
-                    let substs = self.commit_if_ok(|_| {
-                        self.at(cause, self.param_env)
-                            .trace(prev_ty, new_ty)
-                            .lub(&a_substs, &b_substs)
-                            .map(|ok| self.register_infer_ok_obligations(ok))
-                    });
-
-                    if let Ok(substs) = substs {
-                        // We have a LUB of prev_ty and new_ty, just return it.
-                        return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
-                    }
-                }
+        if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
+            // Don't reify if the function types have a LUB, i.e. they
+            // are the same function and their parameters have a LUB.
+            let lub_ty = self.commit_if_ok(|_| {
+                self.at(cause, self.param_env)
+                    .lub(prev_ty, new_ty)
+                    .map(|ok| self.register_infer_ok_obligations(ok))
+            });
+
+            if lub_ty.is_ok() {
+                // We have a LUB of prev_ty and new_ty, just return it.
+                return lub_ty;
+            }
 
-                // Reify both sides and return the reified fn pointer type.
-                let fn_ptr = self.tcx.mk_fn_ptr(fty);
-                for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
-                    // The only adjustment that can produce an fn item is
-                    // `NeverToAny`, so this should always be valid.
-                    self.apply_adjustments(expr, vec![Adjustment {
-                        kind: Adjust::ReifyFnPointer,
-                        target: fn_ptr
-                    }]);
-                }
-                return Ok(fn_ptr);
+            // The signature must match.
+            let a_sig = prev_ty.fn_sig(self.tcx);
+            let a_sig = self.normalize_associated_types_in(new.span, &a_sig);
+            let b_sig = new_ty.fn_sig(self.tcx);
+            let b_sig = self.normalize_associated_types_in(new.span, &b_sig);
+            let sig = self.at(cause, self.param_env)
+                          .trace(prev_ty, new_ty)
+                          .lub(&a_sig, &b_sig)
+                          .map(|ok| self.register_infer_ok_obligations(ok))?;
+
+            // Reify both sides and return the reified fn pointer type.
+            let fn_ptr = self.tcx.mk_fn_ptr(sig);
+            for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
+                // The only adjustment that can produce an fn item is
+                // `NeverToAny`, so this should always be valid.
+                self.apply_adjustments(expr, vec![Adjustment {
+                    kind: Adjust::ReifyFnPointer,
+                    target: fn_ptr
+                }]);
             }
-            _ => {}
+            return Ok(fn_ptr);
         }
 
         let mut coerce = Coerce::new(self, cause.clone());
@@ -1162,6 +1168,18 @@ fn coerce_inner<'a>(&mut self,
                             "`return;` in a function whose return type is not `()`");
                         db.span_label(cause.span, "return type is not ()");
                     }
+                    ObligationCauseCode::BlockTailExpression(blk_id) => {
+                        db = fcx.report_mismatched_types(cause, expected, found, err);
+
+                        let expr = expression.unwrap_or_else(|| {
+                            span_bug!(cause.span,
+                                      "supposed to be part of a block tail expression, but the \
+                                       expression is empty");
+                        });
+                        fcx.suggest_mismatched_types_on_tail(&mut db, expr,
+                                                             expected, found,
+                                                             cause.span, blk_id);
+                    }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
                     }
index 29742469f84d95d8077c113b0f02df22214bff89..bf134f9547d3817893097baf4148f04abcabd9bc 100644 (file)
@@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Compute skolemized form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let m_sig = |method: &ty::AssociatedItem| {
-            match tcx.type_of(method.def_id).sty {
-                ty::TyFnDef(_, _, f) => f,
-                _ => bug!()
-            }
-        };
-
         let (impl_sig, _) =
             infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
                                                             infer::HigherRankedType,
-                                                            &m_sig(impl_m));
+                                                            &tcx.fn_sig(impl_m.def_id));
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
                                               impl_m_node_id,
@@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         let trait_sig = inh.liberate_late_bound_regions(
             impl_m.def_id,
-            &m_sig(trait_m));
+            &tcx.fn_sig(trait_m.def_id));
         let trait_sig =
             trait_sig.subst(tcx, trait_to_skol_substs);
         let trait_sig =
@@ -335,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return Err(ErrorReported);
         }
 
@@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ty::ImplContainer(_) => impl_trait_ref.self_ty(),
             ty::TraitContainer(_) => tcx.mk_self_type()
         };
-        let method_ty = tcx.type_of(method.def_id);
-        let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder();
+        let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder();
         match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
             ExplicitSelf::ByValue => "self".to_string(),
             ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
@@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 trait_m: &ty::AssociatedItem,
                                                 trait_item_span: Option<Span>)
                                                 -> Result<(), ErrorReported> {
-    let m_fty = |method: &ty::AssociatedItem| {
-        match tcx.type_of(method.def_id).sty {
-            ty::TyFnDef(_, _, f) => f,
-            _ => bug!()
-        }
-    };
-    let impl_m_fty = m_fty(impl_m);
-    let trait_m_fty = m_fty(trait_m);
+    let impl_m_fty = tcx.fn_sig(impl_m.def_id);
+    let trait_m_fty = tcx.fn_sig(trait_m.def_id);
     let trait_number_args = trait_m_fty.inputs().skip_binder().len();
     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
     if trait_number_args != impl_number_args {
@@ -807,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return;
         }
 
index 1b6f96cf65137f3fcda3d25d2822d2a4c7986a6f..f54ad54187267fd6d96ee6f48a22c9de61ad573a 100644 (file)
@@ -73,15 +73,21 @@ pub fn demand_eqtype_with_origin(&self,
         }
     }
 
+    pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
+        if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) {
+            err.emit();
+        }
+    }
+
     // Checks that the type of `expr` can be coerced to `expected`.
     //
     // NB: This code relies on `self.diverges` to be accurate.  In
     // particular, assignments to `!` will be permitted if the
     // diverges flag is currently "always".
-    pub fn demand_coerce(&self,
-                         expr: &hir::Expr,
-                         checked_ty: Ty<'tcx>,
-                         expected: Ty<'tcx>) {
+    pub fn demand_coerce_diag(&self,
+                              expr: &hir::Expr,
+                              checked_ty: Ty<'tcx>,
+                              expected: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
         let expected = self.resolve_type_vars_with_obligations(expected);
 
         if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
@@ -105,8 +111,9 @@ pub fn demand_coerce(&self,
                                       self.get_best_match(&suggestions).join("\n")));
                 }
             }
-            err.emit();
+            return Some(err);
         }
+        None
     }
 
     fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
@@ -143,12 +150,7 @@ fn get_best_match(&self, methods: &[AssociatedItem]) -> Vec<String> {
     fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
         match method.def() {
             Def::Method(def_id) => {
-                match self.tcx.type_of(def_id).sty {
-                    ty::TypeVariants::TyFnDef(_, _, sig) => {
-                        sig.inputs().skip_binder().len() == 1
-                    }
-                    _ => false,
-                }
+                self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1
             }
             _ => false,
         }
index 93057f91997daf2af2b6c2aa952a40fbbf45395d..ed22cd1333e9c58cf5b25ad8a565c341be834eee 100644 (file)
@@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
 
         if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return Err(ErrorReported);
         }
 
index 4d9f50b0fc0c94d6e925c9f94a282a671454ac30..3acfbd1d844038183f92c32ea1b24433e353ed4d 100644 (file)
@@ -13,7 +13,6 @@
 
 use intrinsics;
 use rustc::traits::{ObligationCause, ObligationCauseCode};
-use rustc::ty::subst::Substs;
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::util::nodemap::FxHashMap;
 use require_same_types;
@@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    output: Ty<'tcx>) {
     let def_id = tcx.hir.local_def_id(it.id);
 
-    let substs = Substs::for_item(tcx, def_id,
-                                  |_, _| tcx.types.re_erased,
-                                  |def, _| tcx.mk_param_from_def(def));
+    match it.node {
+        hir::ForeignItemFn(..) => {}
+        _ => {
+            struct_span_err!(tcx.sess, it.span, E0619,
+                             "intrinsic must be a function")
+                .span_label(it.span, "expected a function")
+                .emit();
+            return;
+        }
+    }
 
-    let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
-        inputs.into_iter(),
-        output,
-        false,
-        hir::Unsafety::Unsafe,
-        abi
-    )));
     let i_n_tps = tcx.generics_of(def_id).types.len();
     if i_n_tps != n_tps {
         let span = match it.node {
             hir::ForeignItemFn(_, _, ref generics) => generics.span,
-            hir::ForeignItemStatic(..) => it.span
+            _ => bug!()
         };
 
         struct_span_err!(tcx.sess, span, E0094,
@@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         i_n_tps, n_tps)
             .span_label(span, format!("expected {} type parameter", n_tps))
             .emit();
-    } else {
-        require_same_types(tcx,
-                           &ObligationCause::new(it.span,
-                                                 it.id,
-                                                 ObligationCauseCode::IntrinsicType),
-                           tcx.type_of(def_id),
-                           fty);
+        return;
     }
+
+    let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+        inputs.into_iter(),
+        output,
+        false,
+        hir::Unsafety::Unsafe,
+        abi
+    )));
+    let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
+    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
 }
 
 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
@@ -376,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     let mut structural_to_nomimal = FxHashMap();
 
-                    let sig = tcx.type_of(def_id).fn_sig();
+                    let sig = tcx.fn_sig(def_id);
                     let sig = tcx.no_late_bound_regions(&sig).unwrap();
                     if intr.inputs.len() != sig.inputs().len() {
                         span_err!(tcx.sess, it.span, E0444,
index 36bd665738951ff3c29a47871b72be393771ea83..209245187b13fd8bdc4903f266af7ccde2e051c1 100644 (file)
@@ -375,7 +375,7 @@ fn instantiate_method_sig(&mut self,
 
         debug!("method_predicates after subst = {:?}", method_predicates);
 
-        let sig = self.tcx.type_of(def_id).fn_sig();
+        let sig = self.tcx.fn_sig(def_id);
 
         // Instantiate late-bound regions and substitute the trait
         // parameters into the method type to get the actual method type.
index 73c1215f275fbd8612ba0dbdab7ce4b47cc7be49..4f4169ac93d1b3d98027be9149eb20a868ef72b0 100644 (file)
@@ -235,7 +235,7 @@ pub fn lookup_method_in_trait(&self,
         // NB: Instantiate late-bound regions first so that
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
-        let fn_sig = tcx.type_of(def_id).fn_sig();
+        let fn_sig = tcx.fn_sig(def_id);
         let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
                                                                     infer::FnCall,
                                                                     &fn_sig).0;
index 2518a1739f73e69a85cdee096002de109a09fd01..ee9a347ae95111b299c963ebb98a3ce554fae271 100644 (file)
@@ -673,7 +673,7 @@ pub fn matches_return_type(&self, method: &ty::AssociatedItem,
                                expected: ty::Ty<'tcx>) -> bool {
         match method.def() {
             Def::Method(def_id) => {
-                let fty = self.tcx.type_of(def_id).fn_sig();
+                let fty = self.tcx.fn_sig(def_id);
                 self.probe(|_| {
                     let substs = self.fresh_substs_for_item(self.span, method.def_id);
                     let output = fty.output().subst(self.tcx, substs);
@@ -1288,7 +1288,7 @@ fn xform_method_self_ty(&self,
                             impl_ty: Ty<'tcx>,
                             substs: &Substs<'tcx>)
                             -> Ty<'tcx> {
-        let self_ty = self.tcx.type_of(method).fn_sig().input(0);
+        let self_ty = self.tcx.fn_sig(method).input(0);
         debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
                impl_ty,
                self_ty,
index 2bf24d5b3504c534942e943d13cb2352fefe02bb..34cf1d7f96ba02c04cc10bf49cff479383b7689d 100644 (file)
 
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::map::Node;
 use rustc::hir::{self, PatKind};
 use rustc::middle::lang_items;
 use rustc_back::slice;
@@ -216,6 +217,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// environment is for an item or something where the "callee" is
     /// not clear.
     implicit_region_bound: Option<ty::Region<'tcx>>,
+
+    body_id: Option<hir::BodyId>,
 }
 
 impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@@ -604,6 +607,7 @@ fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self {
             deferred_cast_checks: RefCell::new(Vec::new()),
             anon_types: RefCell::new(NodeMap()),
             implicit_region_bound,
+            body_id,
         }
     }
 
@@ -718,20 +722,12 @@ pub fn provide(providers: &mut Providers) {
         typeck_item_bodies,
         typeck_tables_of,
         has_typeck_tables,
-        closure_type,
         closure_kind,
         adt_destructor,
         ..*providers
     };
 }
 
-fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          def_id: DefId)
-                          -> ty::PolyFnSig<'tcx> {
-    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    tcx.typeck_tables_of(def_id).closure_tys[&node_id]
-}
-
 fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           def_id: DefId)
                           -> ty::ClosureKind {
@@ -844,7 +840,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Inherited::build(tcx, def_id).enter(|inh| {
         let param_env = tcx.param_env(def_id);
         let fcx = if let Some(decl) = fn_decl {
-            let fn_sig = tcx.type_of(def_id).fn_sig();
+            let fn_sig = tcx.fn_sig(def_id);
 
             check_abi(tcx, span, fn_sig.abi());
 
@@ -985,7 +981,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
 
     let ret_ty = fn_sig.output();
-    fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
+    fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType);
     let ret_ty = fcx.instantiate_anon_types(&ret_ty);
     fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
     fn_sig = fcx.tcx.mk_fn_sig(
@@ -1000,16 +996,17 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Add formal parameters.
     for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
-        // The type of the argument must be well-formed.
-        //
-        // NB -- this is now checked in wfcheck, but that
-        // currently only results in warnings, so we issue an
-        // old-style WF obligation here so that we still get the
-        // errors that we used to get.
-        fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
-
         // Check the pattern.
         fcx.check_pat_arg(&arg.pat, arg_ty, true);
+
+        // Check that argument is Sized.
+        // The check for a non-trivial pattern is a hack to avoid duplicate warnings
+        // for simple cases like `fn foo(x: Trait)`,
+        // where we would error once on the parameter as a whole, and once on the binding `x`.
+        if arg.pat.simple_name().is_none() {
+            fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation);
+        }
+
         fcx.write_ty(arg.id, arg_ty);
     }
 
@@ -1908,7 +1905,7 @@ fn instantiate_anon_types<T: TypeFoldable<'tcx>>(&self, value: &T) -> T {
 
                     // Require that the predicate holds for the concrete type.
                     let cause = traits::ObligationCause::new(span, self.body_id,
-                                                             traits::ReturnType);
+                                                             traits::SizedReturnType);
                     self.register_predicate(traits::Obligation::new(cause,
                                                                     self.param_env,
                                                                     predicate));
@@ -1985,17 +1982,6 @@ pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
         }
     }
 
-    /// Registers an obligation for checking later, during regionck, that the type `ty` must
-    /// outlive the region `r`.
-    pub fn register_region_obligation(&self,
-                                      ty: Ty<'tcx>,
-                                      region: ty::Region<'tcx>,
-                                      cause: traits::ObligationCause<'tcx>)
-    {
-        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
-        fulfillment_cx.register_region_obligation(ty, region, cause);
-    }
-
     /// Registers an obligation for checking later, during regionck, that the type `ty` must
     /// outlive the region `r`.
     pub fn register_wf_obligation(&self,
@@ -2010,21 +1996,6 @@ pub fn register_wf_obligation(&self,
                                                         ty::Predicate::WellFormed(ty)));
     }
 
-    pub fn register_old_wf_obligation(&self,
-                                      ty: Ty<'tcx>,
-                                      span: Span,
-                                      code: traits::ObligationCauseCode<'tcx>)
-    {
-        // Registers an "old-style" WF obligation that uses the
-        // implicator code.  This is basically a buggy version of
-        // `register_wf_obligation` that is being kept around
-        // temporarily just to help with phasing in the newer rules.
-        //
-        // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
-        let cause = traits::ObligationCause::new(span, self.body_id, code);
-        self.register_region_obligation(ty, self.tcx.types.re_empty, cause);
-    }
-
     /// Registers obligations that all types appearing in `substs` are well-formed.
     pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
     {
@@ -2152,7 +2123,7 @@ fn select_all_obligations_or_error(&self) {
 
         match fulfillment_cx.select_all_or_error(self) {
             Ok(()) => { }
-            Err(errors) => { self.report_fulfillment_errors(&errors); }
+            Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
         }
     }
 
@@ -2160,7 +2131,7 @@ fn select_all_obligations_or_error(&self) {
     fn select_obligations_where_possible(&self) {
         match self.fulfillment_cx.borrow_mut().select_where_possible(self) {
             Ok(()) => { }
-            Err(errors) => { self.report_fulfillment_errors(&errors); }
+            Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
         }
     }
 
@@ -2173,7 +2144,6 @@ fn make_overloaded_lvalue_return_type(&self,
                                           -> ty::TypeAndMut<'tcx>
     {
         // extract method return type, which will be &T;
-        // all LB regions should have been instantiated during method lookup
         let ret_ty = method.sig.output();
 
         // method returns &T, but the type as visible to user is T, so deref
@@ -2580,8 +2550,8 @@ fn variadic_error<'tcx>(s: &Session, span: Span, t: Ty<'tcx>, cast_ty: &str) {
                     ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
                     }
-                    ty::TyFnDef(.., f) => {
-                        let ptr_ty = self.tcx.mk_fn_ptr(f);
+                    ty::TyFnDef(..) => {
+                        let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
                         let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
                         variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
                     }
@@ -2848,10 +2818,11 @@ fn check_return_expr(&self, return_expr: &'gcx hir::Expr) {
                                              "check_return_expr called outside fn body"));
 
         let ret_ty = ret_coercion.borrow().expected_ty();
-        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
+        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone());
         ret_coercion.borrow_mut()
                     .coerce(self,
-                            &self.misc(return_expr.span),
+                            &self.cause(return_expr.span,
+                                        ObligationCauseCode::ReturnType(return_expr.id)),
                             return_expr,
                             return_expr_ty,
                             self.diverges.get());
@@ -4170,8 +4141,10 @@ fn check_block_with_expected(&self,
             let mut coerce = ctxt.coerce.as_mut().unwrap();
             if let Some(tail_expr_ty) = tail_expr_ty {
                 let tail_expr = tail_expr.unwrap();
+                let cause = self.cause(tail_expr.span,
+                                       ObligationCauseCode::BlockTailExpression(blk.id));
                 coerce.coerce(self,
-                              &self.misc(tail_expr.span),
+                              &cause,
                               tail_expr,
                               tail_expr_ty,
                               self.diverges.get());
@@ -4210,6 +4183,130 @@ fn check_block_with_expected(&self,
         ty
     }
 
+    /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
+    /// `fn main` if it is a method, `None` otherwise.
+    pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
+        // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
+        // `while` before reaching it, as block tail returns are not available in them.
+        if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) {
+            let parent = self.tcx.hir.get(fn_id);
+
+            if let Node::NodeItem(&hir::Item {
+                name, node: hir::ItemFn(ref decl, ..), ..
+            }) = parent {
+                decl.clone().and_then(|decl| {
+                    // This is less than ideal, it will not present the return type span on any
+                    // method called `main`, regardless of whether it is actually the entry point.
+                    Some((decl, name == Symbol::intern("main")))
+                })
+            } else if let Node::NodeTraitItem(&hir::TraitItem {
+                node: hir::TraitItemKind::Method(hir::MethodSig {
+                    ref decl, ..
+                }, ..), ..
+            }) = parent {
+                decl.clone().and_then(|decl| {
+                    Some((decl, false))
+                })
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    /// On implicit return expressions with mismatched types, provide the following suggestions:
+    ///
+    ///  - Point out the method's return type as the reason for the expected type
+    ///  - Possible missing semicolon
+    ///  - Possible missing return type if the return type is the default, and not `fn main()`
+    pub fn suggest_mismatched_types_on_tail(&self,
+                                            err: &mut DiagnosticBuilder<'tcx>,
+                                            expression: &'gcx hir::Expr,
+                                            expected: Ty<'tcx>,
+                                            found: Ty<'tcx>,
+                                            cause_span: Span,
+                                            blk_id: ast::NodeId) {
+        self.suggest_missing_semicolon(err, expression, expected, cause_span);
+
+        if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) {
+            // `fn main()` must return `()`, do not suggest changing return type
+            if !is_main {
+                self.suggest_missing_return_type(err, &fn_decl, found);
+            }
+        }
+    }
+
+    /// A common error is to forget to add a semicolon at the end of a block:
+    ///
+    /// ```
+    /// fn foo() {
+    ///     bar_that_returns_u32()
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the return expression in a block would make sense on its own as a
+    /// statement and the return type has been left as defaultor has been specified as `()`. If so,
+    /// it suggests adding a semicolon.
+    fn suggest_missing_semicolon(&self,
+                                     err: &mut DiagnosticBuilder<'tcx>,
+                                     expression: &'gcx hir::Expr,
+                                     expected: Ty<'tcx>,
+                                     cause_span: Span) {
+        if expected.is_nil() {
+            // `BlockTailExpression` only relevant if the tail expr would be
+            // useful on its own.
+            match expression.node {
+                hir::ExprCall(..) |
+                hir::ExprMethodCall(..) |
+                hir::ExprIf(..) |
+                hir::ExprWhile(..) |
+                hir::ExprLoop(..) |
+                hir::ExprMatch(..) |
+                hir::ExprBlock(..) => {
+                    let sp = cause_span.next_point();
+                    err.span_suggestion(sp,
+                                        "did you mean to add a semicolon here?",
+                                        ";".to_string());
+                }
+                _ => (),
+            }
+        }
+    }
+
+
+    /// A possible error is to forget to add a return type that is needed:
+    ///
+    /// ```
+    /// fn foo() {
+    ///     bar_that_returns_u32()
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the return type is left as default, the method is not part of an
+    /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
+    /// type.
+    fn suggest_missing_return_type(&self,
+                                   err: &mut DiagnosticBuilder<'tcx>,
+                                   fn_decl: &hir::FnDecl,
+                                   ty: Ty<'tcx>) {
+
+        // Only recommend changing the return type for methods that
+        // haven't set a return type at all (and aren't `fn main()` or an impl).
+        if let &hir::FnDecl {
+            output: hir::FunctionRetTy::DefaultReturn(span), ..
+        } = fn_decl {
+            if ty.is_suggestable() {
+                err.span_suggestion(span,
+                                    "possibly return type missing here?",
+                                    format!("-> {} ", ty));
+            } else {
+                err.span_label(span, "possibly return type missing here?");
+            }
+        }
+    }
+
+
     /// A common error is to add an extra semicolon:
     ///
     /// ```
@@ -4245,7 +4342,7 @@ fn consider_hint_about_removing_semicolon(&self,
             hi: original_span.hi,
             ctxt: original_span.ctxt,
         };
-        err.span_help(span_semi, "consider removing this semicolon:");
+        err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
     }
 
     // Instantiates the given path, which must refer to an item with the given
index 26f708e934562ba704458f0c361e4dd7d81eda8f..cbda1227742ca32d5756e27344e204cd02736915 100644 (file)
@@ -177,12 +177,11 @@ fn check_associated_item(&mut self,
                 }
                 ty::AssociatedKind::Method => {
                     reject_shadowing_type_parameters(fcx.tcx, item.def_id);
-                    let method_ty = fcx.tcx.type_of(item.def_id);
-                    let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+                    let sig = fcx.tcx.fn_sig(item.def_id);
+                    let sig = fcx.normalize_associated_types_in(span, &sig);
                     let predicates = fcx.tcx.predicates_of(item.def_id)
                         .instantiate_identity(fcx.tcx);
                     let predicates = fcx.normalize_associated_types_in(span, &predicates);
-                    let sig = method_ty.fn_sig();
                     this.check_fn_or_method(fcx, span, sig, &predicates,
                                             item.def_id, &mut implied_bounds);
                     let sig_if_method = sig_if_method.expect("bad signature for method");
@@ -331,9 +330,8 @@ fn check_trait(&mut self, item: &hir::Item) {
     fn check_item_fn(&mut self, item: &hir::Item) {
         self.for_item(item).with_fcx(|fcx, this| {
             let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let ty = fcx.tcx.type_of(def_id);
-            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
-            let sig = item_ty.fn_sig();
+            let sig = fcx.tcx.fn_sig(def_id);
+            let sig = fcx.normalize_associated_types_in(item.span, &sig);
 
             let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
             let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
@@ -461,9 +459,9 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
 
         let span = method_sig.decl.inputs[0].span;
 
-        let method_ty = fcx.tcx.type_of(method.def_id);
-        let fty = fcx.normalize_associated_types_in(span, &method_ty);
-        let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
+        let sig = fcx.tcx.fn_sig(method.def_id);
+        let sig = fcx.normalize_associated_types_in(span, &sig);
+        let sig = fcx.liberate_late_bound_regions(method.def_id, &sig);
 
         debug!("check_method_receiver: sig={:?}", sig);
 
index 4af262bcb78df67b9b5687379e155189ecb0ee4b..81e5dae5477ebcf8df619c8790364c43127f86c4 100644 (file)
@@ -377,7 +377,7 @@ fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>, span: &'cx Locatable, body: &'gcx hir:
 
     fn report_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
-            self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t);
+            self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t);
         }
     }
 }
index ccbc02990418f2b89088f5b1d20c7ae891de25e5..9305eff1436520e7b3ee0bebf1c2e21c4e105198 100644 (file)
@@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Check that all transitive obligations are satisfied.
         if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&errors);
+            infcx.report_fulfillment_errors(&errors, None);
         }
 
         // Finally, resolve all regions.
index fb3bcd31e21fcbaffe0dbcf0bca3cd3a9a34f315..fd6dda5ccf4a72e9c81be10c6bef8beec7c4f7ca 100644 (file)
@@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) {
         type_param_predicates,
         trait_def,
         adt_def,
+        fn_sig,
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
@@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
                 tcx.generics_of(def_id);
                 tcx.type_of(def_id);
                 tcx.predicates_of(def_id);
+                if let hir::ForeignItemFn(..) = item.node {
+                    tcx.fn_sig(def_id);
+                }
             }
         }
         hir::ItemEnum(ref enum_definition, _) => {
@@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.predicates_of(def_id);
+            if let hir::ItemFn(..) = it.node {
+                tcx.fn_sig(def_id);
+            }
         }
     }
 }
@@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast:
         hir::TraitItemKind::Type(_, Some(_)) |
         hir::TraitItemKind::Method(..) => {
             tcx.type_of(def_id);
+            if let hir::TraitItemKind::Method(..) = trait_item.node {
+                tcx.fn_sig(def_id);
+            }
         }
 
         hir::TraitItemKind::Type(_, None) => {}
@@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
     tcx.predicates_of(def_id);
+    if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node {
+        tcx.fn_sig(def_id);
+    }
 }
 
 fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match tcx.hir.get(node_id) {
         NodeTraitItem(item) => {
             match item.node {
-                TraitItemKind::Method(ref sig, _) => {
-                    let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+                TraitItemKind::Method(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, fty)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 TraitItemKind::Const(ref ty, _) |
                 TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
@@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         NodeImplItem(item) => {
             match item.node {
-                ImplItemKind::Method(ref sig, _) => {
-                    let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+                ImplItemKind::Method(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, fty)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
                 ImplItemKind::Type(ref ty) => {
@@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemTy(ref t, _) | ItemImpl(.., ref t, _) => {
                     icx.to_ty(t)
                 }
-                ItemFn(ref decl, unsafety, _, abi, _, _) => {
-                    let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl);
+                ItemFn(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, tofd)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ItemEnum(..) |
                 ItemStruct(..) |
@@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
 
         NodeForeignItem(foreign_item) => {
-            let abi = tcx.hir.get_foreign_abi(node_id);
-
             match foreign_item.node {
-                ForeignItemFn(ref fn_decl, _, _) => {
-                    compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+                ForeignItemFn(..) => {
+                    let substs = Substs::identity_for_item(tcx, def_id);
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ForeignItemStatic(ref t, _) => icx.to_ty(t)
             }
@@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         NodeStructCtor(&ref def) |
         NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => {
-            let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
             match *def {
-                VariantData::Unit(..) | VariantData::Struct(..) => ty,
-                VariantData::Tuple(ref fields, _) => {
-                    let inputs = fields.iter().map(|f| {
-                        tcx.type_of(tcx.hir.local_def_id(f.id))
-                    });
+                VariantData::Unit(..) | VariantData::Struct(..) => {
+                    tcx.type_of(tcx.hir.get_parent_did(node_id))
+                }
+                VariantData::Tuple(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
-                        inputs,
-                        ty,
-                        false,
-                        hir::Unsafety::Normal,
-                        abi::Abi::Rust
-                    )))
+                    tcx.mk_fn_def(def_id, substs)
                 }
             }
         }
@@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    def_id: DefId)
+                    -> ty::PolyFnSig<'tcx> {
+    use rustc::hir::map::*;
+    use rustc::hir::*;
+
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+
+    let icx = ItemCtxt::new(tcx, def_id);
+
+    match tcx.hir.get(node_id) {
+        NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) |
+        NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => {
+            AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl)
+        }
+
+        NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => {
+            AstConv::ty_of_fn(&icx, unsafety, abi, decl)
+        }
+
+        NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => {
+            let abi = tcx.hir.get_foreign_abi(node_id);
+            compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+        }
+
+        NodeStructCtor(&VariantData::Tuple(ref fields, _)) |
+        NodeVariant(&Spanned { node: hir::Variant_ {
+            data: VariantData::Tuple(ref fields, _), ..
+        }, .. }) => {
+            let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
+            let inputs = fields.iter().map(|f| {
+                tcx.type_of(tcx.hir.local_def_id(f.id))
+            });
+            ty::Binder(tcx.mk_fn_sig(
+                inputs,
+                ty,
+                false,
+                hir::Unsafety::Normal,
+                abi::Abi::Rust
+            ))
+        }
+
+        NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
+            tcx.typeck_tables_of(def_id).closure_tys[&node_id]
+        }
+
+        x => {
+            bug!("unexpected sort of node in fn_sig(): {:?}", x);
+        }
+    }
+}
+
 fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             def_id: DefId)
                             -> Option<ty::TraitRef<'tcx>> {
@@ -1502,12 +1555,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
+fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
     decl: &hir::FnDecl,
     abi: abi::Abi)
-    -> Ty<'tcx>
+    -> ty::PolyFnSig<'tcx>
 {
     let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl);
 
@@ -1533,8 +1586,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
         }
     }
 
-    let substs = Substs::identity_for_item(tcx, def_id);
-    tcx.mk_fn_def(def_id, substs, fty)
+    fty
 }
 
 fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index bc5ba4c323dc1576c9a933141c161e091368f35d..bf5adc8644d516af15cf2cb71c802e7c9d7d28c2 100644 (file)
@@ -4208,6 +4208,104 @@ trait was performed.
 ```
 "##,
 
+E0604: r##"
+A cast to `char` was attempted on a type other than `u8`.
+
+Erroneous code example:
+
+```compile_fail,E0604
+0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
+```
+
+As the error message indicates, only `u8` can be cast into `char`. Example:
+
+```
+let c = 86u8 as char; // ok!
+assert_eq!(c, 'V');
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0605: r##"
+An invalid cast was attempted.
+
+Erroneous code examples:
+
+```compile_fail,E0605
+let x = 0u8;
+x as Vec<u8>; // error: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+
+// Another example
+
+let v = 0 as *const u8; // So here, `v` is a `*const u8`.
+v as &u8; // error: non-primitive cast: `*const u8` as `&u8`
+```
+
+Only primitive types can be cast into each other. Examples:
+
+```
+let x = 0u8;
+x as u32; // ok!
+
+let v = 0 as *const u8;
+v as *const i8; // ok!
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0606: r##"
+An incompatible cast was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0606
+let x = &0u8; // Here, `x` is a `&u8`.
+let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
+```
+
+When casting, keep in mind that only primitive types can be cast into each
+other. Example:
+
+```
+let x = &0u8;
+let y: u32 = *x as u32; // We dereference it first and then cast it.
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0607: r##"
+A cast between a thin and a fat pointer was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0607
+let v = 0 as *const u8;
+v as *const [u8];
+```
+
+First: what are thin and fat pointers?
+
+Thin pointers are "simple" pointers: they are purely a reference to a memory
+address.
+
+Fat pointers are pointers referencing Dynamically Sized Types (also called DST).
+DST don't have a statically known size, therefore they can only exist behind
+some kind of pointers that contain additional information. Slices and trait
+objects are DSTs. In the case of slices, the additional information the fat
+pointer holds is their size.
+
+To fix this error, don't try to cast directly between thin and fat pointers.
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
 E0609: r##"
 Attempted to access a non-existent field in a struct.
 
@@ -4638,4 +4736,5 @@ fn i_am_a_function() {}
     E0568, // auto-traits can not have predicates,
     E0588, // packed struct cannot transitively contain a `[repr(align)]` struct
     E0592, // duplicate definitions with name `{}`
+    E0619, // intrinsic must be a function
 }
index 9e99af633d517579ee64c07c23de9745a1e95f6c..2857b5fb5e05e3c7c61ef9c5e3eeac07680ca29e 100644 (file)
@@ -166,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match fulfill_cx.select_all_or_error(infcx) {
             Ok(()) => true,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors);
+                infcx.report_fulfillment_errors(&errors, None);
                 false
             }
         }
@@ -198,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
                 _ => ()
             }
-            let substs = tcx.intern_substs(&[]);
-            let se_ty = tcx.mk_fn_def(main_def_id, substs,
-                ty::Binder(tcx.mk_fn_sig(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+                tcx.mk_fn_sig(
                     iter::empty(),
                     tcx.mk_nil(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust
-                ))
-            );
+                )
+            ));
 
             require_same_types(
                 tcx,
                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
                 se_ty,
-                main_t);
+                tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
         }
         _ => {
             span_bug!(main_span,
@@ -248,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => ()
             }
 
-            let substs = tcx.intern_substs(&[]);
-            let se_ty = tcx.mk_fn_def(start_def_id, substs,
-                ty::Binder(tcx.mk_fn_sig(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+                tcx.mk_fn_sig(
                     [
                         tcx.types.isize,
                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
@@ -259,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust
-                ))
-            );
+                )
+            ));
 
             require_same_types(
                 tcx,
                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
                 se_ty,
-                start_t);
+                tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
         }
         _ => {
             span_bug!(start_span,
index c434edb1c31ab38c595c47559a54d2cba187db45..f4963619370e41ef2b1cc8f6e746b00596f62ace 100644 (file)
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use middle::resolve_lifetime as rl;
 use rustc::dep_graph::{AssertDepGraphSafe, DepKind};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::hir::map as hir_map;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -61,10 +59,10 @@ pub struct Constraint<'a> {
 ///     }
 ///
 /// then while we are visiting `Bar<T>`, the `CurrentItem` would have
-/// the def-id and generics of `Foo`.
-pub struct CurrentItem<'a> {
+/// the def-id and the start of `Foo`'s inferreds.
+pub struct CurrentItem {
     def_id: DefId,
-    generics: &'a ty::Generics,
+    inferred_start: InferredIndex,
 }
 
 pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
@@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
+        match item.node {
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.visit_node_helper(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.visit_node_helper(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.visit_node_helper(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.visit_node_helper(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.visit_node_helper(item.id);
+            }
+
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.visit_node_helper(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.visit_node_helper(trait_item.id);
+        }
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.visit_node_helper(impl_item.id);
+        }
+    }
+}
+
+impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
+    fn visit_node_helper(&mut self, id: ast::NodeId) {
         let tcx = self.terms_cx.tcx;
-        let def_id = tcx.hir.local_def_id(item.id);
+        let def_id = tcx.hir.local_def_id(id);
 
         // Encapsulate constructing the constraints into a task we can
         // reference later. This can go away once the red-green
@@ -100,20 +149,11 @@ fn visit_item(&mut self, item: &hir::Item) {
         //
         // See README.md for a detailed discussion
         // on dep-graph management.
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                tcx.dep_graph.with_task(dep_node,
-                                        AssertDepGraphSafe(self),
-                                        def_id,
-                                        visit_item_task);
-            }
-            _ => {
-                // Nothing to do here, skip the task.
-            }
-        }
+        let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+        tcx.dep_graph.with_task(dep_node,
+                                AssertDepGraphSafe(self),
+                                def_id,
+                                visit_item_task);
 
         fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>,
                                      def_id: DefId)
@@ -122,197 +162,57 @@ fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a,
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-/// Is `param_id` a lifetime according to `map`?
-fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
-    match map.find(param_id) {
-        Some(hir_map::NodeLifetime(..)) => true,
-        _ => false,
-    }
-}
-
-impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.terms_cx.tcx
     }
 
     fn build_constraints_for_item(&mut self, def_id: DefId) {
         let tcx = self.tcx();
-        let id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-        let item = tcx.hir.expect_item(id);
-        debug!("visit_item item={}", tcx.hir.node_to_string(item.id));
+        debug!("build_constraints_for_item({})", tcx.item_path_str(def_id));
 
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let generics = tcx.generics_of(def_id);
-                let current_item = &CurrentItem { def_id, generics };
+        // Skip items with no generics - there's nothing to infer in them.
+        if tcx.generics_of(def_id).count() == 0 {
+            return;
+        }
 
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
+        let inferred_start = self.terms_cx.inferred_starts[&id];
+        let current_item = &CurrentItem { def_id, inferred_start };
+        match tcx.type_of(def_id).sty {
+            ty::TyAdt(def, _) => {
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
                 // in comment at top of module.
                 //
                 // self.add_constraints_from_generics(generics);
 
-                for field in tcx.adt_def(def_id).all_fields() {
+                for field in def.all_fields() {
                     self.add_constraints_from_ty(current_item,
                                                  tcx.type_of(field.did),
                                                  self.covariant);
                 }
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) |
-            hir::ItemImpl(..) |
-            hir::ItemDefaultImpl(..) => {
-                span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def");
+            ty::TyFnDef(..) => {
+                self.add_constraints_from_sig(current_item,
+                                              tcx.fn_sig(def_id),
+                                              self.covariant);
             }
-        }
-    }
-
-    /// Load the generics for another item, adding a corresponding
-    /// relation into the dependencies to indicate that the variance
-    /// for `current` relies on `def_id`.
-    fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics {
-        let generics = self.tcx().generics_of(def_id);
-        if self.tcx().dep_graph.is_fully_enabled() {
-            self.dependencies.add(current.def_id, def_id);
-        }
-        generics
-    }
 
-    fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> {
-        self.terms_cx.inferred_map.get(&param_id)
-    }
-
-    fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
-        let tcx = self.terms_cx.tcx;
-        assert!(is_lifetime(&tcx.hir, param_id));
-        match tcx.named_region_map.defs.get(&param_id) {
-            Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id,
-            Some(_) => bug!("should not encounter non early-bound cases"),
-
-            // The lookup should only fail when `param_id` is
-            // itself a lifetime binding: use it as the decl_id.
-            None => param_id,
-        }
-
-    }
-
-    /// Is `param_id` a type parameter for which we infer variance?
-    fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
-        let result = self.terms_cx.inferred_map.contains_key(&param_id);
-
-        // To safe-guard against invalid inferred_map constructions,
-        // double-check if variance is inferred at some use of a type
-        // parameter (by inspecting parent of its binding declaration
-        // to see if it is introduced by a type or by a fn/impl).
-
-        let check_result = |this: &ConstraintContext| -> bool {
-            let tcx = this.terms_cx.tcx;
-            let decl_id = this.find_binding_for_lifetime(param_id);
-            // Currently only called on lifetimes; double-checking that.
-            assert!(is_lifetime(&tcx.hir, param_id));
-            let parent_id = tcx.hir.get_parent(decl_id);
-            let parent = tcx.hir
-                .find(parent_id)
-                .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id));
-
-            let is_inferred;
-            macro_rules! cannot_happen { () => { {
-                bug!("invalid parent: {} for {}",
-                     tcx.hir.node_to_string(parent_id),
-                     tcx.hir.node_to_string(param_id));
-            } } }
-
-            match parent {
-                hir_map::NodeItem(p) => {
-                    match p.node {
-                        hir::ItemTy(..) |
-                        hir::ItemEnum(..) |
-                        hir::ItemStruct(..) |
-                        hir::ItemUnion(..) |
-                        hir::ItemTrait(..) => is_inferred = true,
-                        hir::ItemFn(..) => is_inferred = false,
-                        _ => cannot_happen!(),
-                    }
-                }
-                hir_map::NodeTraitItem(..) => is_inferred = false,
-                hir_map::NodeImplItem(..) => is_inferred = false,
-                _ => cannot_happen!(),
-            }
-
-            return is_inferred;
-        };
-
-        assert_eq!(result, check_result(self));
-
-        return result;
-    }
-
-    /// Returns a variance term representing the declared variance of the type/region parameter
-    /// with the given id.
-    fn declared_variance(&self,
-                         param_def_id: DefId,
-                         item_def_id: DefId,
-                         index: usize)
-                         -> VarianceTermPtr<'a> {
-        assert_eq!(param_def_id.krate, item_def_id.krate);
-
-        if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) {
-            // Parameter on an item defined within current crate:
-            // variance not yet inferred, so return a symbolic
-            // variance.
-            if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) {
-                self.terms_cx.inferred_infos[index].term
-            } else {
-                // If there is no inferred entry for a type parameter,
-                // it must be declared on a (locally defiend) trait -- they don't
-                // get inferreds because they are always invariant.
-                if cfg!(debug_assertions) {
-                    let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap();
-                    let item = self.tcx().hir.expect_item(item_node_id);
-                    let success = match item.node {
-                        hir::ItemTrait(..) => true,
-                        _ => false,
-                    };
-                    if !success {
-                        bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}",
-                             item_def_id,
-                             item);
-                    }
-                }
-                self.invariant
+            _ => {
+                span_bug!(tcx.def_span(def_id),
+                          "`build_constraints_for_item` unsupported for this item");
             }
-        } else {
-            // Parameter on an item defined within another crate:
-            // variance already inferred, just look it up.
-            let variances = self.tcx().variances_of(item_def_id);
-            self.constant_term(variances[index])
         }
     }
 
     fn add_constraint(&mut self,
-                      InferredIndex(index): InferredIndex,
+                      current: &CurrentItem,
+                      index: u32,
                       variance: VarianceTermPtr<'a>) {
         debug!("add_constraint(index={}, variance={:?})", index, variance);
         self.constraints.push(Constraint {
-            inferred: InferredIndex(index),
+            inferred: InferredIndex(current.inferred_start.0 + index as usize),
             variance: variance,
         });
     }
@@ -354,15 +254,26 @@ fn add_constraints_from_trait_ref(&mut self,
         debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
                trait_ref,
                variance);
+        self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance);
+    }
 
-        let trait_generics = self.tcx().generics_of(trait_ref.def_id);
+    fn add_constraints_from_invariant_substs(&mut self,
+                                             current: &CurrentItem,
+                                             substs: &Substs<'tcx>,
+                                             variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}",
+               substs,
+               variance);
 
-        self.add_constraints_from_substs(current,
-                                         trait_ref.def_id,
-                                         &trait_generics.types,
-                                         &trait_generics.regions,
-                                         trait_ref.substs,
-                                         variance);
+        // Trait are always invariant so we can take advantage of that.
+        let variance_i = self.invariant(variance);
+        for ty in substs.types() {
+            self.add_constraints_from_ty(current, ty, variance_i);
+        }
+
+        for region in substs.regions() {
+            self.add_constraints_from_region(current, region, variance_i);
+        }
     }
 
     /// Adds constraints appropriate for an instance of `ty` appearing
@@ -382,8 +293,8 @@ fn add_constraints_from_ty(&mut self,
                 // leaf type -- noop
             }
 
-            ty::TyClosure(..) |
-            ty::TyAnon(..) => {
+            ty::TyFnDef(..) |
+            ty::TyClosure(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
@@ -409,26 +320,15 @@ fn add_constraints_from_ty(&mut self,
             }
 
             ty::TyAdt(def, substs) => {
-                let adt_generics = self.read_generics(current, def.did);
-
-                self.add_constraints_from_substs(current,
-                                                 def.did,
-                                                 &adt_generics.types,
-                                                 &adt_generics.regions,
-                                                 substs,
-                                                 variance);
+                self.add_constraints_from_substs(current, def.did, substs, variance);
             }
 
             ty::TyProjection(ref data) => {
-                let trait_ref = &data.trait_ref;
-                let trait_generics = self.tcx().generics_of(trait_ref.def_id);
-
-                self.add_constraints_from_substs(current,
-                                                 trait_ref.def_id,
-                                                 &trait_generics.types,
-                                                 &trait_generics.regions,
-                                                 trait_ref.substs,
-                                                 variance);
+                self.add_constraints_from_trait_ref(current, data.trait_ref, variance);
+            }
+
+            ty::TyAnon(_, substs) => {
+                self.add_constraints_from_invariant_substs(current, substs, variance);
             }
 
             ty::TyDynamic(ref data, r) => {
@@ -447,26 +347,9 @@ fn add_constraints_from_ty(&mut self,
             }
 
             ty::TyParam(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let mut i = data.idx as usize;
-                if !current.generics.has_self || i > 0 {
-                    i -= current.generics.regions.len();
-                }
-                let def_id = current.generics.types[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                match self.terms_cx.inferred_map.get(&node_id) {
-                    Some(&index) => {
-                        self.add_constraint(index, variance);
-                    }
-                    None => {
-                        // We do not infer variance for type parameters
-                        // declared on methods. They will not be present
-                        // in the inferred_map.
-                    }
-                }
+                self.add_constraint(current, data.idx, variance);
             }
 
-            ty::TyFnDef(.., sig) |
             ty::TyFnPtr(sig) => {
                 self.add_constraints_from_sig(current, sig, variance);
             }
@@ -489,8 +372,6 @@ fn add_constraints_from_ty(&mut self,
     fn add_constraints_from_substs(&mut self,
                                    current: &CurrentItem,
                                    def_id: DefId,
-                                   type_param_defs: &[ty::TypeParameterDef],
-                                   region_param_defs: &[ty::RegionParameterDef],
                                    substs: &Substs<'tcx>,
                                    variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
@@ -498,21 +379,45 @@ fn add_constraints_from_substs(&mut self,
                substs,
                variance);
 
-        for p in type_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
+        // We don't record `inferred_starts` entries for empty generics.
+        if substs.is_empty() {
+            return;
+        }
+
+        // Add a corresponding relation into the dependencies to
+        // indicate that the variance for `current` relies on `def_id`.
+        if self.tcx().dep_graph.is_fully_enabled() {
+            self.dependencies.add(current.def_id, def_id);
+        }
+
+        let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) {
+            (Some(self.terms_cx.inferred_starts[&id]), None)
+        } else {
+            (None, Some(self.tcx().variances_of(def_id)))
+        };
+
+        for (i, k) in substs.iter().enumerate() {
+            let variance_decl = if let Some(InferredIndex(start)) = local {
+                // Parameter on an item defined within current crate:
+                // variance not yet inferred, so return a symbolic
+                // variance.
+                self.terms_cx.inferred_terms[start + i]
+            } else {
+                // Parameter on an item defined within another crate:
+                // variance already inferred, just look it up.
+                self.constant_term(remote.as_ref().unwrap()[i])
+            };
             let variance_i = self.xform(variance, variance_decl);
-            let substs_ty = substs.type_for_def(p);
             debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
                    variance_decl,
                    variance_i);
-            self.add_constraints_from_ty(current, substs_ty, variance_i);
-        }
-
-        for p in region_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
-            let variance_i = self.xform(variance, variance_decl);
-            let substs_r = substs.region_for_def(p);
-            self.add_constraints_from_region(current, substs_r, variance_i);
+            if let Some(ty) = k.as_type() {
+                self.add_constraints_from_ty(current, ty, variance_i);
+            } else if let Some(r) = k.as_region() {
+                self.add_constraints_from_region(current, r, variance_i);
+            } else {
+                bug!();
+            }
         }
     }
 
@@ -537,21 +442,14 @@ fn add_constraints_from_region(&mut self,
                                    variance: VarianceTermPtr<'a>) {
         match *region {
             ty::ReEarlyBound(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let i = data.index as usize - current.generics.has_self as usize;
-                let def_id = current.generics.regions[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                if self.is_to_be_inferred(node_id) {
-                    let &index = self.opt_inferred_index(node_id).unwrap();
-                    self.add_constraint(index, variance);
-                }
+                self.add_constraint(current, data.index, variance);
             }
 
             ty::ReStatic => {}
 
             ty::ReLateBound(..) => {
-                // We do not infer variance for region parameters on
-                // methods or in fn types.
+                // Late-bound regions do not get substituted the same
+                // way early-bound regions do, so we skip them here.
             }
 
             ty::ReFree(..) |
index 8f9f40ca40b037ee75e157651546a6a2e14604c7..7a9f35545e2f383defa9c09444aac638c0793c63 100644 (file)
@@ -54,45 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
 
 fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
                             -> Rc<Vec<ty::Variance>> {
-    let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
-    let item = tcx.hir.expect_item(item_id);
-    match item.node {
-        hir::ItemTrait(..) => {
-            // Traits are always invariant.
-            let generics = tcx.generics_of(item_def_id);
-            assert!(generics.parent.is_none());
-            Rc::new(vec![ty::Variance::Invariant; generics.count()])
-        }
+    let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
+    let unsupported = || {
+        // Variance not relevant.
+        span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item")
+    };
+    match tcx.hir.get(id) {
+        hir::map::NodeItem(item) => match item.node {
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) |
+            hir::ItemUnion(..) |
+            hir::ItemFn(..) => {}
 
-        hir::ItemEnum(..) |
-        hir::ItemStruct(..) |
-        hir::ItemUnion(..) => {
-            // Everything else must be inferred.
+            _ => unsupported()
+        },
 
-            // Lacking red/green, we read the variances for all items here
-            // but ignore the dependencies, then re-synthesize the ones we need.
-            let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
-            let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-            tcx.dep_graph.read(dep_node);
-            for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
-                if dep_def_id.is_local() {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                    tcx.dep_graph.read(dep_node);
-                } else {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
-                    tcx.dep_graph.read(dep_node);
-                }
-            }
-
-            crate_map.variances.get(&item_def_id)
-                               .unwrap_or(&crate_map.empty_variance)
-                               .clone()
-        }
+        hir::map::NodeTraitItem(item) => match item.node {
+            hir::TraitItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeImplItem(item) => match item.node {
+            hir::ImplItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeForeignItem(item) => match item.node {
+            hir::ForeignItemFn(..) => {}
 
-        _ => {
-            // Variance not relevant.
-            span_bug!(item.span, "asked to compute variance for wrong kind of item")
+            _ => unsupported()
+        },
+
+        hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {}
+
+        _ => unsupported()
+    }
+
+    // Everything else must be inferred.
+
+    // Lacking red/green, we read the variances for all items here
+    // but ignore the dependencies, then re-synthesize the ones we need.
+    let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
+    let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+    tcx.dep_graph.read(dep_node);
+    for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
+        if dep_def_id.is_local() {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+            tcx.dep_graph.read(dep_node);
+        } else {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
+            tcx.dep_graph.read(dep_node);
         }
     }
+
+    crate_map.variances.get(&item_def_id)
+                       .unwrap_or(&crate_map.empty_variance)
+                       .clone()
 }
 
index af8ad491ec00e7075ba0a5c3e2a56922bdb30ef5..495eb95419a90876581ef3165507f97373e7c417 100644 (file)
@@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> {
 pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap {
     let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx;
 
-    let solutions = terms_cx.inferred_infos
-        .iter()
-        .map(|ii| ii.initial_variance)
-        .collect();
+    let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
+    for &(id, ref variances) in &terms_cx.lang_items {
+        let InferredIndex(start) = terms_cx.inferred_starts[&id];
+        for (i, &variance) in variances.iter().enumerate() {
+            solutions[start + i] = variance;
+        }
+    }
 
     let mut solutions_cx = SolveContext {
-        terms_cx: terms_cx,
-        constraints: constraints,
-        solutions: solutions,
+        terms_cx,
+        constraints,
+        solutions,
     };
     solutions_cx.solve();
     let variances = solutions_cx.create_map();
@@ -71,12 +74,9 @@ fn solve(&mut self) {
                 let old_value = self.solutions[inferred];
                 let new_value = glb(variance, old_value);
                 if old_value != new_value {
-                    debug!("Updating inferred {} (node {}) \
+                    debug!("Updating inferred {} \
                             from {:?} to {:?} due to {:?}",
                            inferred,
-                           self.terms_cx
-                                   .inferred_infos[inferred]
-                               .param_id,
                            old_value,
                            new_value,
                            term);
@@ -89,49 +89,28 @@ fn solve(&mut self) {
     }
 
     fn create_map(&self) -> FxHashMap<DefId, Rc<Vec<ty::Variance>>> {
-        // Collect all the variances for a particular item and stick
-        // them into the variance map. We rely on the fact that we
-        // generate all the inferreds for a particular item
-        // consecutively (that is, we collect solutions for an item
-        // until we see a new item id, and we assume (1) the solutions
-        // are in the same order as the type parameters were declared
-        // and (2) all solutions or a given item appear before a new
-        // item id).
-
         let tcx = self.terms_cx.tcx;
 
-        let mut map = FxHashMap();
-
         let solutions = &self.solutions;
-        let inferred_infos = &self.terms_cx.inferred_infos;
-        let mut index = 0;
-        let num_inferred = self.terms_cx.num_inferred();
-        while index < num_inferred {
-            let item_id = inferred_infos[index].item_id;
-
-            let mut item_variances = vec![];
-
-            while index < num_inferred && inferred_infos[index].item_id == item_id {
-                let info = &inferred_infos[index];
-                let variance = solutions[index];
-                debug!("Index {} Info {} Variance {:?}",
-                       index,
-                       info.index,
-                       variance);
-
-                assert_eq!(item_variances.len(), info.index);
-                item_variances.push(variance);
-                index += 1;
-            }
+        self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
+            let def_id = tcx.hir.local_def_id(id);
+            let generics = tcx.generics_of(def_id);
 
-            debug!("item_id={} item_variances={:?}", item_id, item_variances);
+            let mut variances = solutions[start..start+generics.count()].to_vec();
 
-            let item_def_id = tcx.hir.local_def_id(item_id);
+            debug!("id={} variances={:?}", id, variances);
 
-            map.insert(item_def_id, Rc::new(item_variances));
-        }
+            // Functions can have unused type parameters: make those invariant.
+            if let ty::TyFnDef(..) = tcx.type_of(def_id).sty {
+                for variance in &mut variances {
+                    if *variance == ty::Bivariant {
+                        *variance = ty::Invariant;
+                    }
+                }
+            }
 
-        map
+            (def_id, Rc::new(variances))
+        }).collect()
     }
 
     fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
index ad787c57e76f2a60ee49739eef874e17c4ae5665..38457146a9714deebfa958aafa42959bed515e39 100644 (file)
@@ -22,7 +22,6 @@
 use arena::TypedArena;
 use rustc::ty::{self, TyCtxt};
 use std::fmt;
-use std::rc::Rc;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub arena: &'a TypedArena<VarianceTerm<'a>>,
 
-    pub empty_variances: Rc<Vec<ty::Variance>>,
-
     // For marker types, UnsafeCell, and other lang items where
     // variance is hardcoded, records the item-id and the hardcoded
     // variance.
     pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
 
-    // Maps from the node id of a type/generic parameter to the
-    // corresponding inferred index.
-    pub inferred_map: NodeMap<InferredIndex>,
-
-    // Maps from an InferredIndex to the info for that variable.
-    pub inferred_infos: Vec<InferredInfo<'a>>,
-}
-
-pub struct InferredInfo<'a> {
-    pub item_id: ast::NodeId,
-    pub index: usize,
-    pub param_id: ast::NodeId,
-    pub term: VarianceTermPtr<'a>,
+    // Maps from the node id of an item to the first inferred index
+    // used for its type & region parameters.
+    pub inferred_starts: NodeMap<InferredIndex>,
 
-    // Initial value to use for this parameter when inferring
-    // variance. For most parameters, this is Bivariant. But for lang
-    // items and input type parameters on traits, it is different.
-    pub initial_variance: ty::Variance,
+    // Maps from an InferredIndex to the term for that variable.
+    pub inferred_terms: Vec<VarianceTermPtr<'a>>,
 }
 
 pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
     let mut terms_cx = TermsContext {
         tcx: tcx,
         arena: arena,
-        inferred_map: NodeMap(),
-        inferred_infos: Vec::new(),
+        inferred_starts: NodeMap(),
+        inferred_terms: vec![],
 
         lang_items: lang_items(tcx),
-
-        // cache and share the variance struct used for items with
-        // no type/region parameters
-        empty_variances: Rc::new(vec![]),
     };
 
     // See README.md for a discussion on dep-graph management.
@@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
 }
 
 impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-    fn add_inferreds_for_item(&mut self,
-                              item_id: ast::NodeId,
-                              generics: &hir::Generics) {
-        //! Add "inferreds" for the generic parameters declared on this
-        //! item. This has a lot of annoying parameters because we are
-        //! trying to drive this from the AST, rather than the
-        //! ty::Generics, so that we can get span info -- but this
-        //! means we must accommodate syntactic distinctions.
-        //!
+    fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+        let tcx = self.tcx;
+        let def_id = tcx.hir.local_def_id(id);
+        let count = tcx.generics_of(def_id).count();
 
-        // NB: In the code below for writing the results back into the
-        // `CrateVariancesMap`, we rely on the fact that all inferreds
-        // for a particular item are assigned continuous indices.
-
-        for (p, i) in generics.lifetimes.iter().zip(0..) {
-            let id = p.lifetime.id;
-            self.add_inferred(item_id, i, id);
-        }
-
-        for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) {
-            self.add_inferred(item_id, i, p.id);
+        if count == 0 {
+            return;
         }
-    }
 
-    fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) {
-        let inf_index = InferredIndex(self.inferred_infos.len());
-        let term = self.arena.alloc(InferredTerm(inf_index));
-        let initial_variance = self.pick_initial_variance(item_id, index);
-        self.inferred_infos.push(InferredInfo {
-            item_id: item_id,
-            index: index,
-            param_id: param_id,
-            term: term,
-            initial_variance: initial_variance,
-        });
-        let newly_added = self.inferred_map.insert(param_id, inf_index).is_none();
+        // Record the start of this item's inferreds.
+        let start = self.inferred_terms.len();
+        let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
         assert!(newly_added);
 
-        debug!("add_inferred(item_path={}, \
-                item_id={}, \
-                index={}, \
-                param_id={}, \
-                inf_index={:?}, \
-                initial_variance={:?})",
-               self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)),
-               item_id,
-               index,
-               param_id,
-               inf_index,
-               initial_variance);
-    }
-
-    fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance {
-        match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
-            Some(&(_, ref variances)) => variances[index],
-            None => ty::Bivariant,
-        }
-    }
+        // NB: In the code below for writing the results back into the
+        // `CrateVariancesMap`, we rely on the fact that all inferreds
+        // for a particular item are assigned continuous indices.
 
-    pub fn num_inferred(&self) -> usize {
-        self.inferred_infos.len()
+        let arena = self.arena;
+        self.inferred_terms.extend((start..start+count).map(|i| {
+            &*arena.alloc(InferredTerm(InferredIndex(i)))
+        }));
     }
 }
 
@@ -205,30 +147,50 @@ fn visit_item(&mut self, item: &hir::Item) {
                self.tcx.hir.node_to_string(item.id));
 
         match item.node {
-            hir::ItemEnum(_, ref generics) |
-            hir::ItemStruct(_, ref generics) |
-            hir::ItemUnion(_, ref generics) => {
-                self.add_inferreds_for_item(item.id, generics);
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.add_inferreds_for_item(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.add_inferreds_for_item(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.add_inferreds_for_item(item.id);
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
-            hir::ItemImpl(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) => {}
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.add_inferreds_for_item(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.add_inferreds_for_item(trait_item.id);
+        }
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.add_inferreds_for_item(impl_item.id);
+        }
     }
 }
index aeade47048223bef2b88e0c0a5781f789f50f646..fa5a999adf1960c00dfb57d52365d19397d25a79 100644 (file)
@@ -149,7 +149,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
 }
 
 fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
-    let sig = cx.tcx.type_of(did).fn_sig();
+    let sig = cx.tcx.fn_sig(did);
 
     let constness = if cx.tcx.is_const_fn(did) {
         hir::Constness::Const
index 8fc8ccd0cfd92eba6b8f7a0ae2258494fb9dc558..478e2fc5085d19fe8dba0e3fcc7ea6ac6d30e777 100644 (file)
@@ -1367,7 +1367,7 @@ fn clean(&self, cx: &DocContext) -> Item {
             ty::AssociatedKind::Method => {
                 let generics = (cx.tcx.generics_of(self.def_id),
                                 &cx.tcx.predicates_of(self.def_id)).clean(cx);
-                let sig = cx.tcx.type_of(self.def_id).fn_sig();
+                let sig = cx.tcx.fn_sig(self.def_id);
                 let mut decl = (self.def_id, sig).clean(cx);
 
                 if self.method_has_self_argument {
@@ -1842,17 +1842,21 @@ fn clean(&self, cx: &DocContext) -> Type {
                 mutability: mt.mutbl.clean(cx),
                 type_: box mt.ty.clean(cx),
             },
-            ty::TyFnDef(.., sig) |
-            ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl {
-                unsafety: sig.unsafety(),
-                generics: Generics {
-                    lifetimes: Vec::new(),
-                    type_params: Vec::new(),
-                    where_predicates: Vec::new()
-                },
-                decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
-                abi: sig.abi(),
-            }),
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) => {
+                let ty = cx.tcx.lift(self).unwrap();
+                let sig = ty.fn_sig(cx.tcx);
+                BareFunction(box BareFunctionDecl {
+                    unsafety: sig.unsafety(),
+                    generics: Generics {
+                        lifetimes: Vec::new(),
+                        type_params: Vec::new(),
+                        where_predicates: Vec::new()
+                    },
+                    decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
+                    abi: sig.abi(),
+                })
+            }
             ty::TyAdt(def, substs) => {
                 let did = def.did;
                 let kind = match def.adt_kind() {
index bea13397eca4bc298d2d4e438cc8ee4255407cd2..03da451fd9a0a2477fe9226b04f53a23ff08ed2b 100644 (file)
@@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position
                                block_info.should_panic, block_info.no_run,
                                block_info.ignore, block_info.test_harness,
                                block_info.compile_fail, block_info.error_codes,
-                               line, filename);
+                               line, filename, block_info.allow_fail);
             } else {
                 tests.add_old_test(text, filename);
             }
@@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                                block_info.should_panic, block_info.no_run,
                                block_info.ignore, block_info.test_harness,
                                block_info.compile_fail, block_info.error_codes,
-                               line, filename);
+                               line, filename, block_info.allow_fail);
                 prev_offset = offset;
             }
             Event::Start(Tag::Header(level)) => {
@@ -889,6 +889,7 @@ struct LangString {
     test_harness: bool,
     compile_fail: bool,
     error_codes: Vec<String>,
+    allow_fail: bool,
 }
 
 impl LangString {
@@ -902,6 +903,7 @@ fn all_false() -> LangString {
             test_harness: false,
             compile_fail: false,
             error_codes: Vec::new(),
+            allow_fail: false,
         }
     }
 
@@ -930,6 +932,7 @@ fn parse(string: &str) -> LangString {
                 }
                 "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
                 "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+                "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
                 "rust" => { data.rust = true; seen_rust_tags = true; }
                 "test_harness" => {
                     data.test_harness = true;
@@ -1118,7 +1121,7 @@ mod tests {
     fn test_lang_string_parse() {
         fn t(s: &str,
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
-            compile_fail: bool, error_codes: Vec<String>) {
+            compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
             assert_eq!(LangString::parse(s), LangString {
                 should_panic: should_panic,
                 no_run: no_run,
@@ -1128,25 +1131,31 @@ fn t(s: &str,
                 compile_fail: compile_fail,
                 error_codes: error_codes,
                 original: s.to_owned(),
+                allow_fail: allow_fail,
             })
         }
 
+        fn v() -> Vec<String> {
+            Vec::new()
+        }
+
         // marker                | should_panic| no_run| ignore| rust | test_harness| compile_fail
-        //                       | error_codes
-        t("",                      false,        false,  false,  true,  false, false, Vec::new());
-        t("rust",                  false,        false,  false,  true,  false, false, Vec::new());
-        t("sh",                    false,        false,  false,  false, false, false, Vec::new());
-        t("ignore",                false,        false,  true,   true,  false, false, Vec::new());
-        t("should_panic",          true,         false,  false,  true,  false, false, Vec::new());
-        t("no_run",                false,        true,   false,  true,  false, false, Vec::new());
-        t("test_harness",          false,        false,  false,  true,  true,  false, Vec::new());
-        t("compile_fail",          false,        true,   false,  true,  false, true,  Vec::new());
-        t("{.no_run .example}",    false,        true,   false,  true,  false, false, Vec::new());
-        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, Vec::new());
-        t("{.example .rust}",      false,        false,  false,  true,  false, false, Vec::new());
-        t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, Vec::new());
-        t("text, no_run",          false,        true,   false,  false, false, false, Vec::new());
-        t("text,no_run",           false,        true,   false,  false, false, false, Vec::new());
+        //                       | allow_fail | error_codes
+        t("",                      false,        false,  false,  true,  false, false, false, v());
+        t("rust",                  false,        false,  false,  true,  false, false, false, v());
+        t("sh",                    false,        false,  false,  false, false, false, false, v());
+        t("ignore",                false,        false,  true,   true,  false, false, false, v());
+        t("should_panic",          true,         false,  false,  true,  false, false, false, v());
+        t("no_run",                false,        true,   false,  true,  false, false, false, v());
+        t("test_harness",          false,        false,  false,  true,  true,  false, false, v());
+        t("compile_fail",          false,        true,   false,  true,  false, true,  false, v());
+        t("allow_fail",            false,        false,  false,  true,  false, false, true,  v());
+        t("{.no_run .example}",    false,        true,   false,  true,  false, false, false, v());
+        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, false, v());
+        t("{.example .rust}",      false,        false,  false,  true,  false, false, false, v());
+        t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, false, v());
+        t("text, no_run",          false,        true,   false,  false, false, false, false, v());
+        t("text,no_run",           false,        true,   false,  false, false, false, false, v());
     }
 
     #[test]
index cfe2fad0fa4695a59d1b840da41c493305086a6c..4766778eed1b88bc00b505f708ad78b39bc83b97 100644 (file)
@@ -467,7 +467,7 @@ pub fn add_old_test(&mut self, test: String, filename: String) {
     pub fn add_test(&mut self, test: String,
                     should_panic: bool, no_run: bool, should_ignore: bool,
                     as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
-                    line: usize, filename: String) {
+                    line: usize, filename: String, allow_fail: bool) {
         let name = self.generate_name(line, &filename);
         // to be removed when hoedown is removed
         if self.render_type == RenderType::Pulldown {
@@ -499,6 +499,7 @@ pub fn add_test(&mut self, test: String,
                 ignore: should_ignore,
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
+                allow_fail: allow_fail,
             },
             testfn: testing::DynTestFn(box move |()| {
                 let panic = io::set_panic(None);
index b8a6a66eaa65d60201d107319749cc7336af40a6..2ed6724b07da4fb9bab5f40e176ecfb6010d706e 100644 (file)
 pub use self::hash_set::HashSet;
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(reason = "moved to std::ops", since = "1.19.0")]
+#[allow(deprecated)]
 pub use alloc::range;
 
 mod hash;
index 1dfae0ce83f62bbbe177acf96425e92a62d47c12..f81adad3ebebf1747578e982ab3fedb8bc021429 100644 (file)
@@ -949,63 +949,9 @@ mod arch {
 mod tests {
     use super::*;
 
-    use iter::repeat;
-    use rand::{self, Rng};
-    use ffi::{OsString, OsStr};
+    use ffi::OsStr;
     use path::{Path, PathBuf};
 
-    fn make_rand_name() -> OsString {
-        let mut rng = rand::thread_rng();
-        let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
-                                     .collect::<String>());
-        let n = OsString::from(n);
-        assert!(var_os(&n).is_none());
-        n
-    }
-
-    fn eq(a: Option<OsString>, b: Option<&str>) {
-        assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
-    }
-
-    #[test]
-    fn test_set_var() {
-        let n = make_rand_name();
-        set_var(&n, "VALUE");
-        eq(var_os(&n), Some("VALUE"));
-    }
-
-    #[test]
-    fn test_remove_var() {
-        let n = make_rand_name();
-        set_var(&n, "VALUE");
-        remove_var(&n);
-        eq(var_os(&n), None);
-    }
-
-    #[test]
-    fn test_set_var_overwrite() {
-        let n = make_rand_name();
-        set_var(&n, "1");
-        set_var(&n, "2");
-        eq(var_os(&n), Some("2"));
-        set_var(&n, "");
-        eq(var_os(&n), Some(""));
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_var_big() {
-        let mut s = "".to_string();
-        let mut i = 0;
-        while i < 100 {
-            s.push_str("aaaaaaaaaa");
-            i += 1;
-        }
-        let n = make_rand_name();
-        set_var(&n, &s);
-        eq(var_os(&n), Some(&s));
-    }
-
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_self_exe_path() {
@@ -1017,32 +963,6 @@ fn test_self_exe_path() {
         assert!(path.is_absolute());
     }
 
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_env_set_get_huge() {
-        let n = make_rand_name();
-        let s = repeat("x").take(10000).collect::<String>();
-        set_var(&n, &s);
-        eq(var_os(&n), Some(&s));
-        remove_var(&n);
-        eq(var_os(&n), None);
-    }
-
-    #[test]
-    fn test_env_set_var() {
-        let n = make_rand_name();
-
-        let mut e = vars_os();
-        set_var(&n, "VALUE");
-        assert!(!e.any(|(k, v)| {
-            &*k == &*n && &*v == "VALUE"
-        }));
-
-        assert!(vars_os().any(|(k, v)| {
-            &*k == &*n && &*v == "VALUE"
-        }));
-    }
-
     #[test]
     fn test() {
         assert!((!Path::new("test-path").is_absolute()));
index 6134b0b882c5bb80c133ee57b3cbd165294b3451..7d79fb078116f568cd6124af01b6beac93108c97 100644 (file)
@@ -363,39 +363,29 @@ pub fn abs(self) -> f32 { num::Float::abs(self) }
     #[inline]
     pub fn signum(self) -> f32 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0_f32;
     /// let g = -7.0_f32;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0f32;
     /// let g = -7.0f32;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1184,7 +1174,7 @@ fn test_nan() {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1428,7 +1418,8 @@ fn test_is_sign_positive() {
         assert!(!(-1f32).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f32/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1441,6 +1432,7 @@ fn test_is_sign_negative() {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f32/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
index e8d25cfbf949a93c9f9ac81216d3ee16133be22f..d5b0cd3a1fc796b5493cfab84ce3adaadecfbaf7 100644 (file)
@@ -301,21 +301,15 @@ pub fn abs(self) -> f64 { num::Float::abs(self) }
     #[inline]
     pub fn signum(self) -> f64 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan: f64 = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -326,21 +320,15 @@ pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
     #[inline]
     pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1101,7 +1089,7 @@ fn test_nan() {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1347,7 +1335,8 @@ fn test_is_sign_positive() {
         assert!(!(-1f64).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f64/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1360,6 +1349,7 @@ fn test_is_sign_negative() {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f64/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
index f54d79c201f4869ae9fa01b0d499e89f97a85d3b..42d641706a894318bbc1c93c0c9a3ce889a0d9c9 100644 (file)
@@ -29,7 +29,7 @@
 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
 ///   values, interpreted as UTF-16 when it is valid to do so.
 ///
-/// * In Rust, strings are always valid UTF-8, but may contain zeros.
+/// * In Rust, strings are always valid UTF-8, which may contain zeros.
 ///
 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
 /// and platform-native string values, and in particular allowing a Rust string
@@ -230,8 +230,6 @@ pub fn reserve_exact(&mut self, additional: usize) {
     /// # Examples
     ///
     /// ```
-    /// #![feature(osstring_shrink_to_fit)]
-    ///
     /// use std::ffi::OsString;
     ///
     /// let mut s = OsString::from("foo");
@@ -242,7 +240,7 @@ pub fn reserve_exact(&mut self, additional: usize) {
     /// s.shrink_to_fit();
     /// assert_eq!(3, s.capacity());
     /// ```
-    #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")]
+    #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
     pub fn shrink_to_fit(&mut self) {
         self.inner.shrink_to_fit()
     }
index df6a648b7b1626a4cf4ef157003d856ded40b9a4..7adfcc44ad008847e9fd99c8f628de9f768bb688 100644 (file)
@@ -447,8 +447,6 @@ pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
     /// Basic usage:
     ///
     /// ```no_run
-    /// #![feature(command_envs)]
-    ///
     /// use std::process::{Command, Stdio};
     /// use std::env;
     /// use std::collections::HashMap;
@@ -466,7 +464,7 @@ pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
     ///         .spawn()
     ///         .expect("printenv failed to start");
     /// ```
-    #[unstable(feature = "command_envs", issue = "38526")]
+    #[stable(feature = "command_envs", since = "1.19.0")]
     pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
         where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
     {
index ac3fd2ad6b9bed10bc08851d74db09b2dff98def..17673f0bd60b3b5a7525f709ce002e6825cfe55a 100644 (file)
@@ -17,7 +17,6 @@
 use sys::syscall::TimeSpec;
 use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
-use vec::Vec;
 
 use super::{path_to_peer_addr, path_to_local_addr};
 
index 05863adf108cca7cd62e5c16b2d161b98dd8d0d1..28645facd93f814d48db2d4da788d96d439a2a81 100644 (file)
@@ -49,8 +49,8 @@ pub fn read2(p1: AnonPipe,
     //FIXME: Use event based I/O multiplexing
     //unimplemented!()
 
-    p1.read_to_end(v1)?;
-    p2.read_to_end(v2)?;
+    p1.0.read_to_end(v1)?;
+    p2.0.read_to_end(v2)?;
 
     Ok(())
 
index 743b7c3220a8995457c48ba571f7a5d96b530fb9..f4fe52ca3b36c1962c841fbf07da7f303bbc6e64 100644 (file)
@@ -825,8 +825,6 @@ pub fn park_timeout(dur: Duration) {
 /// # Examples
 ///
 /// ```
-/// #![feature(thread_id)]
-///
 /// use std::thread;
 ///
 /// let other_thread = thread::spawn(|| {
@@ -836,7 +834,7 @@ pub fn park_timeout(dur: Duration) {
 /// let other_thread_id = other_thread.join().unwrap();
 /// assert!(thread::current().id() != other_thread_id);
 /// ```
-#[unstable(feature = "thread_id", issue = "21507")]
+#[stable(feature = "thread_id", since = "1.19.0")]
 #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
 pub struct ThreadId(u64);
 
@@ -966,8 +964,6 @@ pub fn unpark(&self) {
     /// # Examples
     ///
     /// ```
-    /// #![feature(thread_id)]
-    ///
     /// use std::thread;
     ///
     /// let other_thread = thread::spawn(|| {
@@ -977,7 +973,7 @@ pub fn unpark(&self) {
     /// let other_thread_id = other_thread.join().unwrap();
     /// assert!(thread::current().id() != other_thread_id);
     /// ```
-    #[unstable(feature = "thread_id", issue = "21507")]
+    #[stable(feature = "thread_id", since = "1.19.0")]
     pub fn id(&self) -> ThreadId {
         self.inner.id
     }
@@ -1168,8 +1164,6 @@ impl<T> JoinHandle<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(thread_id)]
-    ///
     /// use std::thread;
     ///
     /// let builder = thread::Builder::new();
index d7d3a70f3c7c5d2ab5f941bd8f867e2f8f90ae4c..74bf19b841e886fe04a3d3788ba57c29c1ad3acc 100644 (file)
@@ -354,6 +354,9 @@ pub fn new() -> Features {
 
     // rustc internal
     (active, abi_thiscall, "1.19.0", None),
+
+    // Allows a test to fail without failing the whole suite
+    (active, allow_fail, "1.19.0", Some(42219)),
 );
 
 declare_features! (
@@ -812,6 +815,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                              "used internally by rustc",
                                              cfg_fn!(rustc_attrs))),
 
+    ("allow_fail", Normal, Gated(Stability::Unstable,
+                                 "allow_fail",
+                                 "allow_fail attribute is currently unstable",
+                                 cfg_fn!(allow_fail))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
index 851a638e14842af4fd55ce36444e968124805adc..5b0031b2f179fb0ffa62cded3adc83698fd72921 100644 (file)
@@ -1659,8 +1659,10 @@ pub fn parse_lit(&mut self) -> PResult<'a, Lit> {
         Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) })
     }
 
-    /// matches '-' lit | lit
+    /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat)
     pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+        maybe_whole_expr!(self);
+
         let minus_lo = self.span;
         let minus_present = self.eat(&token::BinOp(token::Minus));
         let lo = self.span;
index a0d1785c6ff14a45f5d0d7e479200f63740a5259..86f5f42eac79614c5e74646b26754db314024a8d 100644 (file)
@@ -52,7 +52,8 @@ struct Test {
     path: Vec<Ident> ,
     bench: bool,
     ignore: bool,
-    should_panic: ShouldPanic
+    should_panic: ShouldPanic,
+    allow_fail: bool,
 }
 
 struct TestCtxt<'a> {
@@ -133,7 +134,8 @@ fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
                         path: self.cx.path.clone(),
                         bench: is_bench_fn(&self.cx, &i),
                         ignore: is_ignored(&i),
-                        should_panic: should_panic(&i, &self.cx)
+                        should_panic: should_panic(&i, &self.cx),
+                        allow_fail: is_allowed_fail(&i),
                     };
                     self.cx.testfns.push(test);
                     self.tests.push(i.ident);
@@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool {
     i.attrs.iter().any(|attr| attr.check_name("ignore"))
 }
 
+fn is_allowed_fail(i: &ast::Item) -> bool {
+    i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
+}
+
 fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
     match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
         Some(attr) => {
@@ -668,6 +674,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             }
         }
     };
+    let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
 
     // self::test::TestDesc { ... }
     let desc_expr = ecx.expr_struct(
@@ -675,7 +682,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
         test_path("TestDesc"),
         vec![field("name", name_expr),
              field("ignore", ignore_expr),
-             field("should_panic", fail_expr)]);
+             field("should_panic", fail_expr),
+             field("allow_fail", allow_fail_expr)]);
 
 
     let mut visible_path = match cx.toplevel_reexport {
index 1993d6ebe5b493fc778e74c0455301da599da3b3..35a2a2513f4e250264e2e8642bb18c8e9b2bc5ce 100644 (file)
@@ -167,7 +167,7 @@ fn cs_clone(name: &str,
             all_fields = af;
             vdata = vdata_;
         }
-        EnumMatching(_, variant, ref af) => {
+        EnumMatching(.., variant, ref af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
             all_fields = af;
             vdata = &variant.node.data;
index ec4cb815960d1b6b35ca03f4eec966b90e384819..38ed596098b2123e83618ca7b296c0e137ccb250 100644 (file)
@@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // based on the "shape".
     let (ident, is_struct) = match *substr.fields {
         Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
-        EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
+        EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
index 33f742282c1726a95e12818a69d3000a6b989272..1e19cd994192e15a9b3ef634ebcfbde63122b35d 100644 (file)
@@ -237,7 +237,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
                                      blk])
         }
 
-        EnumMatching(idx, variant, ref fields) => {
+        EnumMatching(idx, _, variant, ref fields) => {
             // We're not generating an AST that the borrow checker is expecting,
             // so we need to generate a unique local variable to take the
             // mutable loan out on, otherwise we get conflicts which don't
index 3a15b82d19f691de1e974a87f152c57700d21fbc..4acd65bbf8652cd0f1c216463b1fc6fff982240c 100644 (file)
@@ -305,10 +305,10 @@ pub enum StaticFields {
 /// A summary of the possible sets of fields.
 pub enum SubstructureFields<'a> {
     Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
-    /// Matching variants of the enum: variant index, ast::Variant,
+    /// Matching variants of the enum: variant index, variant count, ast::Variant,
     /// fields: the field name is only non-`None` in the case of a struct
     /// variant.
-    EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
+    EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
 
     /// Non-matching variants of the enum, but with all state hidden from
     /// the consequent code.  The first component holds `Ident`s for all of
@@ -1252,7 +1252,7 @@ fn build_enum_match_tuple<'b>(&self,
                 // expressions for referencing every field of every
                 // Self arg, assuming all are instances of VariantK.
                 // Build up code associated with such a case.
-                let substructure = EnumMatching(index, variant, field_tuples);
+                let substructure = EnumMatching(index, variants.len(), variant, field_tuples);
                 let arm_expr = self.call_substructure_method(cx,
                                                              trait_,
                                                              type_ident,
@@ -1269,12 +1269,13 @@ fn build_enum_match_tuple<'b>(&self,
                 // We need a default case that handles the fieldless variants.
                 // The index and actual variant aren't meaningful in this case,
                 // so just use whatever
+                let substructure = EnumMatching(0, variants.len(), v, Vec::new());
                 Some(self.call_substructure_method(cx,
                                                    trait_,
                                                    type_ident,
                                                    &self_args[..],
                                                    nonself_args,
-                                                   &EnumMatching(0, v, Vec::new())))
+                                                   &substructure))
             }
             _ if variants.len() > 1 && self_args.len() > 1 => {
                 // Since we know that all the arguments will match if we reach
index 97d7f2ce8003ea8c77481da3104e4647a773b0c1..a341c21d0a126cbc5667a74fd58e7358c6a10993 100644 (file)
@@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
     let mut stmts = Vec::new();
 
     let fields = match *substr.fields {
-        Struct(_, ref fs) => fs,
+        Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
         EnumMatching(.., ref fs) => {
             let variant_value = deriving::call_intrinsic(cx,
                                                          trait_span,
index 2094fd8898d49a3ebc4ec369557358ea50d483da..92cfb862b16691dafde886409044a087a9736780 100644 (file)
@@ -212,6 +212,7 @@ pub struct TestDesc {
     pub name: TestName,
     pub ignore: bool,
     pub should_panic: ShouldPanic,
+    pub allow_fail: bool,
 }
 
 #[derive(Clone)]
@@ -523,6 +524,7 @@ pub enum TestResult {
     TrFailed,
     TrFailedMsg(String),
     TrIgnored,
+    TrAllowedFail,
     TrMetrics(MetricMap),
     TrBench(BenchSamples),
 }
@@ -543,6 +545,7 @@ struct ConsoleTestState<T> {
     passed: usize,
     failed: usize,
     ignored: usize,
+    allowed_fail: usize,
     filtered_out: usize,
     measured: usize,
     metrics: MetricMap,
@@ -572,6 +575,7 @@ pub fn new(opts: &TestOpts, _: Option<T>) -> io::Result<ConsoleTestState<io::Std
             passed: 0,
             failed: 0,
             ignored: 0,
+            allowed_fail: 0,
             filtered_out: 0,
             measured: 0,
             metrics: MetricMap::new(),
@@ -594,6 +598,10 @@ pub fn write_ignored(&mut self) -> io::Result<()> {
         self.write_short_result("ignored", "i", term::color::YELLOW)
     }
 
+    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW)
+    }
+
     pub fn write_metric(&mut self) -> io::Result<()> {
         self.write_pretty("metric", term::color::CYAN)
     }
@@ -669,6 +677,7 @@ pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> {
             TrOk => self.write_ok(),
             TrFailed | TrFailedMsg(_) => self.write_failed(),
             TrIgnored => self.write_ignored(),
+            TrAllowedFail => self.write_allowed_fail(),
             TrMetrics(ref mm) => {
                 self.write_metric()?;
                 self.write_plain(&format!(": {}\n", mm.fmt_metrics()))
@@ -702,6 +711,7 @@ pub fn write_log_result(&mut self, test: &TestDesc, result: &TestResult) -> io::
                         TrFailed => "failed".to_owned(),
                         TrFailedMsg(ref msg) => format!("failed: {}", msg),
                         TrIgnored => "ignored".to_owned(),
+                        TrAllowedFail => "failed (allowed)".to_owned(),
                         TrMetrics(ref mm) => mm.fmt_metrics(),
                         TrBench(ref bs) => fmt_bench_samples(bs),
                     },
@@ -761,7 +771,8 @@ pub fn write_outputs(&mut self) -> io::Result<()> {
     }
 
     pub fn write_run_finish(&mut self) -> io::Result<bool> {
-        assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
+        assert!(self.passed + self.failed + self.ignored + self.measured +
+                    self.allowed_fail == self.total);
 
         if self.options.display_output {
             self.write_outputs()?;
@@ -778,12 +789,24 @@ pub fn write_run_finish(&mut self) -> io::Result<bool> {
         } else {
             self.write_pretty("FAILED", term::color::RED)?;
         }
-        let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
-                        self.passed,
-                        self.failed,
-                        self.ignored,
-                        self.measured,
-                        self.filtered_out);
+        let s = if self.allowed_fail > 0 {
+            format!(
+                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
+                self.passed,
+                self.failed + self.allowed_fail,
+                self.allowed_fail,
+                self.ignored,
+                self.measured,
+                self.filtered_out)
+        } else {
+            format!(
+                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
+                self.passed,
+                self.failed,
+                self.ignored,
+                self.measured,
+                self.filtered_out)
+        };
         self.write_plain(&s)?;
         return Ok(success);
     }
@@ -891,6 +914,7 @@ fn callback<T: Write>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::Re
                         st.not_failures.push((test, stdout));
                     }
                     TrIgnored => st.ignored += 1,
+                    TrAllowedFail => st.allowed_fail += 1,
                     TrMetrics(mm) => {
                         let tname = test.name;
                         let MetricMap(mm) = mm;
@@ -945,12 +969,14 @@ fn should_sort_failures_before_printing_them() {
         name: StaticTestName("a"),
         ignore: false,
         should_panic: ShouldPanic::No,
+        allow_fail: false,
     };
 
     let test_b = TestDesc {
         name: StaticTestName("b"),
         ignore: false,
         should_panic: ShouldPanic::No,
+        allow_fail: false,
     };
 
     let mut st = ConsoleTestState {
@@ -962,6 +988,7 @@ fn should_sort_failures_before_printing_them() {
         passed: 0,
         failed: 0,
         ignored: 0,
+        allowed_fail: 0,
         filtered_out: 0,
         measured: 0,
         max_name_len: 10,
@@ -1471,8 +1498,13 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> Tes
                   .unwrap_or(false) {
                 TrOk
             } else {
-                TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                if desc.allow_fail {
+                    TrAllowedFail
+                } else {
+                    TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                }
             },
+        _ if desc.allow_fail => TrAllowedFail,
         _ => TrFailed,
     }
 }
@@ -1706,6 +1738,7 @@ fn f() {
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1723,6 +1756,7 @@ fn f() {}
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1742,6 +1776,7 @@ fn f() {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1761,6 +1796,7 @@ fn f() {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage("error message"),
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1782,6 +1818,7 @@ fn f() {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage(expected),
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1799,6 +1836,7 @@ fn f() {}
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1832,6 +1870,7 @@ pub fn filter_for_ignored_option() {
                                  name: StaticTestName("1"),
                                  ignore: true,
                                  should_panic: ShouldPanic::No,
+                                 allow_fail: false,
                              },
                              testfn: DynTestFn(Box::new(move |()| {})),
                          },
@@ -1840,6 +1879,7 @@ pub fn filter_for_ignored_option() {
                                  name: StaticTestName("2"),
                                  ignore: false,
                                  should_panic: ShouldPanic::No,
+                                 allow_fail: false,
                              },
                              testfn: DynTestFn(Box::new(move |()| {})),
                          }];
@@ -1863,6 +1903,7 @@ fn tests() -> Vec<TestDescAndFn> {
                     name: StaticTestName(name),
                     ignore: false,
                     should_panic: ShouldPanic::No,
+                    allow_fail: false,
                 },
                 testfn: DynTestFn(Box::new(move |()| {}))
             })
@@ -1944,6 +1985,7 @@ fn testfn() {}
                         name: DynTestName((*name).clone()),
                         ignore: false,
                         should_panic: ShouldPanic::No,
+                        allow_fail: false,
                     },
                     testfn: DynTestFn(Box::new(move |()| testfn())),
                 };
diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs
new file mode 100644 (file)
index 0000000..c5bf3a7
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    1u32 as char; //~ ERROR E0604
+}
diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs
new file mode 100644 (file)
index 0000000..add3fd8
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = 0u8;
+    x as Vec<u8>; //~ ERROR E0605
+                  //~| NOTE an `as` expression can only be used to convert between primitive types
+
+    let v = 0 as *const u8;
+    v as &u8; //~ ERROR E0605
+              //~| NOTE an `as` expression can only be used to convert between primitive types
+}
diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs
new file mode 100644 (file)
index 0000000..5507173
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    &0u8 as u8; //~ ERROR E0606
+}
diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs
new file mode 100644 (file)
index 0000000..fa761f2
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let v = 0 as *const u8;
+    v as *const [u8]; //~ ERROR E0607
+}
index cdb7dff692c146dd6fb762c4c1cdcba8b970946b..d62f6b0f1a37140aa870e30cbcc5313533396926 100644 (file)
@@ -38,11 +38,13 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/compile-fail/block-must-not-have-result-do.rs
deleted file mode 100644 (file)
index 2a6c71d..0000000
+++ /dev/null
@@ -1,15 +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.
-
-fn main() {
-    loop {
-        true //~  ERROR mismatched types
-    }
-}
diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/compile-fail/block-must-not-have-result-res.rs
deleted file mode 100644 (file)
index 8728685..0000000
+++ /dev/null
@@ -1,20 +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.
-
-struct r;
-
-impl Drop for r {
-    fn drop(&mut self) {
-        true //~  ERROR mismatched types
-    }
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/compile-fail/block-must-not-have-result-while.rs
deleted file mode 100644 (file)
index a0fb470..0000000
+++ /dev/null
@@ -1,18 +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.
-
-fn main() {
-    while true {
-        true //~  ERROR mismatched types
-             //~| expected type `()`
-             //~| found type `bool`
-             //~| expected (), found bool
-    }
-}
index 4c6dcaccc9aed5347cb85f94cd456c982f56e724..ab22d352480739d3fe27520993523b4df654acf5 100644 (file)
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: non-scalar cast: `()` as `u32`
+// error-pattern: non-primitive cast: `()` as `u32`
 fn main() { let u = (assert!(true) as u32); }
index 7cc5c727bc7df786e045124167adf0757df82167..d5a998c6e4b6b944884c6135beac62f29cf74742 100644 (file)
@@ -13,8 +13,8 @@ fn foo(_x: isize) { }
 fn main() {
     let v: u64 = 5;
     let x = foo as extern "C" fn() -> isize;
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
     let y = v as extern "Rust" fn(isize) -> (isize, isize);
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
     y(x());
 }
index e5fd5bb33eb908978d6f77f82b7354fabc6fdc17..27d9e8a42b188c58759ff50ac7410f893d33cf65 100644 (file)
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: non-scalar cast: `u32` as `()`
+// error-pattern: non-primitive cast: `u32` as `()`
 fn main() { let u = 0u32 as (); }
index 85dbc899208f6f95e7b3c8096a4122d0982355f8..6584c16c9dec67cfdbb3d6966dcb56d6ada51b10 100644 (file)
@@ -14,5 +14,5 @@
 fn main() {
     let b = 0u8;
     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
 }
index 57d2192e6356b854d3e53db7ad85ed526874f649..0479f5cce65379ed73bd43b46f1356bde316f564 100644 (file)
@@ -17,7 +17,7 @@ fn cast_a() {
 }
 
 fn cast_b() {
-    let y = 22 as !; //~ ERROR non-scalar cast
+    let y = 22 as !; //~ ERROR non-primitive cast
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/compile-fail/consider-removing-last-semi.rs
deleted file mode 100644 (file)
index 530a0e4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn f() -> String {  //~ ERROR mismatched types
-    0u8;
-    "bla".to_string();  //~ HELP consider removing this semicolon
-}
-
-fn g() -> String {  //~ ERROR mismatched types
-    "this won't work".to_string();
-    "removeme".to_string(); //~ HELP consider removing this semicolon
-}
-
-fn main() {}
index c62987a5b900e60c637858a63374061934adcc53..bc2dc1cc5d4c83923f349f8062462af9bc79f020 100644 (file)
@@ -22,7 +22,7 @@ fn main() {
     a as isize; //~ ERROR casting
     a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
     a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
-    b as usize; //~ ERROR non-scalar cast
+    b as usize; //~ ERROR non-primitive cast
     p as usize;
     //~^ ERROR casting
     //~^^ HELP cast through a thin pointer
diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/compile-fail/feature-gate-allow_fail.rs
new file mode 100644 (file)
index 0000000..1124740
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+// check that #[allow_fail] is feature-gated
+
+#[allow_fail] //~ ERROR allow_fail attribute is currently unstable
+fn ok_to_fail() {
+    assert!(false);
+}
+
diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/compile-fail/for-loop-has-unit-body.rs
deleted file mode 100644 (file)
index 8c61fc6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    for x in 0..3 {
-        x //~ ERROR mismatched types
-        //~| NOTE expected ()
-        //~| NOTE expected type `()`
-    }
-}
index 2aa2546cb9fe124b0ca324be16ed9c3e430193df..c42d78c323e3ce643d1fff53e2afeec0e130b131 100644 (file)
@@ -11,6 +11,6 @@
 #![feature(intrinsics)]
 extern "rust-intrinsic" {
     pub static breakpoint : unsafe extern "rust-intrinsic" fn();
-    //~^ ERROR intrinsic has wrong type
+    //~^ ERROR intrinsic must be a function
 }
-fn main() { unsafe { breakpoint(); } }
\ No newline at end of file
+fn main() { unsafe { breakpoint(); } }
index 25060b94dcf37bec0354f1fd1c6e4bbaa714d7d4..2d00f339f33a066607fbf6eee018501ce5557422 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     let nil = ();
-    let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize`
+    let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
 }
diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/compile-fail/issue-11714.rs
deleted file mode 100644 (file)
index 192f78e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn blah() -> i32 { //~ ERROR mismatched types
-    1
-
-    ; //~ HELP consider removing this semicolon:
-}
-
-fn main() { }
diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/compile-fail/issue-13428.rs
deleted file mode 100644 (file)
index 9406199..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// Regression test for #13428
-
-fn foo() -> String {  //~ ERROR mismatched types
-    format!("Hello {}",
-            "world")
-    // Put the trailing semicolon on its own line to test that the
-    // note message gets the offending semicolon exactly
-    ;   //~ HELP consider removing this semicolon
-}
-
-fn bar() -> String {  //~ ERROR mismatched types
-    "foobar".to_string()
-    ;   //~ HELP consider removing this semicolon
-}
-
-pub fn main() {}
diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/compile-fail/issue-13624.rs
deleted file mode 100644 (file)
index e4ed87c..0000000
+++ /dev/null
@@ -1,43 +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.
-
-mod a {
-  pub enum Enum {
-    EnumStructVariant { x: u8, y: u8, z: u8 }
-  }
-
-  pub fn get_enum_struct_variant() -> () {
-    Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
-    //~^ ERROR mismatched types
-    //~| expected type `()`
-    //~| found type `a::Enum`
-    //~| expected (), found enum `a::Enum`
-  }
-}
-
-mod b {
-  mod test {
-    use a;
-
-    fn test_enum_struct_variant() {
-      let enum_struct_variant = ::a::get_enum_struct_variant();
-      match enum_struct_variant {
-        a::Enum::EnumStructVariant { x, y, z } => {
-        //~^ ERROR mismatched types
-        //~| expected type `()`
-        //~| found type `a::Enum`
-        //~| expected (), found enum `a::Enum`
-        }
-      }
-    }
-  }
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/compile-fail/issue-20862.rs
deleted file mode 100644 (file)
index 9df6358..0000000
+++ /dev/null
@@ -1,19 +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.
-
-fn foo(x: i32) {
-    |y| x + y
-//~^ ERROR: mismatched types
-}
-
-fn main() {
-    let x = foo(5)(2);
-//~^ ERROR: expected function, found `()`
-}
index bcbc414d3534bb3245dbd086701a0a2d7c68305e..c23fc4f334472bee36f321981f2e44078bc71d83 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0 as &std::any::Any; //~ ERROR non-scalar cast
+    0 as &std::any::Any; //~ ERROR non-primitive cast
 }
index 4d6e6eded211847a415538c4a0b28fc900e30d52..2128c4206301b3848968c48eb9db804b5a75a17e 100644 (file)
@@ -19,7 +19,7 @@ fn get<'a>(&'a self, y: usize, x: usize) -> Option<&'a <Self as Index<usize>>::O
         }
         let i = y * self.columns() + x;
         let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
-        //~^ERROR non-scalar cast
+        //~^ERROR non-primitive cast
         Some(indexer.index(i))
     }
 }
diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/compile-fail/issue-22645.rs
deleted file mode 100644 (file)
index 81f66e3..0000000
+++ /dev/null
@@ -1,27 +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.
-
-use std::ops::Add;
-
-trait Scalar {}
-impl Scalar for f64 {}
-
-struct Bob;
-
-impl<RHS: Scalar> Add <RHS> for Bob {
-  type Output = Bob;
-  fn add(self, rhs : RHS) -> Bob { Bob }
-}
-
-fn main() {
-  let b = Bob + 3.5;
-  b + 3 //~ ERROR E0277
-  //~^ ERROR: mismatched types
-}
index 28109747b755747db465d323382a6aec6fda0822..129f7c8b1ea0eb8b203f45b4f5f15dc6262bb295 100644 (file)
@@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
 }
 
 fn main() {
-    let ex = |x| {
-        let_(add(x,x), |y| { //~ ERROR type annotations needed
+    let ex = |x| { //~ ERROR type annotations needed
+        let_(add(x,x), |y| {
             let_(add(x, x), |x|x)})};
 }
index 8fbf97411cc7d0aaaf1c72fe4a3d060ff0f3310e..d735e184d5cd568f3c0461d11e9bebb8e9b483b4 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn bad (p: *const isize) {
-    let _q: &isize = p as &isize; //~ ERROR non-scalar cast
+    let _q: &isize = p as &isize; //~ ERROR non-primitive cast
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs
deleted file mode 100644 (file)
index 7928c04..0000000
+++ /dev/null
@@ -1,18 +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.
-
-trait A {
-    fn a(&self) {
-        || self.b()
-        //~^ ERROR no method named `b` found for type `&Self` in the current scope
-        //~| ERROR mismatched types
-    }
-}
-fn main() {}
index 65b17a3db0b59310d279dc59df768459cd3a4fae..896728b6da0f1df15d6b1a26f692556cd869f3cc 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
-
 fn _test(ref _p: str) {}
+//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277]
 
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs
new file mode 100644 (file)
index 0000000..06573b4
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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::ops::Deref;
+
+pub trait Foo {
+    fn baz(_: Self::Target) where Self: Deref {}
+    //~^ ERROR `<Self as std::ops::Deref>::Target: std::marker::Sized` is not satisfied
+}
+
+pub fn f(_: ToString) {}
+//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied
+
+fn main() { }
diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/issue-5500.rs
deleted file mode 100644 (file)
index 1cbb758..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-fn main() {
-    &panic!()
-    //~^ ERROR mismatched types
-    //~| expected type `()`
-    //~| found type `&_`
-    //~| expected (), found reference
-}
index d6f274da967d11e4d227794bb7fb3929123e6bfe..0abbc05eef05dd7b84bcd578b3ef6413001c2ed1 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:non-scalar cast
-
 #[derive(Debug)]
 struct foo {
     x: isize
 }
 
 fn main() {
-    println!("{}", foo{ x: 1 } as isize);
+    println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605]
 }
index 0df8c41ffe1a8e52ae7fa2f710305af478c78348..15375936b898c80de754ba8191984790bda0e5e4 100644 (file)
@@ -44,12 +44,18 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE trait message
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE trait message
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Foo
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Foo
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Bar
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Bar
 }
index 79021cd03ccc13e6fa12f35d6f1ab23c28338252..66d612baab4e8648b80a6275cf9c318e8aba0988 100644 (file)
@@ -33,4 +33,6 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE a usize is required
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE a usize is required
 }
diff --git a/src/test/compile-fail/patkind-litrange-no-expr.rs b/src/test/compile-fail/patkind-litrange-no-expr.rs
new file mode 100644 (file)
index 0000000..afb2cbb
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! enum_number {
+    ($name:ident { $($variant:ident = $value:expr, )* }) => {
+        enum $name {
+            $($variant = $value,)*
+        }
+
+        fn foo(value: i32) -> Option<$name> {
+            match value {
+                $( $value => Some($name::$variant), )* // PatKind::Lit
+                $( $value ... 42 => Some($name::$variant), )* // PatKind::Range
+                _ => None
+            }
+        }
+    }
+}
+
+enum_number!(Change {
+    Pos = 1,
+    Neg = -1,
+    Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
+                   //~^ ERROR arbitrary expressions aren't allowed in patterns
+                   //~^^ ERROR only char and numeric types are allowed in range patterns
+});
+
+fn main() {}
+
index b01063291266c37a55749e4a1d9a1f120308ff47..220537633eaf12291d6f99b18df7af814b5e90b3 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//error-pattern: non-scalar cast
-
 enum non_nullary {
     nullary,
     other(isize),
@@ -17,5 +15,5 @@ enum non_nullary {
 
 fn main() {
     let v = non_nullary::nullary;
-    let val = v as isize;
+    let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605]
 }
index b4df5fb1e2accd5a9c2884585876a03c257e278e..2a5d25e6b98dd0497286a83883c518c64a5ceef0 100644 (file)
@@ -11,7 +11,7 @@
 enum E {}
 
 fn f(e: E) {
-    println!("{}", (e as isize).to_string());   //~ ERROR non-scalar cast
+    println!("{}", (e as isize).to_string());   //~ ERROR non-primitive cast
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/compile-fail/variance-region-bounds.rs
deleted file mode 100644 (file)
index 41d204a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Check that `T:'a` is contravariant in T.
-
-#![feature(rustc_attrs)]
-
-#[rustc_variance]
-trait Foo: 'static { //~ ERROR [o]
-}
-
-#[rustc_variance]
-trait Bar<T> { //~ ERROR [o, o]
-    fn do_it(&self)
-        where T: 'static;
-}
-
-fn main() { }
index 58fb785c48ca7b24a70c92e2cd5c9e897b6c9230..9b88e38e085546feb68ef1435e7aa7a66334b182 100644 (file)
 // Check that bounds on type parameters (other than `Self`) do not
 // influence variance.
 
-#[rustc_variance]
-trait Getter<T> { //~ ERROR [o, o]
+trait Getter<T> {
     fn get(&self) -> T;
 }
 
-#[rustc_variance]
-trait Setter<T> { //~ ERROR [o, o]
+trait Setter<T> {
     fn get(&self, T);
 }
 
@@ -34,20 +32,6 @@ enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
     Foo(T)
 }
 
-#[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR [o, o, o]
-    fn getter(&self, u: U) -> T;
-}
-
-#[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR [o, o]
-}
-
-#[rustc_variance]
-trait TestTrait3<U> { //~ ERROR [o, o]
-    fn getter<T:Getter<U>>(&self);
-}
-
 #[rustc_variance]
 struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
     t: T
index 2df94cc907a9cf88517497712bb4218e90caca3b..5075dd2ceedc093ba972f70c5d952e6332bdc508 100644 (file)
@@ -36,37 +36,14 @@ struct TestIndirect2<A:'static, B:'static> { //~ ERROR [o, o]
     m: TestMut<B, A>
 }
 
-#[rustc_variance]
-trait Getter<A> { //~ ERROR [o, o]
+trait Getter<A> {
     fn get(&self) -> A;
 }
 
-#[rustc_variance]
-trait Setter<A> { //~ ERROR [o, o]
-    fn set(&mut self, a: A);
-}
-
-#[rustc_variance]
-trait GetterSetter<A> { //~ ERROR [o, o]
-    fn get(&self) -> A;
+trait Setter<A> {
     fn set(&mut self, a: A);
 }
 
-#[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR [o, o]
-    // Here, the use of `A` in the method bound *does* affect
-    // variance.  Think of it as if the method requested a dictionary
-    // for `T:Getter<A>`.  Since this dictionary is an input, it is
-    // contravariant, and the Getter is covariant w/r/t A, yielding an
-    // overall contravariant result.
-    fn do_it<T:Getter<A>>(&self);
-}
-
-#[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR [o, o]
-    fn do_it<T:Setter<A>>(&self);
-}
-
 #[rustc_variance]
 struct TestObject<A, R> { //~ ERROR [o, o]
     n: Box<Setter<A>+Send>,
diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs
new file mode 100644 (file)
index 0000000..7cc547d
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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(alloc, allocator_api, heap_api, unique)]
+
+extern crate alloc;
+
+use alloc::heap::HeapAlloc;
+use alloc::allocator::Alloc;
+
+fn main() {
+    unsafe {
+        let ptr = HeapAlloc.alloc_one::<i32>().unwrap_or_else(|e| {
+            HeapAlloc.oom(e)
+        });
+        *ptr.as_ptr() = 4;
+        assert_eq!(*ptr.as_ptr(), 4);
+        HeapAlloc.dealloc_one(ptr);
+    }
+}
index 587fb3f80d6c8a810910d7a31aa2c0451202ef8e..d8d42f2cba281c5cc75095f97d19633fe9cfae43 100644 (file)
@@ -15,8 +15,6 @@
 pub trait Foo {
     type A;
     fn boo(&self) -> Self::A;
-
-    fn baz(_: Self::Target) where Self: Deref {}
 }
 
 impl Foo for isize {
index 91bfc2f9201b7796cbf713117c3e6618b295ffb3..18b2fbe015b425ee89c4c4cb87242fbf975a022a 100644 (file)
@@ -45,8 +45,8 @@ fn write(&mut self, bytes: &[u8]) {
     }
 }
 
-fn fake_hash(v: &mut Vec<u8>, e: E) {
-    e.hash(&mut FakeHasher(v));
+fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
+    a.hash(&mut FakeHasher(v));
 }
 
 fn main() {
@@ -69,4 +69,13 @@ fn main() {
     fake_hash(&mut va, E::A);
     fake_hash(&mut vb, E::B);
     assert!(va != vb);
+
+    // issue #39137: single variant enum hash should not hash discriminant
+    #[derive(Hash)]
+    enum SingleVariantEnum {
+        A(u8),
+    }
+    let mut v = vec![];
+    fake_hash(&mut v, SingleVariantEnum::A(17));
+    assert_eq!(vec![17], v);
 }
index 6725a0c547f1dfaeb2e680c29774a68ee830c31b..bdcd3eecc696a6ffdc35805aeedc9ce21cdb3101 100644 (file)
@@ -106,6 +106,18 @@ fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) {
     }
 }
 
+fn field_assignment(a: &Allocator, c0: bool) {
+    let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc());
+
+    x.1 = a.alloc();
+    x.1 = a.alloc();
+
+    let f = (x.0).0;
+    if c0 {
+        (x.0).0 = f;
+    }
+}
+
 fn assignment2(a: &Allocator, c0: bool, c1: bool) {
     let mut _v = a.alloc();
     let mut _w = a.alloc();
@@ -207,5 +219,8 @@ fn main() {
     run_test(|a| struct_dynamic_drop(a, true, true, false));
     run_test(|a| struct_dynamic_drop(a, true, true, true));
 
+    run_test(|a| field_assignment(a, false));
+    run_test(|a| field_assignment(a, true));
+
     run_test_nopanic(|a| union1(a));
 }
diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs
new file mode 100644 (file)
index 0000000..e602fb2
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+
+#![feature(rand, std_panic)]
+
+use std::env::*;
+use std::__rand as rand;
+use std::__rand::Rng;
+use std::iter::repeat;
+use std::ffi::{OsString, OsStr};
+
+
+fn make_rand_name() -> OsString {
+    let mut rng = rand::thread_rng();
+    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+                                 .collect::<String>());
+    let n = OsString::from(n);
+    assert!(var_os(&n).is_none());
+    n
+}
+
+fn eq(a: Option<OsString>, b: Option<&str>) {
+    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
+}
+
+#[test]
+fn test_set_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    eq(var_os(&n), Some("VALUE"));
+}
+
+#[test]
+fn test_remove_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_set_var_overwrite() {
+    let n = make_rand_name();
+    set_var(&n, "1");
+    set_var(&n, "2");
+    eq(var_os(&n), Some("2"));
+    set_var(&n, "");
+    eq(var_os(&n), Some(""));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_var_big() {
+    let mut s = "".to_string();
+    let mut i = 0;
+    while i < 100 {
+        s.push_str("aaaaaaaaaa");
+        i += 1;
+    }
+    let n = make_rand_name();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_env_set_get_huge() {
+    let n = make_rand_name();
+    let s = repeat("x").take(10000).collect::<String>();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_env_set_var() {
+    let n = make_rand_name();
+
+    let mut e = vars_os();
+    set_var(&n, "VALUE");
+    assert!(!e.any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+
+    assert!(vars_os().any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+}
diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs
new file mode 100644 (file)
index 0000000..5ed1295
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    s.clone();
+}
+fn main() {}
diff --git a/src/test/run-pass/macro-pat-neg-lit.rs b/src/test/run-pass/macro-pat-neg-lit.rs
new file mode 100644 (file)
index 0000000..43ac697
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! enum_number {
+    ($name:ident { $($variant:ident = $value:expr, )* }) => {
+        enum $name {
+            $($variant = $value,)*
+        }
+
+        fn foo(value: i32) -> Option<$name> {
+            match value {
+                $( $value => Some($name::$variant), )*
+                _ => None
+            }
+        }
+    }
+}
+
+enum_number!(Change {
+    Down = -1,
+    None = 0,
+    Up = 1,
+});
+
+fn main() {
+    if let Some(Change::Down) = foo(-1) {} else { panic!() }
+}
+
index a131dcbe4ddc3e65d188f6a958d903b706f188c0..b3785d898baa42fe40c27c89a1e5b0fafd0c7b50 100644 (file)
@@ -10,8 +10,6 @@
 
 // ignore-emscripten
 
-#![feature(command_envs)]
-
 use std::process::Command;
 use std::env;
 use std::collections::HashMap;
diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs
new file mode 100644 (file)
index 0000000..aa9cf76
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+#![feature(allow_fail)]
+
+#[test]
+#[allow_fail]
+fn test1() {
+    panic!();
+}
+
+#[test]
+#[allow_fail]
+fn test2() {
+    assert!(true);
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs
new file mode 100644 (file)
index 0000000..2a6c71d
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+fn main() {
+    loop {
+        true //~  ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr
new file mode 100644 (file)
index 0000000..a770ebe
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-do.rs:13:9
+   |
+13 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs
new file mode 100644 (file)
index 0000000..8728685
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+struct r;
+
+impl Drop for r {
+    fn drop(&mut self) {
+        true //~  ERROR mismatched types
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr
new file mode 100644 (file)
index 0000000..b114686
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-res.rs:15:9
+   |
+15 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs
new file mode 100644 (file)
index 0000000..a0fb470
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+fn main() {
+    while true {
+        true //~  ERROR mismatched types
+             //~| expected type `()`
+             //~| found type `bool`
+             //~| expected (), found bool
+    }
+}
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr
new file mode 100644 (file)
index 0000000..31ec7cd
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-while.rs:13:9
+   |
+13 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs
new file mode 100644 (file)
index 0000000..530a0e4
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f() -> String {  //~ ERROR mismatched types
+    0u8;
+    "bla".to_string();  //~ HELP consider removing this semicolon
+}
+
+fn g() -> String {  //~ ERROR mismatched types
+    "this won't work".to_string();
+    "removeme".to_string(); //~ HELP consider removing this semicolon
+}
+
+fn main() {}
diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr
new file mode 100644 (file)
index 0000000..282583d
--- /dev/null
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:11:18
+   |
+11 |   fn f() -> String {  //~ ERROR mismatched types
+   |  __________________^
+12 | |     0u8;
+13 | |     "bla".to_string();  //~ HELP consider removing this semicolon
+   | |                      - help: consider removing this semicolon
+14 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:16:18
+   |
+16 |   fn g() -> String {  //~ ERROR mismatched types
+   |  __________________^
+17 | |     "this won't work".to_string();
+18 | |     "removeme".to_string(); //~ HELP consider removing this semicolon
+   | |                           - help: consider removing this semicolon
+19 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs
new file mode 100644 (file)
index 0000000..192f78e
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+fn blah() -> i32 { //~ ERROR mismatched types
+    1
+
+    ; //~ HELP consider removing this semicolon:
+}
+
+fn main() { }
diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr
new file mode 100644 (file)
index 0000000..ed61ec6
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11714.rs:11:18
+   |
+11 |   fn blah() -> i32 { //~ ERROR mismatched types
+   |  __________________^
+12 | |     1
+13 | |
+14 | |     ; //~ HELP consider removing this semicolon:
+   | |     - help: consider removing this semicolon
+15 | | }
+   | |_^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs
new file mode 100644 (file)
index 0000000..9406199
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #13428
+
+fn foo() -> String {  //~ ERROR mismatched types
+    format!("Hello {}",
+            "world")
+    // Put the trailing semicolon on its own line to test that the
+    // note message gets the offending semicolon exactly
+    ;   //~ HELP consider removing this semicolon
+}
+
+fn bar() -> String {  //~ ERROR mismatched types
+    "foobar".to_string()
+    ;   //~ HELP consider removing this semicolon
+}
+
+pub fn main() {}
diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr
new file mode 100644 (file)
index 0000000..5e8d92f
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:13:20
+   |
+13 |   fn foo() -> String {  //~ ERROR mismatched types
+   |  ____________________^
+14 | |     format!("Hello {}",
+15 | |             "world")
+16 | |     // Put the trailing semicolon on its own line to test that the
+17 | |     // note message gets the offending semicolon exactly
+18 | |     ;   //~ HELP consider removing this semicolon
+   | |     - help: consider removing this semicolon
+19 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:21:20
+   |
+21 |   fn bar() -> String {  //~ ERROR mismatched types
+   |  ____________________^
+22 | |     "foobar".to_string()
+23 | |     ;   //~ HELP consider removing this semicolon
+   | |     - help: consider removing this semicolon
+24 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs
new file mode 100644 (file)
index 0000000..e4ed87c
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+mod a {
+  pub enum Enum {
+    EnumStructVariant { x: u8, y: u8, z: u8 }
+  }
+
+  pub fn get_enum_struct_variant() -> () {
+    Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `a::Enum`
+    //~| expected (), found enum `a::Enum`
+  }
+}
+
+mod b {
+  mod test {
+    use a;
+
+    fn test_enum_struct_variant() {
+      let enum_struct_variant = ::a::get_enum_struct_variant();
+      match enum_struct_variant {
+        a::Enum::EnumStructVariant { x, y, z } => {
+        //~^ ERROR mismatched types
+        //~| expected type `()`
+        //~| found type `a::Enum`
+        //~| expected (), found enum `a::Enum`
+        }
+      }
+    }
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr
new file mode 100644 (file)
index 0000000..72ff859
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:17:5
+   |
+17 |     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:32:9
+   |
+32 |         a::Enum::EnumStructVariant { x, y, z } => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs
new file mode 100644 (file)
index 0000000..9df6358
--- /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.
+
+fn foo(x: i32) {
+    |y| x + y
+//~^ ERROR: mismatched types
+}
+
+fn main() {
+    let x = foo(5)(2);
+//~^ ERROR: expected function, found `()`
+}
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
new file mode 100644 (file)
index 0000000..e4367f1
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-20862.rs:12:5
+   |
+11 | fn foo(x: i32) {
+   |                - possibly return type missing here?
+12 |     |y| x + y
+   |     ^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]`
+
+error[E0618]: expected function, found `()`
+  --> $DIR/issue-20862.rs:17:13
+   |
+17 |     let x = foo(5)(2);
+   |             ^^^^^^^^^
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs
new file mode 100644 (file)
index 0000000..81f66e3
--- /dev/null
@@ -0,0 +1,27 @@
+// 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::ops::Add;
+
+trait Scalar {}
+impl Scalar for f64 {}
+
+struct Bob;
+
+impl<RHS: Scalar> Add <RHS> for Bob {
+  type Output = Bob;
+  fn add(self, rhs : RHS) -> Bob { Bob }
+}
+
+fn main() {
+  let b = Bob + 3.5;
+  b + 3 //~ ERROR E0277
+  //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr
new file mode 100644 (file)
index 0000000..3921a30
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
+  --> $DIR/issue-22645.rs:25:5
+   |
+25 |   b + 3 //~ ERROR E0277
+   |     ^ the trait `Scalar` is not implemented for `{integer}`
+   |
+   = help: the following implementations were found:
+             <f64 as Scalar>
+   = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-22645.rs:25:3
+   |
+25 |   b + 3 //~ ERROR E0277
+   |   ^^^^^ expected (), found struct `Bob`
+   |
+   = note: expected type `()`
+              found type `Bob`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
new file mode 100644 (file)
index 0000000..7928c04
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+trait A {
+    fn a(&self) {
+        || self.b()
+        //~^ ERROR no method named `b` found for type `&Self` in the current scope
+        //~| ERROR mismatched types
+    }
+}
+fn main() {}
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
new file mode 100644 (file)
index 0000000..c6ab4cb
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0599]: no method named `b` found for type `&Self` in the current scope
+  --> $DIR/issue-3563.rs:13:17
+   |
+13 |         || self.b()
+   |                 ^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-3563.rs:13:9
+   |
+12 |     fn a(&self) {
+   |                 - possibly return type missing here?
+13 |         || self.b()
+   |         ^^^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs
new file mode 100644 (file)
index 0000000..1cbb758
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+fn main() {
+    &panic!()
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `&_`
+    //~| expected (), found reference
+}
diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr
new file mode 100644 (file)
index 0000000..bffe2a8
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5500.rs:12:5
+   |
+12 |     &panic!()
+   |     ^^^^^^^^^ expected (), found reference
+   |
+   = note: expected type `()`
+              found type `&_`
+
+error: aborting due to previous error(s)
+
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs
new file mode 100644 (file)
index 0000000..291b7a1
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-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 we do some basic error correcton in the tokeniser (and don't spew
+// too many bogus errors).
+
+fn foo() -> usize {
+    3
+}
+
+fn bar() {
+    foo()
+}
+
+fn main() {
+    bar()
+}
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr
new file mode 100644 (file)
index 0000000..18d0cc4
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/unexpected-return-on-unit.rs:19:5
+   |
+19 |     foo()
+   |     ^^^^^ expected (), found usize
+   |
+   = note: expected type `()`
+              found type `usize`
+help: did you mean to add a semicolon here?
+   |     foo();
+help: possibly return type missing here?
+   | fn bar() -> usize {
+
+error: aborting due to previous error(s)
+
index e96bc425e0b45fad9e2732758f5160d7cabec188..49e8b9febc2bb6a4e44bc093bffe9e705d2a7b28 100644 (file)
@@ -4,16 +4,12 @@ error[E0308]: mismatched types
 13 |   fn plus_one(x: i32) -> i32 {
    |  ____________________________^
 14 | |     x + 1;
+   | |          - help: consider removing this semicolon
 15 | | }
    | |_^ expected i32, found ()
    |
    = note: expected type `i32`
               found type `()`
-help: consider removing this semicolon:
-  --> $DIR/coercion-missing-tail-expected-type.rs:14:10
-   |
-14 |     x + 1;
-   |          ^
 
 error[E0308]: mismatched types
   --> $DIR/coercion-missing-tail-expected-type.rs:17:29
@@ -21,16 +17,12 @@ error[E0308]: mismatched types
 17 |   fn foo() -> Result<u8, u64> {
    |  _____________________________^
 18 | |     Ok(1);
+   | |          - help: consider removing this semicolon
 19 | | }
    | |_^ expected enum `std::result::Result`, found ()
    |
    = note: expected type `std::result::Result<u8, u64>`
               found type `()`
-help: consider removing this semicolon:
-  --> $DIR/coercion-missing-tail-expected-type.rs:18:10
-   |
-18 |     Ok(1);
-   |          ^
 
 error: aborting due to previous error(s)
 
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
new file mode 100644 (file)
index 0000000..d71da58
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Forbidding a group (here, `unused`) overrules subsequent allowance of both
+// the group, and an individual lint in the group (here, `unused_variables`);
+// and, forbidding an individual lint (here, `non_snake_case`) overrules
+// subsequent allowance of a lint group containing it (here, `bad_style`). See
+// Issue #42873.
+
+#![forbid(unused, non_snake_case)]
+
+#[allow(unused, unused_variables, bad_style)]
+fn main() {
+    println!("hello forbidden world")
+}
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
new file mode 100644 (file)
index 0000000..831b3f6
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:19:17
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |                 ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:35
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |                                   ^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to previous error(s)
+
index 58cd130dcc2534d52f3f827e44b4953b83f15824..879acbcf9d9d1cd198a603df218e067a894c0dab 100644 (file)
@@ -1,4 +1,4 @@
-error: casting `*const U` as `*const V` is invalid
+error[E0606]: casting `*const U` as `*const V` is invalid
   --> $DIR/cast-rfc0401.rs:13:5
    |
 13 |     u as *const V
@@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const U` as `*const str` is invalid
+error[E0606]: casting `*const U` as `*const str` is invalid
   --> $DIR/cast-rfc0401.rs:18:5
    |
 18 |     u as *const str
@@ -20,49 +20,59 @@ error[E0609]: no field `f` on type `fn() {main}`
 75 |     let _ = main.f as *const u32;
    |                  ^
 
-error: non-scalar cast: `*const u8` as `&u8`
+error[E0605]: non-primitive cast: `*const u8` as `&u8`
   --> $DIR/cast-rfc0401.rs:39:13
    |
 39 |     let _ = v as &u8;
    |             ^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `E`
+error[E0605]: non-primitive cast: `*const u8` as `E`
   --> $DIR/cast-rfc0401.rs:40:13
    |
 40 |     let _ = v as E;
    |             ^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `fn()`
+error[E0605]: non-primitive cast: `*const u8` as `fn()`
   --> $DIR/cast-rfc0401.rs:41:13
    |
 41 |     let _ = v as fn();
    |             ^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `(u32,)`
+error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
   --> $DIR/cast-rfc0401.rs:42:13
    |
 42 |     let _ = v as (u32,);
    |             ^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
+error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
   --> $DIR/cast-rfc0401.rs:43:13
    |
 43 |     let _ = Some(&v) as *const u8;
    |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: casting `*const u8` as `f32` is invalid
+error[E0606]: casting `*const u8` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:45:13
    |
 45 |     let _ = v as f32;
    |             ^^^^^^^^
 
-error: casting `fn() {main}` as `f64` is invalid
+error[E0606]: casting `fn() {main}` as `f64` is invalid
   --> $DIR/cast-rfc0401.rs:46:13
    |
 46 |     let _ = main as f64;
    |             ^^^^^^^^^^^
 
-error: casting `&*const u8` as `usize` is invalid
+error[E0606]: casting `&*const u8` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:47:13
    |
 47 |     let _ = &v as usize;
@@ -70,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid
    |
    = help: cast through a raw pointer first
 
-error: casting `f32` as `*const u8` is invalid
+error[E0606]: casting `f32` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:48:13
    |
 48 |     let _ = f as *const u8;
@@ -92,13 +102,13 @@ error[E0054]: cannot cast as `bool`
    |
    = help: compare with zero instead
 
-error: only `u8` can be cast as `char`, not `u32`
+error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:51:13
    |
 51 |     let _ = 0x61u32 as char;
    |             ^^^^^^^^^^^^^^^
 
-error: casting `bool` as `f32` is invalid
+error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:53:13
    |
 53 |     let _ = false as f32;
@@ -106,7 +116,7 @@ error: casting `bool` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `E` as `f32` is invalid
+error[E0606]: casting `E` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:54:13
    |
 54 |     let _ = E::A as f32;
@@ -114,7 +124,7 @@ error: casting `E` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `char` as `f32` is invalid
+error[E0606]: casting `char` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:55:13
    |
 55 |     let _ = 'a' as f32;
@@ -122,67 +132,67 @@ error: casting `char` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `bool` as `*const u8` is invalid
+error[E0606]: casting `bool` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:57:13
    |
 57 |     let _ = false as *const u8;
    |             ^^^^^^^^^^^^^^^^^^
 
-error: casting `E` as `*const u8` is invalid
+error[E0606]: casting `E` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:58:13
    |
 58 |     let _ = E::A as *const u8;
    |             ^^^^^^^^^^^^^^^^^
 
-error: casting `char` as `*const u8` is invalid
+error[E0606]: casting `char` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:59:13
    |
 59 |     let _ = 'a' as *const u8;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `usize` as `*const [u8]` is invalid
+error[E0606]: casting `usize` as `*const [u8]` is invalid
   --> $DIR/cast-rfc0401.rs:61:13
    |
 61 |     let _ = 42usize as *const [u8];
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
-error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
   --> $DIR/cast-rfc0401.rs:62:13
    |
 62 |     let _ = v as *const [u8];
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `&Foo` as `*const str` is invalid
+error[E0606]: casting `&Foo` as `*const str` is invalid
   --> $DIR/cast-rfc0401.rs:64:13
    |
 64 |     let _ = foo as *const str;
    |             ^^^^^^^^^^^^^^^^^
 
-error: casting `&Foo` as `*mut str` is invalid
+error[E0606]: casting `&Foo` as `*mut str` is invalid
   --> $DIR/cast-rfc0401.rs:65:13
    |
 65 |     let _ = foo as *mut str;
    |             ^^^^^^^^^^^^^^^
 
-error: casting `fn() {main}` as `*mut str` is invalid
+error[E0606]: casting `fn() {main}` as `*mut str` is invalid
   --> $DIR/cast-rfc0401.rs:66:13
    |
 66 |     let _ = main as *mut str;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `&f32` as `*mut f32` is invalid
+error[E0606]: casting `&f32` as `*mut f32` is invalid
   --> $DIR/cast-rfc0401.rs:67:13
    |
 67 |     let _ = &f as *mut f32;
    |             ^^^^^^^^^^^^^^
 
-error: casting `&f32` as `*const f64` is invalid
+error[E0606]: casting `&f32` as `*const f64` is invalid
   --> $DIR/cast-rfc0401.rs:68:13
    |
 68 |     let _ = &f as *const f64;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `*const [i8]` as `usize` is invalid
+error[E0606]: casting `*const [i8]` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:69:13
    |
 69 |     let _ = fat_sv as usize;
@@ -190,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid
    |
    = help: cast through a thin pointer first
 
-error: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
   --> $DIR/cast-rfc0401.rs:78:13
    |
 78 |     let _ = cf as *const [u16];
@@ -198,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const Foo` as `*const Bar` is invalid
   --> $DIR/cast-rfc0401.rs:79:13
    |
 79 |     let _ = cf as *const Bar;
@@ -224,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: required for the cast to the object type `Foo`
 
-error: casting `&{float}` as `f32` is invalid
+error[E0606]: casting `&{float}` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:81:30
    |
 81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs
new file mode 100644 (file)
index 0000000..8c61fc6
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    for x in 0..3 {
+        x //~ ERROR mismatched types
+        //~| NOTE expected ()
+        //~| NOTE expected type `()`
+    }
+}
diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr
new file mode 100644 (file)
index 0000000..6787fe9
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/for-loop-has-unit-body.rs:13:9
+   |
+13 |         x //~ ERROR mismatched types
+   |         ^ expected (), found integral variable
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error(s)
+
index cbce4f810c5312469d168dd7e31798c42ead8e28..083c1f953330c0dd4baab3a4dcc4e62dcfb0bd71 100644 (file)
@@ -1,6 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/issue-19109.rs:14:5
    |
+13 | fn function(t: &mut Trait) {
+   |                            - help: possibly return type missing here? `-> *mut Trait `
 14 |     t as *mut Trait
    |     ^^^^^^^^^^^^^^^ expected (), found *-ptr
    |
index dc3764a376cde4d8443f780a649f194146a1a445..9da9042e78ed13b891e2899e6e9bccd36b368a0f 100644 (file)
@@ -7,7 +7,7 @@ error[E0308]: mismatched types
 37 |     write!(hello);
    |     -------------- in this macro invocation
 
-error: non-scalar cast: `{integer}` as `()`
+error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:32:19
    |
 32 |     ($x:expr) => ($x as ())
@@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()`
 ...
 38 |     cast!(2);
    |     --------- in this macro invocation
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
 error: aborting due to previous error(s)
 
index d234c8538fe27a23d8128a70fbb317c7b31043d3..53e9cb2177892eec1f54842fee6091ad2c747b56 100644 (file)
@@ -35,7 +35,9 @@ error[E0308]: mismatched types
   --> $DIR/token-error-correct-3.rs:25:13
    |
 25 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;`
+   |             |
+   |             expected (), found enum `std::result::Result`
    |
    = note: expected type `()`
               found type `std::result::Result<bool, std::io::Error>`
index 534ce68621ce4feec0b7e8627cfd3b077d4f3900..abf01e1eddb3145c83f71b469ea7bee37141e5e1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 534ce68621ce4feec0b7e8627cfd3b077d4f3900
+Subproject commit abf01e1eddb3145c83f71b469ea7bee37141e5e1
index c88ffba357a70f777d3cc728568e6ccc5bebfaab..b4663b0ee6c00677313f7e3c590f1e3e0cdf6420 100644 (file)
@@ -476,6 +476,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
             name: make_test_name(config, testpaths),
             ignore: ignore,
             should_panic: should_panic,
+            allow_fail: false,
         },
         testfn: make_test_closure(config, testpaths),
     }
index 0692e07253fbeefc6bde8c4196f92b7083b89f43..4961609c77fbd99e055eed2d16ad21b0c6219fe9 100644 (file)
@@ -692,7 +692,7 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
         }
 
         if !debugger_run_result.status.success() {
-            self.fatal("gdb failed to execute");
+            self.fatal_proc_rec("gdb failed to execute", &debugger_run_result);
         }
 
         self.check_debugger_output(&debugger_run_result, &check_lines);