]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #47440 - mark-i-m:zunpretty, r=nikomatsakis
authorkennytm <kennytm@gmail.com>
Tue, 23 Jan 2018 09:03:35 +0000 (17:03 +0800)
committerGitHub <noreply@github.com>
Tue, 23 Jan 2018 09:03:35 +0000 (17:03 +0800)
Change the --unpretty flag to -Z unpretty

First PR :smile: !

-Z unpretty no longer requires -Z unstable-options.

Also, I mildly changed the syntax of the flag to match the other -Z flags. All uses of the flag take the form `unpretty=something` where something can either `string` or `string=string` (see the help messages of the CLI).

Fix #47395

r? @nikomatsakis EDIT: apparently rust-highfive doesn't see edits...

209 files changed:
.mailmap
CONTRIBUTING.md
src/Cargo.lock
src/bootstrap/channel.rs
src/bootstrap/check.rs
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/ci/init_repo.sh
src/doc/index.md
src/doc/nomicon
src/doc/unstable-book/src/language-features/repr-transparent.md [new file with mode: 0644]
src/liballoc/allocator.rs
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/btree/set.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/linked_list.rs
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/liballoc/slice.rs
src/liballoc/vec.rs
src/liballoc/vec_deque.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/result.rs
src/libcore/tests/lib.rs
src/libcore/tests/ptr.rs
src/librustc/diagnostics.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
src/librustc/infer/error_reporting/nice_region_error/mod.rs
src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs [new file with mode: 0644]
src/librustc/lib.rs
src/librustc/mir/visit.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/mod.rs
src/librustc_apfloat/ieee.rs
src/librustc_back/target/aarch64_unknown_cloudabi.rs
src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
src/librustc_back/target/i686_unknown_cloudabi.rs
src/librustc_back/target/x86_64_unknown_cloudabi.rs
src/librustc_const_eval/_match.rs
src/librustc_data_structures/array_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/target_features.rs [deleted file]
src/librustc_driver/test.rs
src/librustc_incremental/assert_module_sources.rs [new file with mode: 0644]
src/librustc_incremental/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_metadata/creader.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/renumber.rs
src/librustc_mir/borrow_check/nll/type_check/input_output.rs
src/librustc_mir/borrow_check/nll/universal_regions.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/util/pretty.rs
src/librustc_plugin/load.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_trans/abi.rs
src/librustc_trans/allocator.rs
src/librustc_trans/assert_module_sources.rs [deleted file]
src/librustc_trans/back/command.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/symbol_names.rs [deleted file]
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/diagnostics.rs
src/librustc_trans/lib.rs
src/librustc_trans/llvm_util.rs
src/librustc_trans/mir/mod.rs
src/librustc_trans/symbol_names_test.rs [deleted file]
src/librustc_trans/trans_item.rs
src/librustc_trans_utils/Cargo.toml
src/librustc_trans_utils/diagnostics.rs [new file with mode: 0644]
src/librustc_trans_utils/lib.rs
src/librustc_trans_utils/symbol_names.rs [new file with mode: 0644]
src/librustc_trans_utils/symbol_names_test.rs [new file with mode: 0644]
src/librustc_trans_utils/trans_crate.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/core.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/libserialize/leb128.rs
src/libserialize/opaque.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/lib.rs
src/libstd/net/addr.rs
src/libstd/net/mod.rs
src/libstd/panic.rs
src/libstd/path.rs
src/libstd/sys/unix/l4re.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys_common/net.rs
src/libsyntax/ast.rs
src/libsyntax/attr.rs
src/libsyntax/feature_gate.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/parser.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/test/codegen/issue-47278.rs [new file with mode: 0644]
src/test/codegen/repr-transparent-aggregates-1.rs [new file with mode: 0644]
src/test/codegen/repr-transparent-aggregates-2.rs [new file with mode: 0644]
src/test/codegen/repr-transparent.rs [new file with mode: 0644]
src/test/compile-fail/E0185.rs
src/test/compile-fail/E0618.rs
src/test/compile-fail/E0659.rs [new file with mode: 0644]
src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs [deleted file]
src/test/compile-fail/issue-7573.rs [deleted file]
src/test/compile-fail/lint-ctypes.rs
src/test/compile-fail/lint-unnecessary-parens.rs
src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs [new file with mode: 0644]
src/test/compile-fail/regions-escape-bound-fn-2.rs [deleted file]
src/test/compile-fail/regions-escape-bound-fn.rs [deleted file]
src/test/compile-fail/regions-escape-unboxed-closure.rs [deleted file]
src/test/compile-fail/repr-transparent-other-items.rs [new file with mode: 0644]
src/test/compile-fail/repr-transparent-other-reprs.rs [new file with mode: 0644]
src/test/compile-fail/repr-transparent.rs [new file with mode: 0644]
src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs [new file with mode: 0644]
src/test/incremental-fulldeps/incremental_proc_macro.rs [new file with mode: 0644]
src/test/run-make/hotplug_codegen_backend/Makefile [new file with mode: 0644]
src/test/run-make/hotplug_codegen_backend/some_crate.rs [new file with mode: 0644]
src/test/run-make/hotplug_codegen_backend/the_backend.rs [new file with mode: 0644]
src/test/run-make/issue-19371/foo.rs
src/test/run-make/llvm-phase/Makefile [deleted file]
src/test/run-make/llvm-phase/test.rs [deleted file]
src/test/run-make/long-linker-command-lines-cmd-exe/Makefile [new file with mode: 0644]
src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat [new file with mode: 0644]
src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass/allocator-alloc-one.rs
src/test/run-pass/generator/yield-subtype.rs
src/test/run-pass/issue-23433.rs
src/test/run-pass/issue-46920-byte-array-patterns.rs [new file with mode: 0644]
src/test/run-pass/issue-46964.rs [new file with mode: 0644]
src/test/run-pass/nll/issue-47153-generic-const.rs [new file with mode: 0644]
src/test/run-pass/result-opt-conversions.rs [new file with mode: 0644]
src/test/rustdoc-js/from_u.js
src/test/ui/block-result/issue-20862.stderr
src/test/ui/borrowck/issue-45983.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-45983.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-7573.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-7573.stderr [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-bound-fn-2.rs [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-bound-fn-2.stderr [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-bound-fn.rs [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-bound-fn.stderr [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-unboxed-closure.rs [new file with mode: 0644]
src/test/ui/borrowck/regions-escape-unboxed-closure.stderr [new file with mode: 0644]
src/test/ui/closure-expected-type/expect-region-supply-region.rs [new file with mode: 0644]
src/test/ui/closure-expected-type/expect-region-supply-region.stderr [new file with mode: 0644]
src/test/ui/empty-struct-unit-expr.rs
src/test/ui/empty-struct-unit-expr.stderr
src/test/ui/feature-gate-repr_transparent.rs [new file with mode: 0644]
src/test/ui/feature-gate-repr_transparent.stderr [new file with mode: 0644]
src/test/ui/imports/duplicate.stderr
src/test/ui/imports/macro-paths.stderr
src/test/ui/imports/macros.stderr
src/test/ui/imports/shadow_builtin_macros.stderr
src/test/ui/issue-10969.stderr
src/test/ui/issue-47623.rs [new file with mode: 0644]
src/test/ui/issue-47623.stderr [new file with mode: 0644]
src/test/ui/mismatched_types/closure-arg-count.rs
src/test/ui/mismatched_types/closure-arg-count.stderr
src/test/ui/nll/generator-distinct-lifetime.rs [new file with mode: 0644]
src/test/ui/resolve/privacy-enum-ctor.rs [new file with mode: 0644]
src/test/ui/resolve/privacy-enum-ctor.stderr [new file with mode: 0644]
src/test/ui/resolve/privacy-struct-ctor.rs
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/resolve/tuple-struct-alias.stderr
src/test/ui/suggestions/numeric-cast-2.rs [new file with mode: 0644]
src/test/ui/suggestions/numeric-cast-2.stderr [new file with mode: 0644]
src/test/ui/suggestions/numeric-cast.rs [new file with mode: 0644]
src/test/ui/suggestions/numeric-cast.stderr [new file with mode: 0644]
src/tools/rustbook/Cargo.toml
src/tools/rustbook/src/main.rs
src/tools/rustfmt
src/tools/tidy/src/lib.rs

index c2d3b28602bccbcbcf3254f213f408204cd3ee90..9034aae171417c449ebdfc8c88f500bd28f459e8 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -41,11 +41,12 @@ Boris Egorov <jightuse@gmail.com> <egorov@linux.com>
 Brandon Sanderson <singingboyo@gmail.com> Brandon Sanderson <singingboyo@hotmail.com>
 Brett Cannon <brett@python.org> Brett Cannon <brettcannon@users.noreply.github.com>
 Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com>
+Brian Anderson <banderson@mozilla.com> <banderson@mozilla.org>
 Brian Dawn <brian.t.dawn@gmail.com>
 Brian Leibig <brian@brianleibig.com> Brian Leibig <brian.leibig@gmail.com>
 Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
-Carol (Nichols || Goulding) <carol.nichols@gmail.com>
-Carol (Nichols || Goulding) <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> <cnichols@thinkthroughmath.com>
+Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol Nichols <carol.nichols@gmail.com>
 Carol Willing <carolcode@willingconsulting.com>
 Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
 Chris Pressey <cpressey@gmail.com>
index 54c507304f9f112493d9ea399fdf042de499f5aa..70376c120fc0a4fc8ae663cfa2f762eec0b18df7 100644 (file)
@@ -301,12 +301,12 @@ It's absolutely fine to have multiple build directories with different
 [pull-requests]: #pull-requests
 
 Pull requests are the primary mechanism we use to change Rust. GitHub itself
-has some [great documentation][pull-requests] on using the Pull Request feature.
+has some [great documentation][about-pull-requests] on using the Pull Request feature.
 We use the "fork and pull" model [described here][development-models], where
 contributors push changes to their personal fork and create pull requests to
 bring those changes into the source repository.
 
-[pull-requests]: https://help.github.com/articles/about-pull-requests/
+[about-pull-requests]: https://help.github.com/articles/about-pull-requests/
 [development-models]: https://help.github.com/articles/about-collaborative-development-models/
 
 Please make pull requests against the `master` branch.
index 6ce1e3a7bc6af90d2ca91f1b558cfc4aef644243..ae9e755b7a0e4de08b2c56a80ed15fa05d28dbb9 100644 (file)
@@ -1108,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.0.26"
+version = "0.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1614,7 +1614,7 @@ dependencies = [
  "rls-rustc 0.1.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.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.3.4",
+ "rustfmt-nightly 0.3.6",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1674,7 +1674,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1700,6 +1700,72 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_errors"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-serialize"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-ap-syntax"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-syntax_pos"
+version = "12.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-demangle"
 version = "0.1.5"
@@ -1944,7 +2010,6 @@ dependencies = [
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
- "rustc_trans_utils 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -2067,6 +2132,8 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_incremental 0.0.0",
+ "rustc_mir 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2118,7 +2185,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.3.4"
+version = "0.3.6"
 dependencies = [
  "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2126,9 +2193,12 @@ dependencies = [
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2910,7 +2980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum markup5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "047150a0e03b57e638fc45af33a0b63a0362305d5b9f92ecef81df472a4cceb0"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8a1ac668292d1e5c7b1c6fd64f70d3a85105b8069a89558a0d67bdb2ff298ca1"
+"checksum mdbook 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "1ee8ba20c002000546681dc78d7f7e91fd35832058b1e2fdd492ca842bb6e9be"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
@@ -2964,6 +3034,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
+"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e"
+"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc"
+"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0"
+"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604"
+"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c"
+"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
index 4e3f3a00b15eee4b1c975207e789a761583941bf..e412dd9e3e67010a6f0f2645c17e018494a21296 100644 (file)
 // The version number
 pub const CFG_RELEASE_NUM: &str = "1.25.0";
 
-// An optional number to put after the label, e.g. '.2' -> '-beta.2'
-// Be sure to make this starts with a dot to conform to semver pre-release
-// versions (section 9)
-pub const CFG_PRERELEASE_VERSION: &str = ".1";
-
 pub struct GitInfo {
     inner: Option<Info>,
 }
index 78ad71172a848dedda6af4a9ecc3b96b8ecec189..1187376e1775311abc6c8c750d64e4d093cc3b2f 100644 (file)
@@ -605,6 +605,11 @@ fn run(self, builder: &Builder) {
         mode: "compile-fail",
         suite: "compile-fail-fulldeps",
     },
+    Test {
+        path: "src/test/incremental-fulldeps",
+        mode: "incremental",
+        suite: "incremental-fulldeps",
+    },
     Test { path: "src/test/run-make", mode: "run-make", suite: "run-make" },
     Test { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" },
 
index 7f0613aabe6588a9803e39436737856c822fcd4a..224b31ef26872469d600fc87ff4b99cb006fb0bf 100644 (file)
@@ -1652,7 +1652,6 @@ fn add_env(build: &Build, cmd: &mut Command, target: Interned<String>) {
     cmd.env("CFG_RELEASE_INFO", build.rust_version())
        .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
        .env("CFG_RELEASE", build.rust_release())
-       .env("CFG_PRERELEASE_VERSION", channel::CFG_PRERELEASE_VERSION)
        .env("CFG_VER_MAJOR", parts.next().unwrap())
        .env("CFG_VER_MINOR", parts.next().unwrap())
        .env("CFG_VER_PATCH", parts.next().unwrap())
index 948bf29bbacc3b2d6a30b5d489ac124269751a4a..3738828a4baed00011f87aea1fe41ec37c06f980 100644 (file)
 #[cfg(unix)]
 extern crate libc;
 
-use std::cell::RefCell;
+use std::cell::{RefCell, Cell};
 use std::collections::{HashSet, HashMap};
 use std::env;
 use std::fs::{self, File};
@@ -250,6 +250,7 @@ pub struct Build {
     is_sudo: bool,
     ci_env: CiEnv,
     delayed_failures: RefCell<Vec<String>>,
+    prerelease_version: Cell<Option<u32>>,
 }
 
 #[derive(Debug)]
@@ -335,6 +336,7 @@ pub fn new(config: Config) -> Build {
             is_sudo,
             ci_env: CiEnv::current(),
             delayed_failures: RefCell::new(Vec::new()),
+            prerelease_version: Cell::new(None),
         }
     }
 
@@ -774,12 +776,59 @@ fn openssl_install_dir(&self, target: Interned<String>) -> Option<PathBuf> {
     fn release(&self, num: &str) -> String {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
-            "beta" => format!("{}-beta{}", num, channel::CFG_PRERELEASE_VERSION),
+            "beta" => format!("{}-beta.{}", num, self.beta_prerelease_version()),
             "nightly" => format!("{}-nightly", num),
             _ => format!("{}-dev", num),
         }
     }
 
+    fn beta_prerelease_version(&self) -> u32 {
+        if let Some(s) = self.prerelease_version.get() {
+            return s
+        }
+
+        let beta = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("beta")
+                .current_dir(&self.src)
+        );
+        let beta = beta.trim().split_whitespace().next().unwrap();
+        let master = output(
+            Command::new("git")
+                .arg("ls-remote")
+                .arg("origin")
+                .arg("master")
+                .current_dir(&self.src)
+        );
+        let master = master.trim().split_whitespace().next().unwrap();
+
+        // Figure out where the current beta branch started.
+        let base = output(
+            Command::new("git")
+                .arg("merge-base")
+                .arg(beta)
+                .arg(master)
+                .current_dir(&self.src),
+        );
+        let base = base.trim();
+
+        // Next figure out how many merge commits happened since we branched off
+        // beta. That's our beta number!
+        let count = output(
+            Command::new("git")
+                .arg("rev-list")
+                .arg("--count")
+                .arg("--merges")
+                .arg(format!("{}...HEAD", base))
+                .current_dir(&self.src),
+        );
+        let n = count.trim().parse().unwrap();
+        self.prerelease_version.set(Some(n));
+        n
+    }
+
     /// Returns the value of `release` above for Rust itself.
     fn rust_release(&self) -> String {
         self.release(channel::CFG_RELEASE_NUM)
index e073a3d99c157dc765293c8ca770a63a34a3ec33..14a1906ff421dd24996e619005ff2cdfeaca90f2 100755 (executable)
@@ -36,6 +36,12 @@ fi
 rm -rf "$CACHE_DIR"
 mkdir "$CACHE_DIR"
 
+# On the beta channel we'll be automatically calculating the prerelease version
+# via the git history, so unshallow our shallow clone from CI.
+if grep -q RUST_RELEASE_CHANNEL=beta src/ci/run.sh; then
+  git fetch origin --unshallow beta master
+fi
+
 travis_fold start update_cache
 travis_time_start
 
index 3784cc3c4b497fcb171297d0b136d306307656da..3add2774105e07a0fdffa81dd95561fb800d792c 100644 (file)
@@ -28,6 +28,7 @@ Rust provides a number of book-length sets of documentation, collectively
 nicknamed 'The Rust Bookshelf.'
 
 * [The Rust Programming Language][book] teaches you how to program in Rust.
+* [Rust By Example][rbe] teaches you how to program in Rust using editable examples.
 * [The Cargo Book][cargo-book] is a guide to Cargo, Rust's build tool and dependency manager.
 * [The Unstable Book][unstable-book] has documentation for unstable features.
 * [The Rustonomicon][nomicon] is your guidebook to the dark arts of unsafe Rust.
@@ -51,6 +52,7 @@ before this policy was put into place. That work is being tracked
 [refchecklist]: https://github.com/rust-lang-nursery/reference/issues/9
 [err]: error-index.html
 [book]: book/index.html
+[rbe]: rust-by-example/index.html
 [nomicon]: nomicon/index.html
 [unstable-book]: unstable-book/index.html
 [rustdoc-book]: rustdoc/index.html
index 2f7b05fd5939aa49d52c4ab309b9a47776ba7bd8..fec3182d0b0a3cf8122e192b3270064a5b19be5b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2f7b05fd5939aa49d52c4ab309b9a47776ba7bd8
+Subproject commit fec3182d0b0a3cf8122e192b3270064a5b19be5b
diff --git a/src/doc/unstable-book/src/language-features/repr-transparent.md b/src/doc/unstable-book/src/language-features/repr-transparent.md
new file mode 100644 (file)
index 0000000..62202dc
--- /dev/null
@@ -0,0 +1,176 @@
+# `repr_transparent`
+
+The tracking issue for this feature is: [#43036]
+
+[#43036]: https://github.com/rust-lang/rust/issues/43036
+
+------------------------
+
+This feature enables the `repr(transparent)` attribute on structs, which enables
+the use of newtypes without the usual ABI implications of wrapping the value in
+a struct.
+
+## Background
+
+It's sometimes useful to add additional type safety by introducing *newtypes*.
+For example, code that handles numeric quantities in different units such as
+millimeters, centimeters, grams, kilograms, etc. may want to use the type system
+to rule out mistakes such as adding millimeters to grams:
+
+```rust
+use std::ops::Add;
+
+struct Millimeters(f64);
+struct Grams(f64);
+
+impl Add<Millimeters> for Millimeters {
+    type Output = Millimeters;
+
+    fn add(self, other: Millimeters) -> Millimeters {
+        Millimeters(self.0 + other.0)
+    }
+}
+
+// Likewise: impl Add<Grams> for Grams {}
+```
+
+Other uses of newtypes include using `PhantomData` to add lifetimes to raw
+pointers or to implement the "phantom types" pattern. See the [PhantomData]
+documentation and [the Nomicon][nomicon-phantom] for more details.
+
+The added type safety is especially useful when interacting with C or other
+languages. However, in those cases we need to ensure the newtypes we add do not
+introduce incompatibilities with the C ABI.
+
+## Newtypes in FFI
+
+Luckily, `repr(C)` newtypes are laid out just like the type they wrap on all
+platforms which Rust currently supports, and likely on many more. For example,
+consider this C declaration:
+
+```C
+struct Object {
+    double weight; //< in grams
+    double height; //< in millimeters
+    // ...
+}
+
+void frobnicate(struct Object *);
+```
+
+While using this C code from Rust, we could add `repr(C)` to the `Grams` and
+`Millimeters` newtypes introduced above and use them to add some type safety
+while staying compatible with the memory layout of `Object`:
+
+```rust,no_run
+#[repr(C)]
+struct Grams(f64);
+
+#[repr(C)]
+struct Millimeters(f64);
+
+#[repr(C)]
+struct Object {
+    weight: Grams,
+    height: Millimeters,
+    // ...
+}
+
+extern {
+    fn frobnicate(_: *mut Object);
+}
+```
+
+This works even when adding some `PhantomData` fields, because they are
+zero-sized and therefore don't have to affect the memory layout.
+
+However, there's more to the ABI than just memory layout: there's also the
+question of how function call arguments and return values are passed. Many
+common ABI treat a struct containing a single field differently from that field
+itself, at least when the field is a scalar (e.g., integer or float or pointer).
+
+To continue the above example, suppose the C library also exposes a function
+like this:
+
+```C
+double calculate_weight(double height);
+```
+
+Using our newtypes on the Rust side like this will cause an ABI mismatch on many
+platforms:
+
+```rust,ignore
+extern {
+    fn calculate_weight(height: Millimeters) -> Grams;
+}
+```
+
+For example, on x86_64 Linux, Rust will pass the argument in an integer
+register, while the C function expects the argument to be in a floating-point
+register. Likewise, the C function will return the result in a floating-point
+register while Rust will expect it in an integer register.
+
+Note that this problem is not specific to floats: To give another example,
+32-bit x86 linux will pass and return `struct Foo(i32);` on the stack while
+`i32` is placed in registers.
+
+## Enter `repr(transparent)`
+
+So while `repr(C)` happens to do the right thing with respect to memory layout,
+it's not quite the right tool for newtypes in FFI. Instead of declaring a C
+struct, we need to communicate to the Rust compiler that our newtype is just for
+type safety on the Rust side. This is what `repr(transparent)` does.
+
+The attribute can be applied to a newtype-like structs that contains a single
+field. It indicates that the newtype should be represented exactly like that
+field's type, i.e., the newtype should be ignored for ABI purpopses: not only is
+it laid out the same in memory, it is also passed identically in function calls.
+
+In the above example, the ABI mismatches can be prevented by making the newtypes
+`Grams` and `Millimeters` transparent like this:
+
+```rust
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f64);
+
+#[repr(transparent)]
+struct Millimeters(f64);
+```
+
+In addition to that single field, any number of zero-sized fields are permitted,
+including but not limited to `PhantomData`:
+
+```rust
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+struct Foo { /* ... */ }
+
+#[repr(transparent)]
+struct FooPtrWithLifetime<'a>(*const Foo, PhantomData<&'a Foo>);
+
+#[repr(transparent)]
+struct NumberWithUnit<T, U>(T, PhantomData<U>);
+
+struct CustomZst;
+
+#[repr(transparent)]
+struct PtrWithCustomZst<'a> {
+    ptr: FooPtrWithLifetime<'a>,
+    some_marker: CustomZst,
+}
+```
+
+Transparent structs can be nested: `PtrWithCustomZst` is also represented
+exactly like `*const Foo`.
+
+Because `repr(transparent)` delegates all representation concerns to another
+type, it is incompatible with all other `repr(..)` attributes. It also cannot be
+applied to enums, unions, empty structs, structs whose fields are all
+zero-sized, or structs with *multiple* non-zero-sized fields.
+
+[PhantomData]: https://doc.rust-lang.org/std/marker/struct.PhantomData.html
+[nomicon-phantom]: https://doc.rust-lang.org/nomicon/phantom-data.html
index c2a8f5f8ff957e5004b9b2cf95ea0cb4d6dfe448..55e8c0b430f52c76f6b63617d8b6a0b90bef91d3 100644 (file)
@@ -19,7 +19,7 @@
 use core::fmt;
 use core::mem;
 use core::usize;
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull};
 
 /// Represents the combination of a starting address and
 /// a total capacity of the returned block.
@@ -895,12 +895,12 @@ unsafe fn shrink_in_place(&mut self,
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
+    fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            unsafe { self.alloc(k).map(|p| Unique::new_unchecked(p as *mut T)) }
+            unsafe { self.alloc(k).map(|p| NonNull::new_unchecked(p as *mut T)) }
         } else {
             Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
         }
@@ -923,7 +923,7 @@ fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
     /// * `ptr` must denote a block of memory currently allocated via this allocator
     ///
     /// * the layout of `T` must *fit* that block of memory.
-    unsafe fn dealloc_one<T>(&mut self, ptr: Unique<T>)
+    unsafe fn dealloc_one<T>(&mut self, ptr: NonNull<T>)
         where Self: Sized
     {
         let raw_ptr = ptr.as_ptr() as *mut u8;
@@ -963,7 +963,7 @@ unsafe fn dealloc_one<T>(&mut self, ptr: Unique<T>)
     /// Clients wishing to abort computation in response to an
     /// allocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
-    fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
+    fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         match Layout::array::<T>(n) {
@@ -971,7 +971,7 @@ fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
                 unsafe {
                     self.alloc(layout.clone())
                         .map(|p| {
-                            Unique::new_unchecked(p as *mut T)
+                            NonNull::new_unchecked(p as *mut T)
                         })
                 }
             }
@@ -1012,15 +1012,15 @@ fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
     /// reallocation error are encouraged to call the allocator's `oom`
     /// method, rather than directly invoking `panic!` or similar.
     unsafe fn realloc_array<T>(&mut self,
-                               ptr: Unique<T>,
+                               ptr: NonNull<T>,
                                n_old: usize,
-                               n_new: usize) -> Result<Unique<T>, AllocErr>
+                               n_new: usize) -> Result<NonNull<T>, AllocErr>
         where Self: Sized
     {
         match (Layout::array::<T>(n_old), Layout::array::<T>(n_new), ptr.as_ptr()) {
             (Some(ref k_old), Some(ref k_new), ptr) if k_old.size() > 0 && k_new.size() > 0 => {
                 self.realloc(ptr as *mut u8, k_old.clone(), k_new.clone())
-                    .map(|p|Unique::new_unchecked(p as *mut T))
+                    .map(|p| NonNull::new_unchecked(p as *mut T))
             }
             _ => {
                 Err(AllocErr::invalid_input("invalid layout for realloc_array"))
@@ -1048,7 +1048,7 @@ unsafe fn realloc_array<T>(&mut self,
     /// constraints.
     ///
     /// Always returns `Err` on arithmetic overflow.
-    unsafe fn dealloc_array<T>(&mut self, ptr: Unique<T>, n: usize) -> Result<(), AllocErr>
+    unsafe fn dealloc_array<T>(&mut self, ptr: NonNull<T>, n: usize) -> Result<(), AllocErr>
         where Self: Sized
     {
         let raw_ptr = ptr.as_ptr() as *mut u8;
index 185af8835d1e49d14da8033e13deefa5329e8a71..6a77bf64baee5f9ffe5d9670ad5eab3405abade5 100644 (file)
@@ -25,7 +25,7 @@
 use core::mem::{self, align_of_val, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 use core::marker::{Unsize, PhantomData};
 use core::hash::{Hash, Hasher};
 use core::{isize, usize};
 /// [rc_examples]: ../../std/rc/index.html#examples
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T: ?Sized> {
-    ptr: Shared<ArcInner<T>>,
+    ptr: NonNull<ArcInner<T>>,
     phantom: PhantomData<T>,
 }
 
@@ -234,7 +234,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "arc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
-    ptr: Shared<ArcInner<T>>,
+    ptr: NonNull<ArcInner<T>>,
 }
 
 #[stable(feature = "arc_weak", since = "1.4.0")]
@@ -286,7 +286,7 @@ pub fn new(data: T) -> Arc<T> {
             weak: atomic::AtomicUsize::new(1),
             data,
         };
-        Arc { ptr: Shared::from(Box::into_unique(x)), phantom: PhantomData }
+        Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData }
     }
 
     /// Returns the contained value, if the `Arc` has exactly one strong reference.
@@ -397,7 +397,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
 
         Arc {
-            ptr: Shared::new_unchecked(arc_ptr),
+            ptr: NonNull::new_unchecked(arc_ptr),
             phantom: PhantomData,
         }
     }
@@ -582,7 +582,7 @@ fn from_box(v: Box<T>) -> Arc<T> {
             // Free the allocation without dropping its contents
             box_free(bptr);
 
-            Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -609,7 +609,7 @@ unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
             &mut (*ptr).data as *mut [T] as *mut T,
             v.len());
 
-        Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+        Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
     }
 }
 
@@ -669,7 +669,7 @@ fn drop(&mut self) {
             // All clear. Forget the guard so it doesn't free the new ArcInner.
             mem::forget(guard);
 
-            Arc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -991,11 +991,11 @@ impl<T> Weak<T> {
     pub fn new() -> Weak<T> {
         unsafe {
             Weak {
-                ptr: Shared::from(Box::into_unique(box ArcInner {
+                ptr: Box::into_raw_non_null(box ArcInner {
                     strong: atomic::AtomicUsize::new(0),
                     weak: atomic::AtomicUsize::new(1),
                     data: uninitialized(),
-                })),
+                }),
             }
         }
     }
index 6f125cdba8190d671c7ac4c1f46272ca7d94b50d..bfe23ddeca32828ed5097d8d7cd54249ed834cb0 100644 (file)
@@ -68,7 +68,7 @@
 use core::mem;
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer};
-use core::ptr::{self, Unique};
+use core::ptr::{self, NonNull, Unique};
 use core::convert::From;
 use str::from_boxed_utf8_unchecked;
 
@@ -269,38 +269,7 @@ impl<T: ?Sized> Box<T> {
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
-        Box::from_unique(Unique::new_unchecked(raw))
-    }
-
-    /// Constructs a `Box` from a `Unique<T>` pointer.
-    ///
-    /// After calling this function, the memory is owned by a `Box` and `T` can
-    /// then be destroyed and released upon drop.
-    ///
-    /// # Safety
-    ///
-    /// A `Unique<T>` can be safely created via [`Unique::new`] and thus doesn't
-    /// necessarily own the data pointed to nor is the data guaranteed to live
-    /// as long as the pointer.
-    ///
-    /// [`Unique::new`]: ../../core/ptr/struct.Unique.html#method.new
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(unique)]
-    ///
-    /// fn main() {
-    ///     let x = Box::new(5);
-    ///     let ptr = Box::into_unique(x);
-    ///     let x = unsafe { Box::from_unique(ptr) };
-    /// }
-    /// ```
-    #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-               issue = "27730")]
-    #[inline]
-    pub unsafe fn from_unique(u: Unique<T>) -> Self {
-        Box(u)
+        Box(Unique::new_unchecked(raw))
     }
 
     /// Consumes the `Box`, returning the wrapped raw pointer.
@@ -326,40 +295,42 @@ pub unsafe fn from_unique(u: Unique<T>) -> Self {
     #[stable(feature = "box_raw", since = "1.4.0")]
     #[inline]
     pub fn into_raw(b: Box<T>) -> *mut T {
-        Box::into_unique(b).as_ptr()
+        Box::into_raw_non_null(b).as_ptr()
     }
 
-    /// Consumes the `Box`, returning the wrapped pointer as `Unique<T>`.
+    /// Consumes the `Box`, returning the wrapped pointer as `NonNull<T>`.
     ///
     /// After calling this function, the caller is responsible for the
     /// memory previously managed by the `Box`. In particular, the
     /// caller should properly destroy `T` and release the memory. The
-    /// proper way to do so is to either convert the `Unique<T>` pointer:
-    ///
-    /// - Into a `Box` with the [`Box::from_unique`] function.
-    ///
-    /// - Into a raw pointer and back into a `Box` with the [`Box::from_raw`]
-    ///   function.
+    /// proper way to do so is to convert the `NonNull<T>` pointer
+    /// into a raw pointer and back into a `Box` with the [`Box::from_raw`]
+    /// function.
     ///
     /// Note: this is an associated function, which means that you have
-    /// to call it as `Box::into_unique(b)` instead of `b.into_unique()`. This
+    /// to call it as `Box::into_raw_non_null(b)`
+    /// instead of `b.into_raw_non_null()`. This
     /// is so that there is no conflict with a method on the inner type.
     ///
-    /// [`Box::from_unique`]: struct.Box.html#method.from_unique
     /// [`Box::from_raw`]: struct.Box.html#method.from_raw
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(unique)]
+    /// #![feature(box_into_raw_non_null)]
     ///
     /// fn main() {
     ///     let x = Box::new(5);
-    ///     let ptr = Box::into_unique(x);
+    ///     let ptr = Box::into_raw_non_null(x);
     /// }
     /// ```
-    #[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-               issue = "27730")]
+    #[unstable(feature = "box_into_raw_non_null", issue = "47336")]
+    #[inline]
+    pub fn into_raw_non_null(b: Box<T>) -> NonNull<T> {
+        Box::into_unique(b).into()
+    }
+
+    #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
     #[inline]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
         let unique = b.0;
index e094070fc3dd10cb864e31e49cb142005ed8d00a..327eaaf465130313227ef553b821486559666df0 100644 (file)
@@ -658,26 +658,26 @@ pub fn append(&mut self, other: &mut Self) {
     /// Basic usage:
     ///
     /// ```
-    /// use std::collections::BTreeMap;
+    /// use std::collections::BTreeSet;
     ///
-    /// let mut a = BTreeMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    /// a.insert(3, "c");
-    /// a.insert(17, "d");
-    /// a.insert(41, "e");
+    /// let mut a = BTreeSet::new();
+    /// a.insert(1);
+    /// a.insert(2);
+    /// a.insert(3);
+    /// a.insert(17);
+    /// a.insert(41);
     ///
     /// let b = a.split_off(&3);
     ///
     /// assert_eq!(a.len(), 2);
     /// assert_eq!(b.len(), 3);
     ///
-    /// assert_eq!(a[&1], "a");
-    /// assert_eq!(a[&2], "b");
+    /// assert!(a.contains(&1));
+    /// assert!(a.contains(&2));
     ///
-    /// assert_eq!(b[&3], "c");
-    /// assert_eq!(b[&17], "d");
-    /// assert_eq!(b[&41], "e");
+    /// assert!(b.contains(&3));
+    /// assert!(b.contains(&17));
+    /// assert!(b.contains(&41));
     /// ```
     #[stable(feature = "btree_split_off", since = "1.11.0")]
     pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self where T: Borrow<Q> {
index b2bd9d7d8fafadf9006240a698d0609f0f6a0bd5..37af9ea529532f7b045baa3cd00cc16e1eb554f4 100644 (file)
@@ -232,7 +232,7 @@ unsafe fn shrink_in_place(&mut self,
 ///
 /// This preserves the non-null invariant for types like `Box<T>`. The address
 /// may overlap with non-zero-size memory allocations.
-#[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")]
+#[rustc_deprecated(since = "1.19", reason = "Use Unique/NonNull::empty() instead")]
 #[unstable(feature = "heap_api", issue = "27700")]
 pub const EMPTY: *mut () = 1 as *mut ();
 
index 6ee4f802802abe93ba18795385a2d4ccad943d8a..5139e54b5604a30d5e97fd92d4b32b4eb45ed3d3 100644 (file)
@@ -84,6 +84,7 @@
 #![cfg_attr(test, feature(rand, test))]
 #![feature(allow_internal_unstable)]
 #![feature(ascii_ctype)]
+#![feature(box_into_raw_non_null)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_target_has_atomic)]
 #![feature(pattern)]
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
+#![feature(ptr_internals)]
 #![feature(rustc_attrs)]
-#![feature(shared)]
 #![feature(slice_get_slice)]
 #![feature(slice_patterns)]
 #![feature(slice_rsplit)]
 #![feature(trusted_len)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unique)]
 #![feature(unsize)]
 #![feature(allocator_internals)]
 #![feature(on_unimplemented)]
index 3ac5a85d721a14d8bcdd8bfc6c41ab4dc88d5853..3cc810a055f3efc3eeee5b7e60752847964f75e9 100644 (file)
@@ -29,7 +29,7 @@
 use core::marker::PhantomData;
 use core::mem;
 use core::ops::{BoxPlace, InPlace, Place, Placer};
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 
 use boxed::{Box, IntermediateBox};
 use super::SpecExtend;
 /// more memory efficient and make better use of CPU cache.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LinkedList<T> {
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
     marker: PhantomData<Box<Node<T>>>,
 }
 
 struct Node<T> {
-    next: Option<Shared<Node<T>>>,
-    prev: Option<Shared<Node<T>>>,
+    next: Option<NonNull<Node<T>>>,
+    prev: Option<NonNull<Node<T>>>,
     element: T,
 }
 
@@ -65,8 +65,8 @@ struct Node<T> {
 /// [`LinkedList`]: struct.LinkedList.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
     marker: PhantomData<&'a Node<T>>,
 }
@@ -98,8 +98,8 @@ fn clone(&self) -> Self {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     list: &'a mut LinkedList<T>,
-    head: Option<Shared<Node<T>>>,
-    tail: Option<Shared<Node<T>>>,
+    head: Option<NonNull<Node<T>>>,
+    tail: Option<NonNull<Node<T>>>,
     len: usize,
 }
 
@@ -157,7 +157,7 @@ fn push_front_node(&mut self, mut node: Box<Node<T>>) {
         unsafe {
             node.next = self.head;
             node.prev = None;
-            let node = Some(Shared::from(Box::into_unique(node)));
+            let node = Some(Box::into_raw_non_null(node));
 
             match self.head {
                 None => self.tail = node,
@@ -192,7 +192,7 @@ fn push_back_node(&mut self, mut node: Box<Node<T>>) {
         unsafe {
             node.next = None;
             node.prev = self.tail;
-            let node = Some(Shared::from(Box::into_unique(node)));
+            let node = Some(Box::into_raw_non_null(node));
 
             match self.tail {
                 None => self.head = node,
@@ -225,7 +225,7 @@ fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
     ///
     /// Warning: this will not check that the provided node belongs to the current list.
     #[inline]
-    unsafe fn unlink_node(&mut self, mut node: Shared<Node<T>>) {
+    unsafe fn unlink_node(&mut self, mut node: NonNull<Node<T>>) {
         let node = node.as_mut();
 
         match node.prev {
@@ -986,11 +986,11 @@ pub fn insert_next(&mut self, element: T) {
                     Some(prev) => prev,
                 };
 
-                let node = Some(Shared::from(Box::into_unique(box Node {
+                let node = Some(Box::into_raw_non_null(box Node {
                     next: Some(head),
                     prev: Some(prev),
                     element,
-                })));
+                }));
 
                 prev.as_mut().next = node;
                 head.as_mut().prev = node;
@@ -1038,7 +1038,7 @@ pub struct DrainFilter<'a, T: 'a, F: 'a>
     where F: FnMut(&mut T) -> bool,
 {
     list: &'a mut LinkedList<T>,
-    it: Option<Shared<Node<T>>>,
+    it: Option<NonNull<Node<T>>>,
     pred: F,
     idx: usize,
     old_len: usize,
index dbf1fb1367dda257ecb88aa7118f0be03f1b0f80..621e190696137c7fe7d792733ab0f7978acaa23f 100644 (file)
@@ -322,7 +322,7 @@ pub fn double(&mut self) {
                     // would cause overflow
                     let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
                     match self.a.alloc_array::<T>(new_cap) {
-                        Ok(ptr) => (new_cap, ptr),
+                        Ok(ptr) => (new_cap, ptr.into()),
                         Err(e) => self.a.oom(e),
                     }
                 }
index 59079f9ba76bc3e66df50bd8517c0c60f9391ec6..1fa5d34cb5787147091617c92c1499a0e1506cf5 100644 (file)
 use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
-use core::ptr::{self, Shared};
+use core::ptr::{self, NonNull};
 use core::convert::From;
 
 use heap::{Heap, Alloc, Layout, box_free};
@@ -282,7 +282,7 @@ struct RcBox<T: ?Sized> {
 /// [get_mut]: #method.get_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
-    ptr: Shared<RcBox<T>>,
+    ptr: NonNull<RcBox<T>>,
     phantom: PhantomData<T>,
 }
 
@@ -311,11 +311,11 @@ pub fn new(value: T) -> Rc<T> {
             // pointers, which ensures that the weak destructor never frees
             // the allocation while the strong destructor is running, even
             // if the weak pointer is stored inside the strong one.
-            ptr: Shared::from(Box::into_unique(box RcBox {
+            ptr: Box::into_raw_non_null(box RcBox {
                 strong: Cell::new(1),
                 weak: Cell::new(1),
                 value,
-            })),
+            }),
             phantom: PhantomData,
         }
     }
@@ -428,7 +428,7 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
         let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
 
         Rc {
-            ptr: Shared::new_unchecked(rc_ptr),
+            ptr: NonNull::new_unchecked(rc_ptr),
             phantom: PhantomData,
         }
     }
@@ -649,7 +649,7 @@ pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<Any>> {
                 let raw: *const RcBox<Any> = self.ptr.as_ptr();
                 forget(self);
                 Ok(Rc {
-                    ptr: Shared::new_unchecked(raw as *const RcBox<T> as *mut _),
+                    ptr: NonNull::new_unchecked(raw as *const RcBox<T> as *mut _),
                     phantom: PhantomData,
                 })
             }
@@ -695,7 +695,7 @@ fn from_box(v: Box<T>) -> Rc<T> {
             // Free the allocation without dropping its contents
             box_free(bptr);
 
-            Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -722,7 +722,7 @@ unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
             &mut (*ptr).value as *mut [T] as *mut T,
             v.len());
 
-        Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+        Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
     }
 }
 
@@ -781,7 +781,7 @@ fn drop(&mut self) {
             // All clear. Forget the guard so it doesn't free the new RcBox.
             forget(guard);
 
-            Rc { ptr: Shared::new_unchecked(ptr), phantom: PhantomData }
+            Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
         }
     }
 }
@@ -1160,7 +1160,7 @@ fn from(mut v: Vec<T>) -> Rc<[T]> {
 /// [`None`]: ../../std/option/enum.Option.html#variant.None
 #[stable(feature = "rc_weak", since = "1.4.0")]
 pub struct Weak<T: ?Sized> {
-    ptr: Shared<RcBox<T>>,
+    ptr: NonNull<RcBox<T>>,
 }
 
 #[stable(feature = "rc_weak", since = "1.4.0")]
@@ -1190,11 +1190,11 @@ impl<T> Weak<T> {
     pub fn new() -> Weak<T> {
         unsafe {
             Weak {
-                ptr: Shared::from(Box::into_unique(box RcBox {
+                ptr: Box::into_raw_non_null(box RcBox {
                     strong: Cell::new(0),
                     weak: Cell::new(1),
                     value: uninitialized(),
-                })),
+                }),
             }
         }
     }
index 861f72bcf88ee42b2e5fcf711a9fc1a1a6c358f4..028983de556f20c0e0e3cd4f5482057c085e5266 100644 (file)
@@ -630,6 +630,8 @@ pub fn windows(&self, size: usize) -> Windows<T> {
     /// assert_eq!(iter.next().unwrap(), &['m']);
     /// assert!(iter.next().is_none());
     /// ```
+    ///
+    /// [`exact_chunks`]: #method.exact_chunks
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
@@ -660,6 +662,8 @@ pub fn chunks(&self, chunk_size: usize) -> Chunks<T> {
     /// assert_eq!(iter.next().unwrap(), &['r', 'e']);
     /// assert!(iter.next().is_none());
     /// ```
+    ///
+    /// [`chunks`]: #method.chunks
     #[unstable(feature = "exact_chunks", issue = "47115")]
     #[inline]
     pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
@@ -692,6 +696,8 @@ pub fn exact_chunks(&self, chunk_size: usize) -> ExactChunks<T> {
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 3]);
     /// ```
+    ///
+    /// [`exact_chunks_mut`]: #method.exact_chunks_mut
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
@@ -728,6 +734,8 @@ pub fn chunks_mut(&mut self, chunk_size: usize) -> ChunksMut<T> {
     /// }
     /// assert_eq!(v, &[1, 1, 2, 2, 0]);
     /// ```
+    ///
+    /// [`chunks_mut`]: #method.chunks_mut
     #[unstable(feature = "exact_chunks", issue = "47115")]
     #[inline]
     pub fn exact_chunks_mut(&mut self, chunk_size: usize) -> ExactChunksMut<T> {
index 301e44632b82379394c980ca6e2b1e9d9a7eb1c2..b14b9d747654817343bbad6d36806f4514e76653 100644 (file)
@@ -78,7 +78,7 @@
 use core::ops::{InPlace, Index, IndexMut, Place, Placer};
 use core::ops;
 use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
 use core::slice;
 
 use borrow::ToOwned;
@@ -1124,7 +1124,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
                 tail_start: end,
                 tail_len: len - end,
                 iter: range_slice.iter(),
-                vec: Shared::from(self),
+                vec: NonNull::from(self),
             }
         }
     }
@@ -1745,7 +1745,7 @@ fn into_iter(mut self) -> IntoIter<T> {
             let cap = self.buf.cap();
             mem::forget(self);
             IntoIter {
-                buf: Shared::new_unchecked(begin),
+                buf: NonNull::new_unchecked(begin),
                 phantom: PhantomData,
                 cap,
                 ptr: begin,
@@ -2267,7 +2267,7 @@ fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Cow<'a, [T]> {
 /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<T> {
-    buf: Shared<T>,
+    buf: NonNull<T>,
     phantom: PhantomData<T>,
     cap: usize,
     ptr: *const T,
@@ -2442,7 +2442,7 @@ pub struct Drain<'a, T: 'a> {
     tail_len: usize,
     /// Current remaining range to remove
     iter: slice::Iter<'a, T>,
-    vec: Shared<Vec<T>>,
+    vec: NonNull<Vec<T>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
index f56aa23a4eb2f83f78b704ff025791bd86e22b00..9259138bab0a9f891914a65f3710e03caff56ebf 100644 (file)
@@ -23,7 +23,7 @@
 use core::mem;
 use core::ops::{Index, IndexMut, Place, Placer, InPlace};
 use core::ptr;
-use core::ptr::Shared;
+use core::ptr::NonNull;
 use core::slice;
 
 use core::hash::{Hash, Hasher};
@@ -895,7 +895,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
         self.head = drain_tail;
 
         Drain {
-            deque: Shared::from(&mut *self),
+            deque: NonNull::from(&mut *self),
             after_tail: drain_head,
             after_head: head,
             iter: Iter {
@@ -906,7 +906,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
         }
     }
 
-    /// Clears the buffer, removing all values.
+    /// Clears the `VecDeque`, removing all values.
     ///
     /// # Examples
     ///
@@ -1624,10 +1624,10 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
         return elem;
     }
 
-    /// Splits the collection into two at the given index.
+    /// Splits the `VecDeque` into two at the given index.
     ///
-    /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
-    /// and the returned `Self` contains elements `[at, len)`.
+    /// Returns a newly allocated `VecDeque`. `self` contains elements `[0, at)`,
+    /// and the returned `VecDeque` contains elements `[at, len)`.
     ///
     /// Note that the capacity of `self` does not change.
     ///
@@ -1635,7 +1635,7 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
     ///
     /// # Panics
     ///
-    /// Panics if `at > len`
+    /// Panics if `at > len`.
     ///
     /// # Examples
     ///
@@ -1815,7 +1815,8 @@ pub fn place_front(&mut self) -> PlaceFront<T> {
 
 impl<T: Clone> VecDeque<T> {
     /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
-    /// either by removing excess elements or by appending clones of `value` to the back.
+    /// either by removing excess elements from the back or by appending clones of `value`
+    /// to the back.
     ///
     /// # Examples
     ///
@@ -2154,7 +2155,7 @@ pub struct Drain<'a, T: 'a> {
     after_tail: usize,
     after_head: usize,
     iter: Iter<'a, T>,
-    deque: Shared<VecDeque<T>>,
+    deque: NonNull<VecDeque<T>>,
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
@@ -2390,7 +2391,7 @@ impl<T> IntoIterator for VecDeque<T> {
     type Item = T;
     type IntoIter = IntoIter<T>;
 
-    /// Consumes the list into a front-to-back iterator yielding elements by
+    /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
     /// value.
     fn into_iter(self) -> IntoIter<T> {
         IntoIter { inner: self }
@@ -2480,7 +2481,7 @@ fn from(other: VecDeque<T>) -> Self {
             if other.is_contiguous() {
                 ptr::copy(buf.offset(tail as isize), buf, len);
             } else {
-                if (tail - head) >= cmp::min((cap - tail), head) {
+                if (tail - head) >= cmp::min(cap - tail, head) {
                     // There is enough free space in the centre for the shortest block so we can
                     // do this in at most three copy moves.
                     if (cap - tail) > head {
index 15181dab8531cb9330fff8574e5cc9c112657708..b8fe28d0f0d71b6fa7a8c07084464754acb979d2 100644 (file)
@@ -881,6 +881,35 @@ pub fn unwrap_or_default(self) -> T {
     }
 }
 
+impl<T, E> Option<Result<T, E>> {
+    /// Transposes an `Option` of a `Result` into a `Result` of an `Option`.
+    ///
+    /// `None` will be mapped to `Ok(None)`.
+    /// `Some(Ok(_))` and `Some(Err(_))` will be mapped to `Ok(Some(_))` and `Err(_)`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(transpose_result)]
+    ///
+    /// #[derive(Debug, Eq, PartialEq)]
+    /// struct SomeErr;
+    ///
+    /// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
+    /// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
+    /// assert_eq!(x, y.transpose());
+    /// ```
+    #[inline]
+    #[unstable(feature = "transpose_result", issue = "47338")]
+    pub fn transpose(self) -> Result<Option<T>, E> {
+        match self {
+            Some(Ok(x)) => Ok(Some(x)),
+            Some(Err(e)) => Err(e),
+            None => Ok(None),
+        }
+    }
+}
+
 // This is a separate function to reduce the code size of .expect() itself.
 #[inline(never)]
 #[cold]
index 7f7246df8f2a72d2d6a97f4730ea15a6cefd347c..fab5832d905df8262bfbaa85971ef913e8711844 100644 (file)
@@ -2321,7 +2321,7 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 /// its owning Unique.
 ///
 /// If you're uncertain of whether it's correct to use `Unique` for your purposes,
-/// consider using `Shared`, which has weaker semantics.
+/// consider using `NonNull`, which has weaker semantics.
 ///
 /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
 /// is never dereferenced. This is so that enums may use this forbidden value
@@ -2330,9 +2330,9 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 ///
 /// Unlike `*mut T`, `Unique<T>` is covariant over `T`. This should always be correct
 /// for any type which upholds Unique's aliasing requirements.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "unique", reason = "needs an RFC to flesh out design",
-           issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0",
+           reason = "use NonNull instead and consider PhantomData<T> \
+                     (if you also use #[may_dangle]), Send, and/or Sync")]
 pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     // NOTE: this marker has no consequences for variance, but is necessary
@@ -2343,26 +2343,34 @@ pub struct Unique<T: ?Sized> {
     _marker: PhantomData<T>,
 }
 
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<T: ?Sized> fmt::Debug for Unique<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&self.as_ptr(), f)
+    }
+}
+
 /// `Unique` pointers are `Send` if `T` is `Send` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: Sized> Unique<T> {
     /// Creates a new `Unique` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
+    // FIXME: rename to dangling() to match NonNull?
     pub fn empty() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
@@ -2371,14 +2379,13 @@ pub fn empty() -> Self {
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Unique<T> {
     /// Creates a new `Unique`.
     ///
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    #[unstable(feature = "unique", issue = "27730")]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
@@ -2397,7 +2404,7 @@ pub fn as_ptr(self) -> *mut T {
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
     pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
@@ -2406,112 +2413,130 @@ pub unsafe fn as_ref(&self) -> &T {
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
     pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_ptr()
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Clone for Unique<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> Copy for Unique<T> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsize<U> { }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: ?Sized> fmt::Pointer for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
     fn from(reference: &'a mut T) -> Self {
         Unique { pointer: NonZero::from(reference), _marker: PhantomData }
     }
 }
 
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
     fn from(reference: &'a T) -> Self {
         Unique { pointer: NonZero::from(reference), _marker: PhantomData }
     }
 }
 
+#[unstable(feature = "ptr_internals", issue = "0")]
+impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
+    fn from(p: NonNull<T>) -> Self {
+        Unique { pointer: p.pointer, _marker: PhantomData }
+    }
+}
+
+/// Previous name of `NonNull`.
+#[rustc_deprecated(since = "1.24", reason = "renamed to `NonNull`")]
+#[unstable(feature = "shared", issue = "27730")]
+pub type Shared<T> = NonNull<T>;
+
 /// `*mut T` but non-zero and covariant.
 ///
 /// This is often the correct thing to use when building data structures using
 /// raw pointers, but is ultimately more dangerous to use because of its additional
-/// properties. If you're not sure if you should use `Shared<T>`, just use `*mut T`!
+/// properties. If you're not sure if you should use `NonNull<T>`, just use `*mut T`!
 ///
 /// Unlike `*mut T`, the pointer must always be non-null, even if the pointer
 /// is never dereferenced. This is so that enums may use this forbidden value
-/// as a discriminant -- `Option<Shared<T>>` has the same size as `Shared<T>`.
+/// as a discriminant -- `Option<NonNull<T>>` has the same size as `NonNull<T>`.
 /// However the pointer may still dangle if it isn't dereferenced.
 ///
-/// Unlike `*mut T`, `Shared<T>` is covariant over `T`. If this is incorrect
+/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect
 /// for your use case, you should include some PhantomData in your type to
 /// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
 /// Usually this won't be necessary; covariance is correct for most safe abstractions,
 /// such as Box, Rc, Arc, Vec, and LinkedList. This is the case because they
 /// provide a public API that follows the normal shared XOR mutable rules of Rust.
-#[allow(missing_debug_implementations)]
-#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
-           issue = "27730")]
-pub struct Shared<T: ?Sized> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+pub struct NonNull<T: ?Sized> {
     pointer: NonZero<*const T>,
 }
 
-/// `Shared` pointers are not `Send` because the data they reference may be aliased.
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Debug for NonNull<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&self.as_ptr(), f)
+    }
+}
+
+/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
 // NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Send for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Send for NonNull<T> { }
 
-/// `Shared` pointers are not `Sync` because the data they reference may be aliased.
+/// `NonNull` pointers are not `Sync` because the data they reference may be aliased.
 // NB: This impl is unnecessary, but should provide better error messages.
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> !Sync for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> !Sync for NonNull<T> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: Sized> Shared<T> {
-    /// Creates a new `Shared` that is dangling, but well-aligned.
+impl<T: Sized> NonNull<T> {
+    /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
     /// `Vec::new` does.
-    pub fn empty() -> Self {
+    #[stable(feature = "nonnull", since = "1.24.0")]
+    pub fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
-            Shared::new_unchecked(ptr)
+            NonNull::new_unchecked(ptr)
         }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Shared<T> {
-    /// Creates a new `Shared`.
+impl<T: ?Sized> NonNull<T> {
+    /// Creates a new `NonNull`.
     ///
     /// # Safety
     ///
     /// `ptr` must be non-null.
-    #[unstable(feature = "shared", issue = "27730")]
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
-        Shared { pointer: NonZero::new_unchecked(ptr) }
+        NonNull { pointer: NonZero::new_unchecked(ptr) }
     }
 
-    /// Creates a new `Shared` if `ptr` is non-null.
+    /// Creates a new `NonNull` if `ptr` is non-null.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub fn new(ptr: *mut T) -> Option<Self> {
-        NonZero::new(ptr as *const T).map(|nz| Shared { pointer: nz })
+        NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz })
     }
 
     /// Acquires the underlying `*mut` pointer.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub fn as_ptr(self) -> *mut T {
         self.pointer.get() as *mut T
     }
@@ -2520,7 +2545,8 @@ pub fn as_ptr(self) -> *mut T {
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&*my_ptr.ptr()`.
+    /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub unsafe fn as_ref(&self) -> &T {
         &*self.as_ptr()
     }
@@ -2529,56 +2555,50 @@ pub unsafe fn as_ref(&self) -> &T {
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
     /// it were actually an instance of T that is getting borrowed. If a longer
-    /// (unbound) lifetime is needed, use `&mut *my_ptr.ptr_mut()`.
+    /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`.
+    #[stable(feature = "nonnull", since = "1.24.0")]
     pub unsafe fn as_mut(&mut self) -> &mut T {
         &mut *self.as_ptr()
     }
-
-    /// Acquires the underlying pointer as a `*mut` pointer.
-    #[rustc_deprecated(since = "1.19", reason = "renamed to `as_ptr` for ergonomics/consistency")]
-    #[unstable(feature = "shared", issue = "27730")]
-    pub unsafe fn as_mut_ptr(&self) -> *mut T {
-        self.as_ptr()
-    }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Clone for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Clone for NonNull<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> Copy for Shared<T> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> Copy for NonNull<T> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Unsize<U> { }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> fmt::Pointer for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> fmt::Pointer for NonNull<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&self.as_ptr(), f)
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: ?Sized> From<Unique<T>> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
     fn from(unique: Unique<T>) -> Self {
-        Shared { pointer: unique.pointer }
+        NonNull { pointer: unique.pointer }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a mut T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
     fn from(reference: &'a mut T) -> Self {
-        Shared { pointer: NonZero::from(reference) }
+        NonNull { pointer: NonZero::from(reference) }
     }
 }
 
-#[unstable(feature = "shared", issue = "27730")]
-impl<'a, T: ?Sized> From<&'a T> for Shared<T> {
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
     fn from(reference: &'a T) -> Self {
-        Shared { pointer: NonZero::from(reference) }
+        NonNull { pointer: NonZero::from(reference) }
     }
 }
index 2ace3d2aee8739fc4671637a7c467f0b0dea34b0..3801db94e15d53242fc71986782f8ee161554079 100644 (file)
@@ -909,6 +909,35 @@ pub fn unwrap_or_default(self) -> T {
     }
 }
 
+impl<T, E> Result<Option<T>, E> {
+    /// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
+    ///
+    /// `Ok(None)` will be mapped to `None`.
+    /// `Ok(Some(_))` and `Err(_)` will be mapped to `Some(Ok(_))` and `Some(Err(_))`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(transpose_result)]
+    ///
+    /// #[derive(Debug, Eq, PartialEq)]
+    /// struct SomeErr;
+    ///
+    /// let x: Result<Option<i32>, SomeErr> = Ok(Some(5));
+    /// let y: Option<Result<i32, SomeErr>> = Some(Ok(5));
+    /// assert_eq!(x.transpose(), y);
+    /// ```
+    #[inline]
+    #[unstable(feature = "transpose_result", issue = "47338")]
+    pub fn transpose(self) -> Option<Result<T, E>> {
+        match self {
+            Ok(Some(x)) => Some(Ok(x)),
+            Ok(None) => None,
+            Err(e) => Some(Err(e)),
+        }
+    }
+}
+
 // This is a separate function to reduce the code size of the methods
 #[inline(never)]
 #[cold]
index 2c0009569d75d60dccb391fe2a3a79332f96f929..1c32452f84635e6b6554b510b8a49199f7aac6d7 100644 (file)
@@ -41,7 +41,6 @@
 #![feature(trusted_len)]
 #![feature(try_from)]
 #![feature(try_trait)]
-#![feature(unique)]
 #![feature(exact_chunks)]
 
 extern crate core;
index 98436f0e1d1cd968d613e70acfe8995c8b8a5257..00f87336f3c80c863f2b3bdff684d429e9b50411 100644 (file)
@@ -249,9 +249,9 @@ fn test_set_memory() {
 }
 
 #[test]
-fn test_unsized_unique() {
+fn test_unsized_nonnull() {
     let xs: &[i32] = &[1, 2, 3];
-    let ptr = unsafe { Unique::new_unchecked(xs as *const [i32] as *mut [i32]) };
+    let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
     let ys = unsafe { ptr.as_ref() };
     let zs: &[i32] = &[1, 2, 3];
     assert!(ys == zs);
index 7b48e7801dfb1bf6bd2865328c3f15c97522bf36..1d7cde8126547ed8672f73fb3ba14629176e6e53 100644 (file)
@@ -2003,7 +2003,69 @@ fn main() {
 invoking itself via a virtual call, and hence does not directly
 reference its own *type*.
 
-"##, }
+"##,
+
+E0692: r##"
+A `repr(transparent)` type was also annotated with other, incompatible
+representation hints.
+
+Erroneous code example:
+
+```compile_fail,E0692
+#![feature(repr_transparent)]
+
+#[repr(transparent, C)] // error: incompatible representation hints
+struct Grams(f32);
+```
+
+A type annotated as `repr(transparent)` delegates all representation concerns to
+another type, so adding more representation hints is contradictory. Remove
+either the `transparent` hint or the other hints, like this:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f32);
+```
+
+Alternatively, move the other attributes to the contained type:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(C)]
+struct Foo {
+    x: i32,
+    // ...
+}
+
+#[repr(transparent)]
+struct FooWrapper(Foo);
+```
+
+Note that introducing another `struct` just to have a place for the other
+attributes may have unintended side effects on the representation:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Grams(f32);
+
+#[repr(C)]
+struct Float(f32);
+
+#[repr(transparent)]
+struct Grams2(Float); // this is not equivalent to `Grams` above
+```
+
+Here, `Grams2` is a not equivalent to `Grams` -- the former transparently wraps
+a (non-transparent) struct containing a single float, while `Grams` is a
+transparent wrapper around a float. This can make a difference for the ABI.
+"##,
+
+}
 
 
 register_diagnostics! {
index 4b528a0fdc7781c1c55dfa57f6858608bf241b66..a073910fdc83f1d06d23d655189d044a56ea05b7 100644 (file)
@@ -92,6 +92,7 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
         let mut int_reprs = 0;
         let mut is_c = false;
         let mut is_simd = false;
+        let mut is_transparent = false;
 
         for hint in &hints {
             let name = if let Some(name) = hint.name() {
@@ -137,6 +138,14 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
                         continue
                     }
                 }
+                "transparent" => {
+                    is_transparent = true;
+                    if target != Target::Struct {
+                        ("a", "struct")
+                    } else {
+                        continue
+                    }
+                }
                 "i8" | "u8" | "i16" | "u16" |
                 "i32" | "u32" | "i64" | "u64" |
                 "isize" | "usize" => {
@@ -155,14 +164,22 @@ fn check_repr(&self, item: &hir::Item, target: Target) {
                 .emit();
         }
 
+        // Just point at all repr hints if there are any incompatibilities.
+        // This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
+        let hint_spans = hints.iter().map(|hint| hint.span);
+
+        // Error on repr(transparent, <anything else>).
+        if is_transparent && hints.len() > 1 {
+            let hint_spans: Vec<_> = hint_spans.clone().collect();
+            span_err!(self.tcx.sess, hint_spans, E0692,
+                      "transparent struct cannot have other repr hints");
+        }
         // Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
         if (int_reprs > 1)
            || (is_simd && is_c)
            || (int_reprs == 1 && is_c && is_c_like_enum(item)) {
-            // Just point at all repr hints. This is not ideal, but tracking
-            // precisely which ones are at fault is a huge hassle.
-            let spans: Vec<_> = hints.iter().map(|hint| hint.span).collect();
-            span_warn!(self.tcx.sess, spans, E0566,
+            let hint_spans: Vec<_> = hint_spans.collect();
+            span_warn!(self.tcx.sess, hint_spans, E0566,
                        "conflicting representation hints");
         }
     }
index 238145a061f551a76c82f085553c503a41b1f375..32b55a05124acd53939fa8ec67b0b826b18e8ec7 100644 (file)
@@ -2046,7 +2046,8 @@ fn lower_use_tree(&mut self,
                 };
 
                 // Correctly resolve `self` imports
-                if path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
+                if path.segments.len() > 1 &&
+                   path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
                     let _ = path.segments.pop();
                     if ident.name == keywords::SelfValue.name() {
                         *name = path.segments.last().unwrap().identifier.name;
index 8d43b9b4aa7396878c5d9161eef07fb61ba5f46d..3da2855929d3ab56b95b7427785ddff976387b48 100644 (file)
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
 use syntax::abi::Abi;
-use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
+use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::tokenstream::TokenStream;
 use syntax::util::ThinVec;
+use syntax::util::parser::ExprPrecedence;
 use ty::AdtKind;
 
 use rustc_data_structures::indexed_vec;
@@ -958,6 +959,31 @@ pub fn is_by_value(self) -> bool {
     }
 }
 
+impl Into<ast::BinOpKind> for BinOp_ {
+    fn into(self) -> ast::BinOpKind {
+        match self {
+            BiAdd => ast::BinOpKind::Add,
+            BiSub => ast::BinOpKind::Sub,
+            BiMul => ast::BinOpKind::Mul,
+            BiDiv => ast::BinOpKind::Div,
+            BiRem => ast::BinOpKind::Rem,
+            BiAnd => ast::BinOpKind::And,
+            BiOr => ast::BinOpKind::Or,
+            BiBitXor => ast::BinOpKind::BitXor,
+            BiBitAnd => ast::BinOpKind::BitAnd,
+            BiBitOr => ast::BinOpKind::BitOr,
+            BiShl => ast::BinOpKind::Shl,
+            BiShr => ast::BinOpKind::Shr,
+            BiEq => ast::BinOpKind::Eq,
+            BiLt => ast::BinOpKind::Lt,
+            BiLe => ast::BinOpKind::Le,
+            BiNe => ast::BinOpKind::Ne,
+            BiGe => ast::BinOpKind::Ge,
+            BiGt => ast::BinOpKind::Gt,
+        }
+    }
+}
+
 pub type BinOp = Spanned<BinOp_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1166,6 +1192,42 @@ pub struct Expr {
     pub hir_id: HirId,
 }
 
+impl Expr {
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprBox(_) => ExprPrecedence::Box,
+            ExprArray(_) => ExprPrecedence::Array,
+            ExprCall(..) => ExprPrecedence::Call,
+            ExprMethodCall(..) => ExprPrecedence::MethodCall,
+            ExprTup(_) => ExprPrecedence::Tup,
+            ExprBinary(op, ..) => ExprPrecedence::Binary(op.node.into()),
+            ExprUnary(..) => ExprPrecedence::Unary,
+            ExprLit(_) => ExprPrecedence::Lit,
+            ExprType(..) | ExprCast(..) => ExprPrecedence::Cast,
+            ExprIf(..) => ExprPrecedence::If,
+            ExprWhile(..) => ExprPrecedence::While,
+            ExprLoop(..) => ExprPrecedence::Loop,
+            ExprMatch(..) => ExprPrecedence::Match,
+            ExprClosure(..) => ExprPrecedence::Closure,
+            ExprBlock(..) => ExprPrecedence::Block,
+            ExprAssign(..) => ExprPrecedence::Assign,
+            ExprAssignOp(..) => ExprPrecedence::AssignOp,
+            ExprField(..) => ExprPrecedence::Field,
+            ExprTupField(..) => ExprPrecedence::TupField,
+            ExprIndex(..) => ExprPrecedence::Index,
+            ExprPath(..) => ExprPrecedence::Path,
+            ExprAddrOf(..) => ExprPrecedence::AddrOf,
+            ExprBreak(..) => ExprPrecedence::Break,
+            ExprAgain(..) => ExprPrecedence::Continue,
+            ExprRet(..) => ExprPrecedence::Ret,
+            ExprInlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprStruct(..) => ExprPrecedence::Struct,
+            ExprRepeat(..) => ExprPrecedence::Repeat,
+            ExprYield(..) => ExprPrecedence::Yield,
+        }
+    }
+}
+
 impl fmt::Debug for Expr {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "expr({}: {})", self.id,
index a8e55674ae521ceb6420fe58e46520e5a868edee..4cfa7a470a4faaca1c78b742bc2502c7f905d45d 100644 (file)
@@ -1104,7 +1104,7 @@ fn print_call_post(&mut self, args: &[hir::Expr]) -> io::Result<()> {
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &hir::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
@@ -2318,55 +2318,6 @@ fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
     }
 }
 
-
-fn expr_precedence(expr: &hir::Expr) -> i8 {
-    use syntax::util::parser::*;
-
-    match expr.node {
-        hir::ExprClosure(..) => PREC_CLOSURE,
-
-        hir::ExprBreak(..) |
-        hir::ExprAgain(..) |
-        hir::ExprRet(..) |
-        hir::ExprYield(..) => PREC_JUMP,
-
-        // Binop-like expr kinds, handled by `AssocOp`.
-        hir::ExprBinary(op, _, _) => bin_op_to_assoc_op(op.node).precedence() as i8,
-
-        hir::ExprCast(..) => AssocOp::As.precedence() as i8,
-        hir::ExprType(..) => AssocOp::Colon.precedence() as i8,
-
-        hir::ExprAssign(..) |
-        hir::ExprAssignOp(..) => AssocOp::Assign.precedence() as i8,
-
-        // Unary, prefix
-        hir::ExprBox(..) |
-        hir::ExprAddrOf(..) |
-        hir::ExprUnary(..) => PREC_PREFIX,
-
-        // Unary, postfix
-        hir::ExprCall(..) |
-        hir::ExprMethodCall(..) |
-        hir::ExprField(..) |
-        hir::ExprTupField(..) |
-        hir::ExprIndex(..) |
-        hir::ExprInlineAsm(..) => PREC_POSTFIX,
-
-        // Never need parens
-        hir::ExprArray(..) |
-        hir::ExprRepeat(..) |
-        hir::ExprTup(..) |
-        hir::ExprLit(..) |
-        hir::ExprPath(..) |
-        hir::ExprIf(..) |
-        hir::ExprWhile(..) |
-        hir::ExprLoop(..) |
-        hir::ExprMatch(..) |
-        hir::ExprBlock(..) |
-        hir::ExprStruct(..) => PREC_PAREN,
-    }
-}
-
 fn bin_op_to_assoc_op(op: hir::BinOp_) -> AssocOp {
     use hir::BinOp_::*;
     match op {
index ea3a1074aa2698b140f4020f7eeeff5a192f697a..4ae114c4e69da8cc6f871f7b17474c12ade335b8 100644 (file)
 //! This module contains `HashStable` implementations for various data types
 //! from rustc::ty in no particular order.
 
-use ich::{StableHashingContext, NodeIdHashingMode};
+use ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
                                            StableHasher, StableHasherResult};
+use std::cell::RefCell;
 use std::hash as std_hash;
 use std::mem;
 use middle::region;
@@ -26,7 +28,26 @@ impl<'gcx, T> HashStable<StableHashingContext<'gcx>>
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        (&self[..]).hash_stable(hcx, hasher);
+        thread_local! {
+            static CACHE: RefCell<FxHashMap<(usize, usize), Fingerprint>> =
+                RefCell::new(FxHashMap());
+        }
+
+        let hash = CACHE.with(|cache| {
+            let key = (self.as_ptr() as usize, self.len());
+            if let Some(&hash) = cache.borrow().get(&key) {
+                return hash;
+            }
+
+            let mut hasher = StableHasher::new();
+            (&self[..]).hash_stable(hcx, &mut hasher);
+
+            let hash: Fingerprint = hasher.finish();
+            cache.borrow_mut().insert(key, hash);
+            hash
+        });
+
+        hash.hash_stable(hcx, hasher);
     }
 }
 
index c477a0d383e217e9f24a66cb16da35116847962e..541c1356dd4abbd73ae604adf5c2a22c499b8786 100644 (file)
@@ -1067,6 +1067,7 @@ fn report_sub_sup_conflict(&self,
                                sub_region: Region<'tcx>,
                                sup_origin: SubregionOrigin<'tcx>,
                                sup_region: Region<'tcx>) {
+
         let mut err = self.report_inference_failure(var_origin);
 
         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
index d4ea899dc747f1cbf08d27f5054296fa6dee6bb5..7b0f2933580b39429b2354fb25c0fd2fb1f49741 100644 (file)
@@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
     ///
     /// It will later be extended to trait objects.
     pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
-        let NiceRegionError { span, sub, sup, .. } = *self;
+        let (span, sub, sup) = self.get_regions();
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
         let anon_reg_sup = self.is_suitable_region(sup)?;
index edc38b6bb14eea3ff2914efb8c4603245d588733..59b36a50a2b09d2dcb5c774bec1d1f8bb7581191 100644 (file)
 mod different_lifetimes;
 mod find_anon_type;
 mod named_anon_conflict;
+mod outlives_closure;
 mod util;
 
 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
-        let (span, sub, sup) = match *error {
-            ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
-            SubSupConflict(_, ref origin, sub, _, sup) => (origin.span(), sub, sup),
-            _ => return false, // inapplicable
-        };
+        match *error {
+            ConcreteFailure(..) | SubSupConflict(..) => {}
+            _ => return false,  // inapplicable
+        }
 
         if let Some(tables) = self.in_progress_tables {
             let tables = tables.borrow();
-            NiceRegionError::new(self.tcx, span, sub, sup, Some(&tables)).try_report().is_some()
+            NiceRegionError::new(self.tcx, error.clone(), Some(&tables)).try_report().is_some()
         } else {
-            NiceRegionError::new(self.tcx, span, sub, sup, None).try_report().is_some()
+            NiceRegionError::new(self.tcx, error.clone(), None).try_report().is_some()
         }
     }
 }
 
 pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-    span: Span,
-    sub: ty::Region<'tcx>,
-    sup: ty::Region<'tcx>,
+    error: Option<RegionResolutionError<'tcx>>,
+    regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
     tables: Option<&'cx ty::TypeckTables<'tcx>>,
 }
 
 impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> {
     pub fn new(
+        tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+        error: RegionResolutionError<'tcx>,
+        tables: Option<&'cx ty::TypeckTables<'tcx>>,
+    ) -> Self {
+        Self { tcx, error: Some(error), regions: None, tables }
+    }
+
+    pub fn new_from_span(
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
         span: Span,
         sub: ty::Region<'tcx>,
         sup: ty::Region<'tcx>,
         tables: Option<&'cx ty::TypeckTables<'tcx>>,
     ) -> Self {
-        Self { tcx, span, sub, sup, tables }
+        Self { tcx, error: None, regions: Some((span, sub, sup)), tables }
     }
 
     pub fn try_report(&self) -> Option<ErrorReported> {
         self.try_report_named_anon_conflict()
             .or_else(|| self.try_report_anon_anon_conflict())
+            .or_else(|| self.try_report_outlives_closure())
+    }
+
+    pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) {
+        match (&self.error, self.regions) {
+            (&Some(ConcreteFailure(ref origin, sub, sup)), None) => (origin.span(), sub, sup),
+            (&Some(SubSupConflict(_, ref origin, sub, _, sup)), None) => (origin.span(), sub, sup),
+            (None, Some((span, sub, sup))) => (span, sub, sup),
+            (Some(_), Some(_)) => panic!("incorrectly built NiceRegionError"),
+            _ => panic!("trying to report on an incorrect lifetime failure"),
+        }
     }
 }
index 5617c7723859743cf3f5cd7468475941a81d27ca..c106fd0c3d2c0b3c95d483d5bfdd4294272d72a1 100644 (file)
@@ -18,7 +18,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
     /// When given a `ConcreteFailure` for a function with arguments containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
     pub(super) fn try_report_named_anon_conflict(&self) -> Option<ErrorReported> {
-        let NiceRegionError { span, sub, sup, .. } = *self;
+        let (span, sub, sup) = self.get_regions();
 
         debug!(
             "try_report_named_anon_conflict(sub={:?}, sup={:?})",
diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs
new file mode 100644 (file)
index 0000000..95f44b8
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Error Reporting for Anonymous Region Lifetime Errors
+//! where both the regions are anonymous.
+
+use infer::error_reporting::nice_region_error::NiceRegionError;
+use infer::SubregionOrigin;
+use ty::RegionKind;
+use hir::{Expr, ExprClosure};
+use hir::map::NodeExpr;
+use util::common::ErrorReported;
+use infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
+
+impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
+    /// Print the error message for lifetime errors when binding excapes a closure.
+    ///
+    /// Consider a case where we have
+    ///
+    /// ```no_run
+    /// fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    ///     let x = 3;
+    ///     f(&x);
+    /// }
+    /// fn main() {
+    ///     let mut x = None;
+    ///     with_int(|y| x = Some(y));
+    /// }
+    /// ```
+    ///
+    /// the output will be
+    ///
+    /// ```text
+    ///     let mut x = None;
+    ///         ----- borrowed data cannot be stored into here...
+    ///     with_int(|y| x = Some(y));
+    ///              ---          ^ cannot be stored outside of its closure
+    ///              |
+    ///              ...because it cannot outlive this closure
+    /// ```
+    pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
+        if let Some(SubSupConflict(origin,
+                                   ref sub_origin,
+                                   _,
+                                   ref sup_origin,
+                                   sup_region)) = self.error {
+
+            // #45983: when trying to assign the contents of an argument to a binding outside of a
+            // closure, provide a specific message pointing this out.
+            if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
+                    &RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) {
+                let hir = &self.tcx.hir;
+                if let Some(node_id) = hir.as_local_node_id(free_region.scope) {
+                    match hir.get(node_id) {
+                        NodeExpr(Expr {
+                            node: ExprClosure(_, _, _, closure_span, false),
+                            ..
+                        }) => {
+                            let sup_sp = sup_origin.span();
+                            let origin_sp = origin.span();
+                            let mut err = self.tcx.sess.struct_span_err(
+                                sup_sp,
+                                "borrowed data cannot be stored outside of its closure");
+                            err.span_label(sup_sp, "cannot be stored outside of its closure");
+                            if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
+// // sup_sp == origin.span():
+//
+// let mut x = None;
+//     ----- borrowed data cannot be stored into here...
+// with_int(|y| x = Some(y));
+//          ---          ^ cannot be stored outside of its closure
+//          |
+//          ...because it cannot outlive this closure
+//
+// // origin.contains(&sup_sp):
+//
+// let mut f: Option<&u32> = None;
+//     ----- borrowed data cannot be stored into here...
+// closure_expecting_bound(|x: &'x u32| {
+//                         ------------ ... because it cannot outlive this closure
+//     f = Some(x);
+//              ^ cannot be stored outside of its closure
+                                err.span_label(*external_span,
+                                               "borrowed data cannot be stored into here...");
+                                err.span_label(*closure_span,
+                                               "...because it cannot outlive this closure");
+                            } else {
+// FIXME: the wording for this case could be much improved
+//
+// let mut lines_to_use: Vec<&CrateId> = Vec::new();
+//                           - cannot infer an appropriate lifetime...
+// let push_id = |installed_id: &CrateId| {
+//     -------   ------------------------ borrowed data cannot outlive this closure
+//     |
+//     ...so that variable is valid at time of its declaration
+//     lines_to_use.push(installed_id);
+//                       ^^^^^^^^^^^^ cannot be stored outside of its closure
+                                err.span_label(origin_sp,
+                                               "cannot infer an appropriate lifetime...");
+                                err.span_label(*external_span,
+                                               "...so that variable is valid at time of its \
+                                                declaration");
+                                err.span_label(*closure_span,
+                                               "borrowed data cannot outlive this closure");
+                            }
+                            err.emit();
+                            return Some(ErrorReported);
+                        }
+                        _ => {}
+                    }
+                }
+            }
+        }
+        None
+    }
+}
+
index 075ee0b8c7c2874ce62ab77cd44d91eb6f97c906..d727dfb0c4b2deef220d33c0f16cefa057ad8e37 100644 (file)
@@ -44,6 +44,7 @@
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
+#![feature(copy_closures, clone_closures)]
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(dyn_trait)]
index 58067931d562eed2e8d157012a001c06db8db556..57ed41f2f06e63c7ef6968409e55754ef44f3dbc 100644 (file)
@@ -277,6 +277,13 @@ fn visit_visibility_scope(&mut self,
 
             fn super_mir(&mut self,
                          mir: & $($mutability)* Mir<'tcx>) {
+                if let Some(yield_ty) = &$($mutability)* mir.yield_ty {
+                    self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
+                        span: mir.span,
+                        scope: ARGUMENT_VISIBILITY_SCOPE,
+                    }));
+                }
+
                 // for best performance, we want to use an iterator rather
                 // than a for-loop, to avoid calling Mir::invalidate for
                 // each basic block.
@@ -852,6 +859,8 @@ pub enum TyContext {
     /// The return type of the function.
     ReturnTy(SourceInfo),
 
+    YieldTy(SourceInfo),
+
     /// A type found at some location.
     Location(Location),
 }
index 8efd6b458e9cbf1c0251a9e5c2c591d951025b78..da119ba45694dea17fedfd05623be94ee43b95b6 100644 (file)
@@ -1058,6 +1058,8 @@ fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          build_debugging_options, "Z", "debugging",
          DB_OPTIONS, db_type_desc, dbsetters,
+    codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
+        "the backend to use"),
     verbose: bool = (false, parse_bool, [UNTRACKED],
         "in general, enable more debug printouts"),
     span_free_formats: bool = (false, parse_bool, [UNTRACKED],
index 3ae7d01823c8a370124d4b236a7070c6e902de53..94fcfb7e2aa572ccc357df605c0b5e5bfa25f9d9 100644 (file)
@@ -11,7 +11,7 @@
 pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
 pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
 
-use hir::def_id::{CrateNum, DefIndex};
+use hir::def_id::CrateNum;
 use ich::Fingerprint;
 
 use lint;
@@ -558,18 +558,16 @@ pub fn must_not_eliminate_frame_pointers(&self) -> bool {
 
     /// Returns the symbol name for the registrar function,
     /// given the crate Svh and the function DefIndex.
-    pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator,
-                                            index: DefIndex)
+    pub fn generate_plugin_registrar_symbol(&self,
+                                            disambiguator: CrateDisambiguator)
                                             -> String {
-        format!("__rustc_plugin_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
-                                                   index.to_proc_macro_index())
+        format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
-    pub fn generate_derive_registrar_symbol(&self, disambiguator: CrateDisambiguator,
-                                            index: DefIndex)
+    pub fn generate_derive_registrar_symbol(&self,
+                                            disambiguator: CrateDisambiguator)
                                             -> String {
-        format!("__rustc_derive_registrar__{}_{}", disambiguator.to_fingerprint().to_hex(),
-                                                   index.to_proc_macro_index())
+        format!("__rustc_derive_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
     pub fn sysroot<'a>(&'a self) -> &'a Path {
index 1aca687af2bf3e808bbff8cedaf4741ee28ef9e3..e649f1b49df765052fdd61b6b3b69c0e69c8d2ef 100644 (file)
@@ -717,93 +717,40 @@ pub fn report_selection_error(&self,
                     self.tcx.hir.span_if_local(did)
                 }).map(|sp| self.tcx.sess.codemap().def_span(sp)); // the sp could be an fn def
 
-                let found_ty_count =
-                    match found_trait_ref.skip_binder().substs.type_at(1).sty {
-                        ty::TyTuple(ref tys, _) => tys.len(),
-                        _ => 1,
-                    };
-                let (expected_tys, expected_ty_count) =
-                    match expected_trait_ref.skip_binder().substs.type_at(1).sty {
-                        ty::TyTuple(ref tys, _) =>
-                            (tys.iter().map(|t| &t.sty).collect(), tys.len()),
-                        ref sty => (vec![sty], 1),
-                    };
-                if found_ty_count == expected_ty_count {
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
+                    ty::TyTuple(ref tys, _) => tys.iter()
+                        .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
+                    _ => vec![ArgKind::empty()],
+                };
+                let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
+                    ty::TyTuple(ref tys, _) => tys.iter()
+                        .map(|t| match t.sty {
+                            ty::TypeVariants::TyTuple(ref tys, _) => ArgKind::Tuple(
+                                span,
+                                tys.iter()
+                                    .map(|ty| ("_".to_owned(), format!("{}", ty.sty)))
+                                    .collect::<Vec<_>>()
+                            ),
+                            _ => ArgKind::Arg("_".to_owned(), format!("{}", t.sty)),
+                        }).collect(),
+                    ref sty => vec![ArgKind::Arg("_".to_owned(), format!("{}", sty))],
+                };
+                if found.len()== expected.len() {
                     self.report_closure_arg_mismatch(span,
                                                      found_span,
                                                      found_trait_ref,
                                                      expected_trait_ref)
                 } else {
-                    let expected_tuple = if expected_ty_count == 1 {
-                        expected_tys.first().and_then(|t| {
-                            if let &&ty::TyTuple(ref tuptys, _) = t {
-                                Some(tuptys.len())
-                            } else {
-                                None
-                            }
-                        })
-                    } else {
-                        None
-                    };
-
-                    // FIXME(#44150): Expand this to "N args expected but a N-tuple found."
-                    // Type of the 1st expected argument is somehow provided as type of a
-                    // found one in that case.
-                    //
-                    // ```
-                    // [1i32, 2, 3].sort_by(|(a, b)| ..)
-                    // //           ^^^^^^^ --------
-                    // // expected_trait_ref:  std::ops::FnMut<(&i32, &i32)>
-                    // //    found_trait_ref:  std::ops::FnMut<(&i32,)>
-                    // ```
-
-                    let (closure_span, closure_args) = found_did
+                    let (closure_span, found) = found_did
                         .and_then(|did| self.tcx.hir.get_if_local(did))
-                        .and_then(|node| {
-                            if let hir::map::NodeExpr(
-                                &hir::Expr {
-                                    node: hir::ExprClosure(_, ref decl, id, span, _),
-                                    ..
-                                }) = node
-                            {
-                                let ty_snips = decl.inputs.iter()
-                                    .map(|ty| {
-                                        self.tcx.sess.codemap().span_to_snippet(ty.span).ok()
-                                            .and_then(|snip| {
-                                                // filter out dummy spans
-                                                if snip == "," || snip == "|" {
-                                                    None
-                                                } else {
-                                                    Some(snip)
-                                                }
-                                            })
-                                    })
-                                    .collect::<Vec<Option<String>>>();
-
-                                let body = self.tcx.hir.body(id);
-                                let pat_snips = body.arguments.iter()
-                                    .map(|arg|
-                                        self.tcx.sess.codemap().span_to_snippet(arg.pat.span).ok())
-                                    .collect::<Option<Vec<String>>>();
-
-                                Some((span, pat_snips, ty_snips))
-                            } else {
-                                None
-                            }
-                        })
-                        .map(|(span, pat, ty)| (Some(span), Some((pat, ty))))
-                        .unwrap_or((None, None));
-                    let closure_args = closure_args.and_then(|(pat, ty)| Some((pat?, ty)));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span.or(found_span),
-                        expected_ty_count,
-                        expected_tuple,
-                        found_ty_count,
-                        closure_args,
-                        found_trait_ty.is_closure()
-                    )
+                        .map(|node| self.get_fn_like_arguments(node))
+                        .unwrap_or((found_span.unwrap(), found));
+
+                    self.report_arg_count_mismatch(span,
+                                                   closure_span,
+                                                   expected,
+                                                   found,
+                                                   found_trait_ty.is_closure())
                 }
             }
 
@@ -845,94 +792,135 @@ fn suggest_borrow_on_unsized_slice(&self,
         }
     }
 
+    fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>) {
+        if let hir::map::NodeExpr(&hir::Expr {
+            node: hir::ExprClosure(_, ref _decl, id, span, _),
+            ..
+        }) = node {
+            (self.tcx.sess.codemap().def_span(span), self.tcx.hir.body(id).arguments.iter()
+                .map(|arg| {
+                    if let hir::Pat {
+                        node: hir::PatKind::Tuple(args, _),
+                        span,
+                        ..
+                    } = arg.pat.clone().into_inner() {
+                        ArgKind::Tuple(
+                            span,
+                            args.iter().map(|pat| {
+                                let snippet = self.tcx.sess.codemap()
+                                    .span_to_snippet(pat.span).unwrap();
+                                (snippet, "_".to_owned())
+                            }).collect::<Vec<_>>(),
+                        )
+                    } else {
+                        let name = self.tcx.sess.codemap().span_to_snippet(arg.pat.span).unwrap();
+                        ArgKind::Arg(name, "_".to_owned())
+                    }
+                })
+                .collect::<Vec<ArgKind>>())
+        } else if let hir::map::NodeItem(&hir::Item {
+            span,
+            node: hir::ItemFn(ref decl, ..),
+            ..
+        }) = node {
+            (self.tcx.sess.codemap().def_span(span), decl.inputs.iter()
+                    .map(|arg| match arg.clone().into_inner().node {
+                hir::TyTup(ref tys) => ArgKind::Tuple(
+                    arg.span,
+                    tys.iter()
+                        .map(|_| ("_".to_owned(), "_".to_owned()))
+                        .collect::<Vec<_>>(),
+                ),
+                _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
+            }).collect::<Vec<ArgKind>>())
+        } else {
+            panic!("non-FnLike node found: {:?}", node);
+        }
+    }
+
     fn report_arg_count_mismatch(
         &self,
         span: Span,
-        found_span: Option<Span>,
-        expected: usize,
-        expected_tuple: Option<usize>,
-        found: usize,
-        closure_args: Option<(Vec<String>, Vec<Option<String>>)>,
-        is_closure: bool
+        found_span: Span,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
     ) -> DiagnosticBuilder<'tcx> {
-        use std::borrow::Cow;
-
         let kind = if is_closure { "closure" } else { "function" };
 
-        let args_str = |n, distinct| format!(
-                "{} {}argument{}",
-                n,
-                if distinct && n >= 2 { "distinct " } else { "" },
-                if n == 1 { "" } else { "s" },
-            );
-
-        let expected_str = if let Some(n) = expected_tuple {
-            assert!(expected == 1);
-            if closure_args.as_ref().map(|&(ref pats, _)| pats.len()) == Some(n) {
-                Cow::from("a single tuple as argument")
-            } else {
-                // be verbose when numbers differ
-                Cow::from(format!("a single {}-tuple as argument", n))
+        let args_str = |arguments: &Vec<ArgKind>, other: &Vec<ArgKind>| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!("{} {}argument{}",
+                             arg_length,
+                             if distinct && arg_length > 1 { "distinct " } else { "" },
+                             if arg_length == 1 { "" } else { "s" }),
             }
-        } else {
-            Cow::from(args_str(expected, false))
-        };
-
-        let found_str = if expected_tuple.is_some() {
-            args_str(found, true)
-        } else {
-            args_str(found, false)
         };
 
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
 
-        let mut err = struct_span_err!(self.tcx.sess, span, E0593,
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
             "{} is expected to take {}, but it takes {}",
             kind,
             expected_str,
             found_str,
         );
 
-        err.span_label(
-            span,
-            format!(
-                "expected {} that takes {}",
-                kind,
-                expected_str,
-            )
-        );
-
-        if let Some(span) = found_span {
-            if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) {
-                if expected_tuple != found || pats.len() != found {
-                    err.span_label(span, format!("takes {}", found_str));
-                } else {
-                    let sugg = format!(
-                        "|({}){}|",
-                        pats.join(", "),
-
-                        // add type annotations if available
-                        if tys.iter().any(|ty| ty.is_some()) {
-                            Cow::from(format!(
-                                ": ({})",
-                                tys.into_iter().map(|ty| if let Some(ty) = ty {
-                                    ty
-                                } else {
-                                    "_".to_string()
-                                }).collect::<Vec<String>>().join(", ")
-                            ))
-                        } else {
-                            Cow::from("")
-                        },
-                    );
-
-                    err.span_suggestion(
-                        span,
-                        "consider changing the closure to accept a tuple",
-                        sugg
-                    );
-                }
-            } else {
-                err.span_label(span, format!("takes {}", found_str));
+        err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
+        err.span_label(found_span, format!("takes {}", found_str));
+
+        if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+            if fields.len() == expected_args.len() {
+                let sugg = fields.iter()
+                    .map(|(name, _)| name.to_owned())
+                    .collect::<Vec<String>>().join(", ");
+                err.span_suggestion(found_span,
+                                    "change the closure to take multiple arguments instead of \
+                                     a single tuple",
+                                    format!("|{}|", sugg));
+            }
+        }
+        if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+            if fields.len() == found_args.len() && is_closure {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args.iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(": ({})",
+                                fields.iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", "))
+                    } else {
+                        "".to_owned()
+                    },
+                );
+                err.span_suggestion(found_span,
+                                    "change the closure to accept a tuple instead of individual \
+                                     arguments",
+                                    sugg);
             }
         }
 
@@ -1331,3 +1319,14 @@ fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
                           suggested_limit));
     }
 }
+
+enum ArgKind {
+    Arg(String, String),
+    Tuple(Span, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+}
index 2b4d2c80c6f9e904bc941939fe1ed66d3bf654f2..123432074761ba15197aec10b7d6e6678a4e3cec 100644 (file)
@@ -20,6 +20,7 @@
 use hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use hir::map::DefPathData;
 use hir::svh::Svh;
+use ich::Fingerprint;
 use ich::StableHashingContext;
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
@@ -37,6 +38,7 @@
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
 
 use serialize::{self, Encodable, Encoder};
+use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::cmp;
 use std::fmt;
@@ -1476,17 +1478,32 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for AdtDef {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'gcx>,
                                           hasher: &mut StableHasher<W>) {
-        let ty::AdtDef {
-            did,
-            ref variants,
-            ref flags,
-            ref repr,
-        } = *self;
+        thread_local! {
+            static CACHE: RefCell<FxHashMap<usize, Fingerprint>> =
+                RefCell::new(FxHashMap());
+        }
+
+        let hash: Fingerprint = CACHE.with(|cache| {
+            let addr = self as *const AdtDef as usize;
+            *cache.borrow_mut().entry(addr).or_insert_with(|| {
+                let ty::AdtDef {
+                    did,
+                    ref variants,
+                    ref flags,
+                    ref repr,
+                } = *self;
 
-        did.hash_stable(hcx, hasher);
-        variants.hash_stable(hcx, hasher);
-        flags.hash_stable(hcx, hasher);
-        repr.hash_stable(hcx, hasher);
+                let mut hasher = StableHasher::new();
+                did.hash_stable(hcx, &mut hasher);
+                variants.hash_stable(hcx, &mut hasher);
+                flags.hash_stable(hcx, &mut hasher);
+                repr.hash_stable(hcx, &mut hasher);
+
+                hasher.finish()
+           })
+        });
+
+        hash.hash_stable(hcx, hasher);
     }
 }
 
@@ -1499,8 +1516,9 @@ pub struct ReprFlags: u8 {
         const IS_C               = 1 << 0;
         const IS_PACKED          = 1 << 1;
         const IS_SIMD            = 1 << 2;
+        const IS_TRANSPARENT     = 1 << 3;
         // Internal only for now. If true, don't reorder fields.
-        const IS_LINEAR          = 1 << 3;
+        const IS_LINEAR          = 1 << 4;
 
         // Any of these flags being set prevent field reordering optimisation.
         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits |
@@ -1540,6 +1558,7 @@ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
                 flags.insert(match r {
                     attr::ReprC => ReprFlags::IS_C,
                     attr::ReprPacked => ReprFlags::IS_PACKED,
+                    attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
                     attr::ReprSimd => ReprFlags::IS_SIMD,
                     attr::ReprInt(i) => {
                         size = Some(i);
@@ -1567,6 +1586,8 @@ pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) }
     #[inline]
     pub fn packed(&self) -> bool { self.flags.contains(ReprFlags::IS_PACKED) }
     #[inline]
+    pub fn transparent(&self) -> bool { self.flags.contains(ReprFlags::IS_TRANSPARENT) }
+    #[inline]
     pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) }
 
     pub fn discr_type(&self) -> attr::IntType {
index 3e76b60b84a13ad69b53a51d30a6e007c2fa6e08..7abd02b6656f3aa15f8192930d827fd302e9ff16 100644 (file)
@@ -1434,7 +1434,7 @@ fn scalbn_r(mut self, exp: ExpInt, round: Round) -> Self {
         let max_change = S::MAX_EXP as i32 - (S::MIN_EXP as i32 - sig_bits) + 1;
 
         // Clamp to one past the range ends to let normalize handle overflow.
-        let exp_change = cmp::min(cmp::max(exp as i32, (-max_change - 1)), max_change);
+        let exp_change = cmp::min(cmp::max(exp as i32, -max_change - 1), max_change);
         self.exp = self.exp.saturating_add(exp_change as ExpInt);
         self = self.normalize(round, Loss::ExactlyZero).value;
         if self.is_nan() {
index d5e8194c3f79b9bda698b9ce04e9eb90a489552d..59c82e06a679c1eb2133e74f3136267362664b1d 100644 (file)
@@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.max_atomic_width = Some(128);
     base.abi_blacklist = super::arm_base::abi_blacklist();
+    base.linker = "aarch64-unknown-cloudabi-cc".to_string();
 
     Ok(Target {
         llvm_target: "aarch64-unknown-cloudabi".to_string(),
index 4dad8e1713b432811570a0764d0566b1f6764286..faa2c4fdceb9b2fce6b8b60182a03bf6c12aef45 100644 (file)
@@ -17,6 +17,7 @@ pub fn target() -> TargetResult {
     base.max_atomic_width = Some(64);
     base.features = "+v7,+vfp3,+neon".to_string();
     base.abi_blacklist = super::arm_base::abi_blacklist();
+    base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string();
 
     Ok(Target {
         llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),
index b9aa6176d87687d8f73d3f734b23cd36dc95fed6..e244f443d3e3a353acf2fbd70995f933de14dcb6 100644 (file)
@@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.cpu = "pentium4".to_string();
     base.max_atomic_width = Some(64);
+    base.linker = "i686-unknown-cloudabi-cc".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
     base.stack_probes = true;
 
index f9a563174d4a96c7f90d960db5a48c7e0f8741c4..1ce3c6444f1ea718d492ed6be6b8eca154dd7402 100644 (file)
@@ -15,6 +15,7 @@ pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
+    base.linker = "x86_64-unknown-cloudabi-cc".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.stack_probes = true;
 
index 33d9bfa6e6b9c21b44d31f2ec37afbebc941832a..a7c382eba5091608fb375738858cab77b230a001 100644 (file)
@@ -561,19 +561,25 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
 ///   (1) all_constructors will only return constructors that are statically
 ///       possible. eg. it will only return Ok for Result<T, !>
 ///
-/// Whether a vector `v` of patterns is 'useful' in relation to a set of such
-/// vectors `m` is defined as there being a set of inputs that will match `v`
-/// but not any of the sets in `m`.
+/// This finds whether a (row) vector `v` of patterns is 'useful' in relation
+/// to a set of such vectors `m` - this is defined as there being a set of
+/// inputs that will match `v` but not any of the sets in `m`.
+///
+/// All the patterns at each column of the `matrix ++ v` matrix must
+/// have the same type, except that wildcard (PatternKind::Wild) patterns
+/// with type TyErr are also allowed, even if the "type of the column"
+/// is not TyErr. That is used to represent private fields, as using their
+/// real type would assert that they are inhabited.
 ///
 /// This is used both for reachability checking (if a pattern isn't useful in
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
 pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
-                           matrix: &Matrix<'p, 'tcx>,
-                           v: &[&'p Pattern<'tcx>],
-                           witness: WitnessPreference)
-                           -> Usefulness<'tcx> {
+                                       matrix: &Matrix<'p, 'tcx>,
+                                       v: &[&'p Pattern<'tcx>],
+                                       witness: WitnessPreference)
+                                       -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
     debug!("is_useful({:?}, {:?})", matrix, v);
 
@@ -596,6 +602,25 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     assert!(rows.iter().all(|r| r.len() == v.len()));
 
     let pcx = PatternContext {
+        // TyErr is used to represent the type of wildcard patterns matching
+        // against inaccessible (private) fields of structs, so that we won't
+        // be able to observe whether the types of the struct's fields are
+        // inhabited.
+        //
+        // If the field is truely inaccessible, then all the patterns
+        // matching against it must be wildcard patterns, so its type
+        // does not matter.
+        //
+        // However, if we are matching against non-wildcard patterns, we
+        // need to know the real type of the field so we can specialize
+        // against it. This primarily occurs through constants - they
+        // can include contents for fields that are inaccessible at the
+        // location of the match. In that case, the field's type is
+        // inhabited - by the constant - so we can just use it.
+        //
+        // FIXME: this might lead to "unstable" behavior with macro hygiene
+        // introducing uninhabited patterns for inaccessible fields. We
+        // need to figure out how to model that.
         ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error())
             .unwrap_or(v[0].ty),
         max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
@@ -861,13 +886,13 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                     if is_visible {
                         field.ty(cx.tcx, substs)
                     } else {
-                        // Treat all non-visible fields as nil. They
+                        // Treat all non-visible fields as TyErr. They
                         // can't appear in any other pattern from
                         // this match (because they are private),
                         // so their type does not matter - but
                         // we don't want to know they are
                         // uninhabited.
-                        cx.tcx.mk_nil()
+                        cx.tcx.types.err
                     }
                 }).collect()
             }
index 57fc78ef531107fa58d73f25f7e8c842eb9eea74..511c407d45a7fef0ad7d7cb0f5d937041b93826e 100644 (file)
@@ -12,7 +12,7 @@
 
 use std::marker::Unsize;
 use std::iter::Extend;
-use std::ptr::{self, drop_in_place, Shared};
+use std::ptr::{self, drop_in_place, NonNull};
 use std::ops::{Deref, DerefMut, Range};
 use std::hash::{Hash, Hasher};
 use std::slice;
@@ -146,7 +146,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<A>
                 tail_start: end,
                 tail_len: len - end,
                 iter: range_slice.iter(),
-                array_vec: Shared::from(self),
+                array_vec: NonNull::from(self),
             }
         }
     }
@@ -232,7 +232,7 @@ pub struct Drain<'a, A: Array>
     tail_start: usize,
     tail_len: usize,
     iter: slice::Iter<'a, ManuallyDrop<A::Element>>,
-    array_vec: Shared<ArrayVec<A>>,
+    array_vec: NonNull<ArrayVec<A>>,
 }
 
 impl<'a, A: Array> Iterator for Drain<'a, A> {
index 24048e606df4739b02e11779568426e7118a1e1d..a35ef2f7ce7baefec130cbd7a9823d3897010390 100644 (file)
@@ -21,7 +21,6 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(shared)]
 #![feature(collections_range)]
 #![feature(nonzero)]
 #![feature(unboxed_closures)]
index f7e35ba0081e46300d3d88f7e1193f1db65b5725..468a08b1fd9f37fd36989e6a6377a315d98af693 100644 (file)
@@ -31,7 +31,6 @@
 use rustc_resolve::{MakeGlobMap, Resolver};
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::{self, CStore};
-use rustc_trans as trans;
 use rustc_trans_utils::trans_crate::TransCrate;
 use rustc_typeck as typeck;
 use rustc_privacy;
@@ -40,7 +39,6 @@
 use rustc_passes::{self, ast_validation, loops, consts, static_recursion, hir_stats};
 use rustc_const_eval::{self, check_match};
 use super::Compilation;
-use ::DefaultTransCrate;
 
 use serialize::json;
 
@@ -68,7 +66,8 @@
 
 use profile;
 
-pub fn compile_input(sess: &Session,
+pub fn compile_input(trans: Box<TransCrate>,
+                     sess: &Session,
                      cstore: &CStore,
                      input_path: &Option<PathBuf>,
                      input: &Input,
@@ -76,8 +75,6 @@ pub fn compile_input(sess: &Session,
                      output: &Option<PathBuf>,
                      addl_plugins: Option<Vec<String>>,
                      control: &CompileController) -> CompileResult {
-    use rustc::session::config::CrateType;
-
     macro_rules! controller_entry_point {
         ($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
             let state = &mut $make_state;
@@ -94,22 +91,6 @@ macro_rules! controller_entry_point {
         }}
     }
 
-    if cfg!(not(feature="llvm")) {
-        for cty in sess.opts.crate_types.iter() {
-            match *cty {
-                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
-                CrateType::CrateTypeExecutable => {},
-                _ => {
-                    sess.parse_sess.span_diagnostic.warn(
-                        &format!("LLVM unsupported, so output type {} is not supported", cty)
-                    );
-                },
-            }
-        }
-
-        sess.abort_if_errors();
-    }
-
     if sess.profile_queries() {
         profile::begin();
     }
@@ -117,7 +98,7 @@ macro_rules! controller_entry_point {
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (outputs, trans, dep_graph) = {
+    let (outputs, ongoing_trans, dep_graph) = {
         let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
@@ -217,7 +198,8 @@ macro_rules! controller_entry_point {
             None
         };
 
-        phase_3_run_analysis_passes(control,
+        phase_3_run_analysis_passes(&*trans,
+                                    control,
                                     sess,
                                     cstore,
                                     hir_map,
@@ -254,7 +236,7 @@ macro_rules! controller_entry_point {
                 tcx.print_debug_stats();
             }
 
-            let trans = phase_4_translate_to_llvm::<DefaultTransCrate>(tcx, rx);
+            let ongoing_trans = phase_4_translate_to_llvm(&*trans, tcx, rx);
 
             if log_enabled!(::log::Level::Info) {
                 println!("Post-trans");
@@ -268,7 +250,7 @@ macro_rules! controller_entry_point {
                 }
             }
 
-            Ok((outputs.clone(), trans, tcx.dep_graph.clone()))
+            Ok((outputs.clone(), ongoing_trans, tcx.dep_graph.clone()))
         })??
     };
 
@@ -276,25 +258,7 @@ macro_rules! controller_entry_point {
         sess.code_stats.borrow().print_type_sizes();
     }
 
-    let (phase5_result, trans) =
-        phase_5_run_llvm_passes::<DefaultTransCrate>(sess, &dep_graph, trans);
-
-    controller_entry_point!(after_llvm,
-                            sess,
-                            CompileState::state_after_llvm(input, sess, outdir, output, &trans),
-                            phase5_result);
-    phase5_result?;
-
-    // Run the linker on any artifacts that resulted from the LLVM run.
-    // This should produce either a finished executable or library.
-    time(sess.time_passes(), "linking", || {
-        DefaultTransCrate::link_binary(sess, &trans, &outputs)
-    });
-
-    // Now that we won't touch anything in the incremental compilation directory
-    // any more, we can finalize it (which involves renaming it)
-    #[cfg(feature="llvm")]
-    rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+    trans.join_trans_and_link(ongoing_trans, sess, &dep_graph, &outputs)?;
 
     if sess.opts.debugging_opts.perf_stats {
         sess.print_perf_stats();
@@ -340,7 +304,6 @@ pub struct CompileController<'a> {
     pub after_expand: PhaseController<'a>,
     pub after_hir_lowering: PhaseController<'a>,
     pub after_analysis: PhaseController<'a>,
-    pub after_llvm: PhaseController<'a>,
     pub compilation_done: PhaseController<'a>,
 
     // FIXME we probably want to group the below options together and offer a
@@ -366,7 +329,6 @@ pub fn basic() -> CompileController<'a> {
             after_expand: PhaseController::basic(),
             after_hir_lowering: PhaseController::basic(),
             after_analysis: PhaseController::basic(),
-            after_llvm: PhaseController::basic(),
             compilation_done: PhaseController::basic(),
             make_glob_map: MakeGlobMap::No,
             keep_ast: false,
@@ -415,7 +377,6 @@ pub struct CompileState<'a, 'tcx: 'a> {
     pub resolutions: Option<&'a Resolutions>,
     pub analysis: Option<&'a ty::CrateAnalysis>,
     pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
-    pub trans: Option<&'a trans::CrateTranslation>,
 }
 
 impl<'a, 'tcx> CompileState<'a, 'tcx> {
@@ -440,7 +401,6 @@ fn empty(input: &'a Input,
             resolutions: None,
             analysis: None,
             tcx: None,
-            trans: None,
         }
     }
 
@@ -528,19 +488,6 @@ fn state_after_analysis(input: &'a Input,
         }
     }
 
-    fn state_after_llvm(input: &'a Input,
-                        session: &'tcx Session,
-                        out_dir: &'a Option<PathBuf>,
-                        out_file: &'a Option<PathBuf>,
-                        trans: &'a trans::CrateTranslation)
-                        -> Self {
-        CompileState {
-            trans: Some(trans),
-            out_file: out_file.as_ref().map(|s| &**s),
-            ..CompileState::empty(input, session, out_dir)
-        }
-    }
-
     fn state_when_compilation_done(input: &'a Input,
                                    session: &'tcx Session,
                                    out_dir: &'a Option<PathBuf>,
@@ -933,7 +880,6 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
     reachable::provide(providers);
     resolve_lifetime::provide(providers);
     rustc_privacy::provide(providers);
-    DefaultTransCrate::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
     traits::provide(providers);
@@ -947,13 +893,13 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
 
 pub fn default_provide_extern(providers: &mut ty::maps::Providers) {
     cstore::provide_extern(providers);
-    DefaultTransCrate::provide_extern(providers);
 }
 
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
-pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
+pub fn phase_3_run_analysis_passes<'tcx, F, R>(trans: &TransCrate,
+                                               control: &CompileController,
                                                sess: &'tcx Session,
                                                cstore: &'tcx CrateStore,
                                                hir_map: hir_map::Map<'tcx>,
@@ -1006,10 +952,12 @@ macro_rules! try_with_f {
 
     let mut local_providers = ty::maps::Providers::default();
     default_provide(&mut local_providers);
+    trans.provide(&mut local_providers);
     (control.provide)(&mut local_providers);
 
     let mut extern_providers = local_providers;
     default_provide_extern(&mut extern_providers);
+    trans.provide_extern(&mut extern_providers);
     (control.provide_extern)(&mut extern_providers);
 
     let (tx, rx) = mpsc::channel();
@@ -1101,9 +1049,10 @@ macro_rules! try_with_f {
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub fn phase_4_translate_to_llvm<'a, 'tcx>(trans: &TransCrate,
+                                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            rx: mpsc::Receiver<Box<Any + Send>>)
-                                           -> <Trans as TransCrate>::OngoingCrateTranslation {
+                                           -> Box<Any> {
     let time_passes = tcx.sess.time_passes();
 
     time(time_passes,
@@ -1112,7 +1061,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't
 
     let translation =
         time(time_passes, "translation", move || {
-            Trans::trans_crate(tcx, rx)
+            trans.trans_crate(tcx, rx)
         });
     if tcx.sess.profile_queries() {
         profile::dump("profile_queries".to_string())
@@ -1121,25 +1070,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx, Trans: TransCrate>(tcx: TyCtxt<'a, 't
     translation
 }
 
-/// Run LLVM itself, producing a bitcode file, assembly file or object file
-/// as a side effect.
-pub fn phase_5_run_llvm_passes<Trans: TransCrate>(sess: &Session,
-                               dep_graph: &DepGraph,
-                               trans: <Trans as TransCrate>::OngoingCrateTranslation)
-                               -> (CompileResult, <Trans as TransCrate>::TranslatedCrate) {
-    let trans = Trans::join_trans(trans, sess, dep_graph);
-
-    if sess.opts.debugging_opts.incremental_info {
-        Trans::dump_incremental_data(&trans);
-    }
-
-    time(sess.time_passes(),
-         "serialize work products",
-         move || rustc_incremental::save_work_products(sess, dep_graph));
-
-    (sess.compile_status(), trans)
-}
-
 fn escape_dep_filename(filename: &FileName) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
index a985fa073ef8ceca9320640a39c7574fd279fc6a..541405975f6f1991f5e9bab9dd9c6e340f2f316f 100644 (file)
@@ -48,7 +48,7 @@
 extern crate rustc_resolve;
 extern crate rustc_save_analysis;
 #[cfg(feature="llvm")]
-extern crate rustc_trans;
+pub extern crate rustc_trans;
 extern crate rustc_trans_utils;
 extern crate rustc_typeck;
 extern crate serialize;
@@ -66,7 +66,7 @@
 use rustc_save_analysis::DumpHandler;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::CompileIncomplete;
-use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
+use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
 use rustc::session::config::nightly_options;
 use rustc::session::{early_error, early_warn};
 use rustc::lint::Lint;
 pub mod profile;
 pub mod driver;
 pub mod pretty;
-pub mod target_features;
 mod derive_registrar;
 
+pub mod target_features {
+    use syntax::ast;
+    use syntax::symbol::Symbol;
+    use rustc::session::Session;
+    use rustc_trans_utils::trans_crate::TransCrate;
+
+    /// Add `target_feature = "..."` cfgs for a variety of platform
+    /// specific features (SSE, NEON etc.).
+    ///
+    /// This is performed by checking whether a whitelisted set of
+    /// features is available on the target machine, by querying LLVM.
+    pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session, trans: &TransCrate) {
+        let tf = Symbol::intern("target_feature");
+
+        for feat in trans.target_features(sess) {
+            cfg.insert((tf, Some(feat)));
+        }
+
+        if sess.crt_static_feature() {
+            cfg.insert((tf, Some(Symbol::intern("crt-static"))));
+        }
+    }
+}
+
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
@@ -159,25 +182,51 @@ pub fn run<F>(run_compiler: F) -> isize
 pub use rustc_trans::LlvmTransCrate as DefaultTransCrate;
 
 #[cfg(not(feature="llvm"))]
-mod rustc_trans {
-    use syntax_pos::symbol::Symbol;
-    use rustc::session::Session;
-    use rustc::session::config::PrintRequest;
+pub mod rustc_trans {
     pub use rustc_trans_utils::trans_crate::MetadataOnlyTransCrate as LlvmTransCrate;
-    pub use rustc_trans_utils::trans_crate::TranslatedCrate as CrateTranslation;
 
-    pub fn init(_sess: &Session) {}
     pub fn print_version() {}
     pub fn print_passes() {}
-    pub fn print(_req: PrintRequest, _sess: &Session) {}
-    pub fn target_features(_sess: &Session) -> Vec<Symbol> { vec![] }
-
-    pub mod back {
-        pub mod write {
-            pub const RELOC_MODEL_ARGS: [(&'static str, ()); 0] = [];
-            pub const CODE_GEN_MODEL_ARGS: [(&'static str, ()); 0] = [];
-            pub const TLS_MODEL_ARGS: [(&'static str, ()); 0] = [];
+}
+
+fn load_backend_from_dylib(sess: &Session, backend_name: &str) -> Box<TransCrate> {
+    use std::path::Path;
+    use rustc_metadata::dynamic_lib::DynamicLibrary;
+
+    match DynamicLibrary::open(Some(Path::new(backend_name))) {
+        Ok(lib) => {
+            unsafe {
+                let trans = {
+                    let __rustc_codegen_backend: unsafe fn(&Session) -> Box<TransCrate>;
+                    __rustc_codegen_backend = match lib.symbol("__rustc_codegen_backend") {
+                        Ok(f) => ::std::mem::transmute::<*mut u8, _>(f),
+                        Err(e) => sess.fatal(&format!("Couldnt load codegen backend as it\
+                        doesn't export the __rustc_backend_new symbol: {:?}", e)),
+                    };
+                    __rustc_codegen_backend(sess)
+                };
+                ::std::mem::forget(lib);
+                trans
+            }
+        }
+        Err(err) => {
+            sess.fatal(&format!("Couldnt load codegen backend {:?}: {:?}", backend_name, err));
+        }
+    }
+}
+
+pub fn get_trans(sess: &Session) -> Box<TransCrate> {
+    let trans_name = sess.opts.debugging_opts.codegen_backend.clone();
+    match trans_name.as_ref().map(|s|&**s) {
+        None => DefaultTransCrate::new(&sess),
+        Some("llvm") => rustc_trans::LlvmTransCrate::new(&sess),
+        Some("metadata_only") => {
+            rustc_trans_utils::trans_crate::MetadataOnlyTransCrate::new(&sess)
+        }
+        Some(filename) if filename.contains(".") => {
+            load_backend_from_dylib(&sess, &filename)
         }
+        Some(trans_name) => sess.fatal(&format!("Unknown codegen backend {}", trans_name)),
     }
 }
 
@@ -222,30 +271,36 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         },
     };
 
-    let cstore = CStore::new(DefaultTransCrate::metadata_loader());
-
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
     let mut sess = session::build_session_with_codemap(
         sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
     );
-    rustc_trans::init(&sess);
+
+    let trans = get_trans(&sess);
+
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, cfg);
-    target_features::add_configuration(&mut cfg, &sess);
+    target_features::add_configuration(&mut cfg, &sess, &*trans);
     sess.parse_sess.config = cfg;
 
-    do_or_return!(callbacks.late_callback(&matches,
+    let plugins = sess.opts.debugging_opts.extra_plugins.clone();
+
+    let cstore = CStore::new(trans.metadata_loader());
+
+    do_or_return!(callbacks.late_callback(&*trans,
+                                          &matches,
                                           &sess,
                                           &cstore,
                                           &input,
                                           &odir,
                                           &ofile), Some(sess));
 
-    let plugins = sess.opts.debugging_opts.extra_plugins.clone();
     let control = callbacks.build_controller(&sess, &matches);
-    (driver::compile_input(&sess,
+
+    (driver::compile_input(trans,
+                           &sess,
                            &cstore,
                            &input_file_path,
                            &input,
@@ -339,6 +394,7 @@ fn early_callback(&mut self,
     // be called just before actual compilation starts (and before build_controller
     // is called), after all arguments etc. have been completely handled.
     fn late_callback(&mut self,
+                     _: &TransCrate,
                      _: &getopts::Matches,
                      _: &Session,
                      _: &CrateStore,
@@ -518,13 +574,18 @@ fn no_input(&mut self,
                 let mut sess = build_session(sopts.clone(),
                     None,
                     descriptions.clone());
-                rustc_trans::init(&sess);
                 rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let mut cfg = config::build_configuration(&sess, cfg.clone());
-                target_features::add_configuration(&mut cfg, &sess);
+                let trans = get_trans(&sess);
+                target_features::add_configuration(&mut cfg, &sess, &*trans);
                 sess.parse_sess.config = cfg;
-                let should_stop =
-                    RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
+                let should_stop = RustcDefaultCalls::print_crate_info(
+                    &*trans,
+                    &sess,
+                    None,
+                    odir,
+                    ofile
+                );
 
                 if should_stop == Compilation::Stop {
                     return None;
@@ -537,6 +598,7 @@ fn no_input(&mut self,
     }
 
     fn late_callback(&mut self,
+                     trans: &TransCrate,
                      matches: &getopts::Matches,
                      sess: &Session,
                      cstore: &CrateStore,
@@ -544,7 +606,7 @@ fn late_callback(&mut self,
                      odir: &Option<PathBuf>,
                      ofile: &Option<PathBuf>)
                      -> Compilation {
-        RustcDefaultCalls::print_crate_info(sess, Some(input), odir, ofile)
+        RustcDefaultCalls::print_crate_info(trans, sess, Some(input), odir, ofile)
             .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input))
     }
 
@@ -608,11 +670,6 @@ fn build_controller(&mut self,
             control.after_hir_lowering.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
-                                                   i == OutputType::Metadata) {
-            control.after_llvm.stop = Compilation::Stop;
-        }
-
         if save_analysis(sess) {
             enable_save_analysis(&mut control);
         }
@@ -682,11 +739,13 @@ pub fn list_metadata(sess: &Session,
     }
 
 
-    fn print_crate_info(sess: &Session,
+    fn print_crate_info(trans: &TransCrate,
+                        sess: &Session,
                         input: Option<&Input>,
                         odir: &Option<PathBuf>,
                         ofile: &Option<PathBuf>)
                         -> Compilation {
+        use rustc::session::config::PrintRequest::*;
         // PrintRequest::NativeStaticLibs is special - printed during linking
         // (empty iterator returns true)
         if sess.opts.prints.iter().all(|&p| p==PrintRequest::NativeStaticLibs) {
@@ -708,15 +767,14 @@ fn print_crate_info(sess: &Session,
         };
         for req in &sess.opts.prints {
             match *req {
-                PrintRequest::TargetList => {
+                TargetList => {
                     let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
-                PrintRequest::Sysroot => println!("{}", sess.sysroot().display()),
-                PrintRequest::TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
-                PrintRequest::FileNames |
-                PrintRequest::CrateName => {
+                Sysroot => println!("{}", sess.sysroot().display()),
+                TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
+                FileNames | CrateName => {
                     let input = match input {
                         Some(input) => input,
                         None => early_error(ErrorOutputType::default(), "no input file provided"),
@@ -742,7 +800,7 @@ fn print_crate_info(sess: &Session,
                                       .to_string_lossy());
                     }
                 }
-                PrintRequest::Cfg => {
+                Cfg => {
                     let allow_unstable_cfg = UnstableFeatures::from_environment()
                         .is_nightly_build();
 
@@ -782,29 +840,8 @@ fn print_crate_info(sess: &Session,
                         println!("{}", cfg);
                     }
                 }
-                PrintRequest::RelocationModels => {
-                    println!("Available relocation models:");
-                    for &(name, _) in rustc_trans::back::write::RELOC_MODEL_ARGS.iter() {
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::CodeModels => {
-                    println!("Available code models:");
-                    for &(name, _) in rustc_trans::back::write::CODE_GEN_MODEL_ARGS.iter(){
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::TlsModels => {
-                    println!("Available TLS models:");
-                    for &(name, _) in rustc_trans::back::write::TLS_MODEL_ARGS.iter(){
-                        println!("    {}", name);
-                    }
-                    println!("");
-                }
-                PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
-                    rustc_trans::print(*req, sess);
+                RelocationModels | CodeModels | TlsModels | TargetCPUs | TargetFeatures => {
+                    trans.print(*req, sess);
                 }
                 // Any output here interferes with Cargo's parsing of other printed output
                 PrintRequest::NativeStaticLibs => {}
@@ -1282,6 +1319,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
     #[cfg(feature="llvm")]
     all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
+    all_errors.extend_from_slice(&rustc_trans_utils::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_passes::DIAGNOSTICS);
index a771cdad70ff68a13b5c124bc62f570ca903687c..68f4b17a6a3f24a8f7b99bc46052f3df7f7c912c 100644 (file)
@@ -228,7 +228,8 @@ fn call_with_pp_support_hir<'tcx, A, F>(&self,
             }
             PpmTyped => {
                 let control = &driver::CompileController::basic();
-                abort_on_err(driver::phase_3_run_analysis_passes(control,
+                abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
+                                                                 control,
                                                                  sess,
                                                                  cstore,
                                                                  hir_map.clone(),
@@ -1080,7 +1081,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
     let mut out = Vec::new();
 
     let control = &driver::CompileController::basic();
-    abort_on_err(driver::phase_3_run_analysis_passes(control,
+    abort_on_err(driver::phase_3_run_analysis_passes(&*::DefaultTransCrate::new(&sess),
+                                                     control,
                                                      sess,
                                                      cstore,
                                                      hir_map.clone(),
diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs
deleted file mode 100644 (file)
index 9626447..0000000
+++ /dev/null
@@ -1,31 +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 syntax::ast;
-use rustc::session::Session;
-use syntax::symbol::Symbol;
-use rustc_trans;
-
-/// Add `target_feature = "..."` cfgs for a variety of platform
-/// specific features (SSE, NEON etc.).
-///
-/// This is performed by checking whether a whitelisted set of
-/// features is available on the target machine, by querying LLVM.
-pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
-    let tf = Symbol::intern("target_feature");
-
-    for feat in rustc_trans::target_features(sess) {
-        cfg.insert((tf, Some(feat)));
-    }
-
-    if sess.crt_static_feature() {
-        cfg.insert((tf, Some(Symbol::intern("crt-static"))));
-    }
-}
index 371f0e79a3ad1dc9c8f82639821463a4d195f9da..306e7e9c16dce2c5b05611fcad78ba6f9b4e9036 100644 (file)
@@ -16,7 +16,6 @@
 use driver;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
-use rustc_trans;
 use rustc::middle::region;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::traits::{ObligationCause, Reveal};
@@ -29,7 +28,6 @@
 use rustc::hir::map as hir_map;
 use rustc::session::{self, config};
 use rustc::session::config::{OutputFilenames, OutputTypes};
-use rustc_trans_utils::trans_crate::TransCrate;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::abi::Abi;
@@ -104,12 +102,11 @@ fn test_env<F>(source_string: &str,
     options.unstable_features = UnstableFeatures::Allow;
     let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
 
-    let cstore = Rc::new(CStore::new(::DefaultTransCrate::metadata_loader()));
     let sess = session::build_session_(options,
                                        None,
                                        diagnostic_handler,
                                        Rc::new(CodeMap::new(FilePathMapping::empty())));
-    rustc_trans::init(&sess);
+    let cstore = Rc::new(CStore::new(::get_trans(&sess).metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let input = config::Input::Str {
         name: FileName::Anon,
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
new file mode 100644 (file)
index 0000000..46ba94f
--- /dev/null
@@ -0,0 +1,138 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This pass is only used for UNIT TESTS related to incremental
+//! compilation. It tests whether a particular `.o` file will be re-used
+//! from a previous compilation or whether it must be regenerated.
+//!
+//! The user adds annotations to the crate of the following form:
+//!
+//! ```
+//! #![rustc_partition_reused(module="spike", cfg="rpass2")]
+//! #![rustc_partition_translated(module="spike-x", cfg="rpass2")]
+//! ```
+//!
+//! The first indicates (in the cfg `rpass2`) that `spike.o` will be
+//! reused, the second that `spike-x.o` will be recreated. If these
+//! annotations are inaccurate, errors are reported.
+//!
+//! The reason that we use `cfg=...` and not `#[cfg_attr]` is so that
+//! the HIR doesn't change as a result of the annotations, which might
+//! perturb the reuse results.
+
+use rustc::dep_graph::{DepNode, DepConstructor};
+use rustc::mir::mono::CodegenUnit;
+use rustc::ty::TyCtxt;
+use syntax::ast;
+use syntax_pos::symbol::Symbol;
+use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
+
+const MODULE: &'static str = "module";
+const CFG: &'static str = "cfg";
+
+#[derive(Debug, PartialEq, Clone, Copy)]
+enum Disposition { Reused, Translated }
+
+pub fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    tcx.dep_graph.with_ignore(|| {
+        if tcx.sess.opts.incremental.is_none() {
+            return;
+        }
+
+        let ams = AssertModuleSource { tcx };
+        for attr in &tcx.hir.krate().attrs {
+            ams.check_attr(attr);
+        }
+    })
+}
+
+struct AssertModuleSource<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
+    fn check_attr(&self, attr: &ast::Attribute) {
+        let disposition = if attr.check_name(ATTR_PARTITION_REUSED) {
+            Disposition::Reused
+        } else if attr.check_name(ATTR_PARTITION_TRANSLATED) {
+            Disposition::Translated
+        } else {
+            return;
+        };
+
+        if !self.check_config(attr) {
+            debug!("check_attr: config does not match, ignoring attr");
+            return;
+        }
+
+        let mname = self.field(attr, MODULE);
+        let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
+        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
+
+        let dep_node = DepNode::new(self.tcx,
+                                    DepConstructor::CompileCodegenUnit(mangled_cgu_name));
+
+        if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
+            match (disposition, loaded_from_cache) {
+                (Disposition::Reused, false) => {
+                    self.tcx.sess.span_err(
+                        attr.span,
+                        &format!("expected module named `{}` to be Reused but is Translated",
+                                 mname));
+                }
+                (Disposition::Translated, true) => {
+                    self.tcx.sess.span_err(
+                        attr.span,
+                        &format!("expected module named `{}` to be Translated but is Reused",
+                                 mname));
+                }
+                (Disposition::Reused, true) |
+                (Disposition::Translated, false) => {
+                    // These are what we would expect.
+                }
+            }
+        } else {
+            self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname));
+        }
+    }
+
+    fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name {
+        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
+            if item.check_name(name) {
+                if let Some(value) = item.value_str() {
+                    return value;
+                } else {
+                    self.tcx.sess.span_fatal(
+                        item.span,
+                        &format!("associated value expected for `{}`", name));
+                }
+            }
+        }
+
+        self.tcx.sess.span_fatal(
+            attr.span,
+            &format!("no field `{}`", name));
+    }
+
+    /// Scan for a `cfg="foo"` attribute and check whether we have a
+    /// cfg flag called `foo`.
+    fn check_config(&self, attr: &ast::Attribute) -> bool {
+        let config = &self.tcx.sess.parse_sess.config;
+        let value = self.field(attr, CFG);
+        debug!("check_config(config={:?}, value={:?})", config, value);
+        if config.iter().any(|&(name, _)| name == value) {
+            debug!("check_config: matched");
+            return true;
+        }
+        debug!("check_config: no match found");
+        return false;
+    }
+
+}
index 0b827a0ee9873e58cb7be015eaefe98aca199c61..b53ee1daada429427c18040a8bdf48619b7972fd 100644 (file)
@@ -32,6 +32,7 @@
 extern crate syntax_pos;
 
 mod assert_dep_graph;
+pub mod assert_module_sources;
 mod persist;
 
 pub use assert_dep_graph::assert_dep_graph;
index bf5d16696f9cd28f440b94e5e10ef0474ea7b6de..2267d2b89ccf1d80d925659bb77a1db4b50cd230 100644 (file)
@@ -416,7 +416,7 @@ fn check_type_for_ffi(&self,
                 }
                 match def.adt_kind() {
                     AdtKind::Struct => {
-                        if !def.repr.c() {
+                        if !def.repr.c() && !def.repr.transparent() {
                             return FfiUnsafe("found struct without foreign-function-safe \
                                               representation annotation in foreign module, \
                                               consider adding a #[repr(C)] attribute to the type");
@@ -427,13 +427,24 @@ fn check_type_for_ffi(&self,
                                               adding a member to this struct");
                         }
 
-                        // We can't completely trust repr(C) markings; make sure the
-                        // fields are actually safe.
+                        // We can't completely trust repr(C) and repr(transparent) markings;
+                        // make sure the fields are actually safe.
                         let mut all_phantom = true;
                         for field in &def.non_enum_variant().fields {
                             let field_ty = cx.fully_normalize_associated_types_in(
                                 &field.ty(cx, substs)
                             );
+                            // repr(transparent) types are allowed to have arbitrary ZSTs, not just
+                            // PhantomData -- skip checking all ZST fields
+                            if def.repr.transparent() {
+                                let is_zst = (cx, cx.param_env(field.did))
+                                    .layout_of(field_ty)
+                                    .map(|layout| layout.is_zst())
+                                    .unwrap_or(false);
+                                if is_zst {
+                                    continue;
+                                }
+                            }
                             let r = self.check_type_for_ffi(cache, field_ty);
                             match r {
                                 FfiSafe => {
index 4e066ecf999e3f0eb99292e3970ea802959b0549..ef6475f9ee4c7b403aa607845363774d633425aa 100644 (file)
@@ -302,6 +302,18 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
             Assign(_, ref value) => (value, "assigned value", false),
             AssignOp(.., ref value) => (value, "assigned value", false),
             InPlace(_, ref value) => (value, "emplacement value", false),
+            Call(_, ref args) => {
+                for arg in args {
+                    self.check_unused_parens_core(cx, arg, "function argument", false)
+                }
+                return;
+            },
+            MethodCall(_, ref args) => {
+                for arg in &args[1..] { // first "argument" is self (which sometimes needs parens)
+                    self.check_unused_parens_core(cx, arg, "method argument", false)
+                }
+                return;
+            }
             _ => return,
         };
         self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
index 946eecaa45f7d6fe76d930258feda93a6b04cbb9..246f5c9255ef414d1e450752891c42ba6c479292 100644 (file)
@@ -15,7 +15,7 @@
 use native_libs::relevant_lib;
 use schema::CrateRoot;
 
-use rustc::hir::def_id::{CrateNum, DefIndex, CRATE_DEF_INDEX};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
 use rustc::hir::svh::Svh;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::DepKind;
@@ -532,8 +532,7 @@ fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span:
             Err(err) => self.sess.span_fatal(span, &err),
         };
 
-        let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator,
-                                                             root.macro_derive_registrar.unwrap());
+        let sym = self.sess.generate_derive_registrar_symbol(root.disambiguator);
         let registrar = unsafe {
             let sym = match lib.symbol(&sym) {
                 Ok(f) => f,
@@ -588,7 +587,7 @@ fn register_bang_proc_macro(&mut self,
     pub fn find_plugin_registrar(&mut self,
                                  span: Span,
                                  name: &str)
-                                 -> Option<(PathBuf, CrateDisambiguator, DefIndex)> {
+                                 -> Option<(PathBuf, CrateDisambiguator)> {
         let name = Symbol::intern(name);
         let ekrate = self.read_extension_crate(span, name, name);
 
@@ -603,11 +602,11 @@ pub fn find_plugin_registrar(&mut self,
         }
 
         let root = ekrate.metadata.get_root();
-        match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
-            (Some(dylib), Some(reg)) => {
-                Some((dylib.to_path_buf(), root.disambiguator, reg))
+        match ekrate.dylib.as_ref() {
+            Some(dylib) => {
+                Some((dylib.to_path_buf(), root.disambiguator))
             }
-            (None, Some(_)) => {
+            None => {
                 span_err!(self.sess, span, E0457,
                           "plugin `{}` only found in rlib format, but must be available \
                            in dylib format",
@@ -616,7 +615,6 @@ pub fn find_plugin_registrar(&mut self,
                 // empty dylib.
                 None
             }
-            _ => None,
         }
     }
 
index 195335dd64c1349aa0692784295af8737e9b39a2..ea05a513f7e7d9c5d7190d3cd00cf91d885eace3 100644 (file)
@@ -24,4 +24,3 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 byteorder = { version = "1.1", features = ["i128"] }
 rustc_apfloat = { path = "../librustc_apfloat" }
-rustc_trans_utils = { path = "../librustc_trans_utils" }
index 7ca4ebd1cb29660dd60576d21669f5976a06da05..3a39eb5c908de3660efe06d05d7a7da6e2d4d9a1 100644 (file)
@@ -69,6 +69,7 @@ fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
     fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
         match ty_context {
             TyContext::ReturnTy(source_info) |
+            TyContext::YieldTy(source_info) |
             TyContext::LocalDecl { source_info, .. } => {
                 span_bug!(source_info.span,
                           "should not be visiting outside of the CFG: {:?}",
index da136a34b99710b80eeea8a40d7707662e66982b..9a2f98d4622f77eb00cfd2d2898e29d049b0af05 100644 (file)
@@ -989,7 +989,7 @@ fn report_error(
 
         if let (Some(f), Some(o)) = (fr_name, outlived_fr_name) {
             let tables = infcx.tcx.typeck_tables_of(mir_def_id);
-            let nice = NiceRegionError::new(infcx.tcx, blame_span, o, f, Some(tables));
+            let nice = NiceRegionError::new_from_span(infcx.tcx, blame_span, o, f, Some(tables));
             if let Some(ErrorReported) = nice.try_report() {
                 return;
             }
index 4aee48b979d6150541087aef8e85d8ba65a0ebd4..c54acda8a6252786b26cb30083b1c85663fd7c37 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, ClosureSubsts, Ty, TypeFoldable};
+use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
 use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
@@ -90,6 +90,21 @@ fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Locati
         *constant = self.renumber_regions(ty_context, &*constant);
     }
 
+    fn visit_generator_interior(&mut self,
+                                interior: &mut GeneratorInterior<'tcx>,
+                                location: Location) {
+        debug!(
+            "visit_generator_interior(interior={:?}, location={:?})",
+            interior,
+            location,
+        );
+
+        let ty_context = TyContext::Location(location);
+        *interior = self.renumber_regions(ty_context, interior);
+
+        debug!("visit_generator_interior: interior={:?}", interior);
+    }
+
     fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
         debug!(
             "visit_closure_substs(substs={:?}, location={:?})",
index 9e88a632f5c3dc833d10733bfe4858c2b7fee395..b1aeae0b76bb112b48234a286e1909d050db9dd9 100644 (file)
@@ -60,6 +60,15 @@ pub(super) fn equate_inputs_and_outputs(
             self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty);
         }
 
+        assert!(
+            mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() ||
+            mir.yield_ty.is_none() && universal_regions.yield_ty.is_none()
+            );
+        if let Some(mir_yield_ty) = mir.yield_ty {
+            let ur_yield_ty = universal_regions.yield_ty.unwrap();
+            self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty);
+        }
+
         // Return types are a bit more complex. They may contain existential `impl Trait`
         // types.
         debug!(
index 45604d52958c185f7535ab98a4bc3ebd00ad0d91..e47e3c728dff21327697f69dbd55674052c23fa4 100644 (file)
@@ -96,6 +96,8 @@ pub struct UniversalRegions<'tcx> {
     /// our special inference variable there, we would mess that up.
     pub region_bound_pairs: Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>,
 
+    pub yield_ty: Option<Ty<'tcx>>,
+
     relations: UniversalRegionRelations,
 }
 
@@ -505,6 +507,13 @@ fn build(mut self) -> UniversalRegions<'tcx> {
             num_universals
         );
 
+        let yield_ty = match defining_ty {
+            DefiningTy::Generator(def_id, substs, _) => {
+                Some(substs.generator_yield_ty(def_id, self.infcx.tcx))
+            }
+            _ => None,
+        };
+
         UniversalRegions {
             indices,
             fr_static,
@@ -516,6 +525,7 @@ fn build(mut self) -> UniversalRegions<'tcx> {
             unnormalized_output_ty,
             unnormalized_input_tys,
             region_bound_pairs: self.region_bound_pairs,
+            yield_ty: yield_ty,
             relations: self.relations,
         }
     }
@@ -584,13 +594,9 @@ fn compute_indices(
 
             DefiningTy::FnDef(_, substs) => substs,
 
-            // When we encounter other sorts of constant
-            // expressions, such as the `22` in `[foo; 22]`, we can
-            // get the type `usize` here. For now, just return an
-            // empty vector of substs in this case, since there are no
-            // generics in scope in such expressions right now.
+            // When we encounter a constant body, just return whatever
+            // substitutions are in scope for that constant.
             DefiningTy::Const(_) => {
-                assert!(identity_substs.is_empty());
                 identity_substs
             }
         };
@@ -654,9 +660,8 @@ fn compute_inputs_and_output(
                 sig.inputs_and_output()
             }
 
-            // This happens on things like `[foo; 22]`. Hence, no
-            // inputs, one output, but it seems like we need a more
-            // general way to handle this category of MIR.
+            // For a constant body, there are no inputs, and one
+            // "output" (the type of the constant).
             DefiningTy::Const(ty) => ty::Binder::dummy(tcx.mk_type_list(iter::once(ty))),
         }
     }
@@ -799,10 +804,12 @@ fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>,
     /// during initialization. Relies on the `indices` map having been
     /// fully initialized.
     pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
-        match r {
-            ty::ReEarlyBound(..) | ty::ReStatic => *self.indices.get(&r).unwrap(),
-            ty::ReVar(..) => r.to_region_vid(),
-            _ => bug!("cannot convert `{:?}` to a region vid", r),
+        if let ty::ReVar(..) = r {
+            r.to_region_vid()
+        } else {
+            *self.indices.get(&r).unwrap_or_else(|| {
+                bug!("cannot convert `{:?}` to a region vid", r)
+            })
         }
     }
 
index b2357b771572fa6a1896b97612fa0e8fe0f22d6f..bdcbfc0bdd85e9f6506216ac340d219cfcdb67a3 100644 (file)
@@ -174,12 +174,50 @@ pub fn add_variants_to_switch<'pat>(&mut self,
         }
     }
 
+    /// Convert a byte array or byte slice to a byte slice.
+    fn to_slice_operand(&mut self,
+                        block: BasicBlock,
+                        source_info: SourceInfo,
+                        operand: Operand<'tcx>)
+                        -> Operand<'tcx>
+    {
+        let tcx = self.hir.tcx();
+        let ty = operand.ty(&self.local_decls, tcx);
+        debug!("to_slice_operand({:?}, {:?}: {:?})", block, operand, ty);
+        match ty.sty {
+            ty::TyRef(region, mt) => match mt.ty.sty {
+                ty::TyArray(ety, _) => {
+                    let ty = tcx.mk_imm_ref(region, tcx.mk_slice(ety));
+                    let temp = self.temp(ty, source_info.span);
+                    self.cfg.push_assign(block, source_info, &temp,
+                                         Rvalue::Cast(CastKind::Unsize, operand, ty));
+                    Operand::Move(temp)
+                }
+                ty::TySlice(_) => operand,
+                _ => {
+                    span_bug!(source_info.span,
+                              "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+                }
+            }
+            _ => {
+                span_bug!(source_info.span,
+                          "bad operand {:?}: {:?} to `to_slice_operand`", operand, ty)
+            }
+        }
+
+    }
+
     /// Generates the code to perform a test.
     pub fn perform_test(&mut self,
                         block: BasicBlock,
                         place: &Place<'tcx>,
                         test: &Test<'tcx>)
                         -> Vec<BasicBlock> {
+        debug!("perform_test({:?}, {:?}: {:?}, {:?})",
+               block,
+               place,
+               place.ty(&self.local_decls, self.hir.tcx()),
+               test);
         let source_info = self.source_info(test.span);
         match test.kind {
             TestKind::Switch { adt_def, ref variants } => {
@@ -258,45 +296,35 @@ pub fn perform_test(&mut self,
                 ret
             }
 
-            TestKind::Eq { value, mut ty } => {
+            TestKind::Eq { value, ty } => {
+                let tcx = self.hir.tcx();
                 let mut val = Operand::Copy(place.clone());
 
                 // If we're using b"..." as a pattern, we need to insert an
                 // unsizing coercion, as the byte string has the type &[u8; N].
-                let expect = if let ConstVal::ByteStr(bytes) = value.val {
-                    let tcx = self.hir.tcx();
-
-                    // Unsize the place to &[u8], too, if necessary.
-                    if let ty::TyRef(region, mt) = ty.sty {
-                        if let ty::TyArray(_, _) = mt.ty.sty {
-                            ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
-                            let val_slice = self.temp(ty, test.span);
-                            self.cfg.push_assign(block, source_info, &val_slice,
-                                                 Rvalue::Cast(CastKind::Unsize, val, ty));
-                            val = Operand::Move(val_slice);
-                        }
-                    }
-
-                    assert!(ty.is_slice());
-
+                //
+                // We want to do this even when the scrutinee is a reference to an
+                // array, so we can call `<[u8]>::eq` rather than having to find an
+                // `<[u8; N]>::eq`.
+                let (expect, val) = if let ConstVal::ByteStr(bytes) = value.val {
                     let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len() as u64);
                     let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
                     let array = self.literal_operand(test.span, array_ref, Literal::Value {
                         value
                     });
 
-                    let slice = self.temp(ty, test.span);
-                    self.cfg.push_assign(block, source_info, &slice,
-                                         Rvalue::Cast(CastKind::Unsize, array, ty));
-                    Operand::Move(slice)
+                    let val = self.to_slice_operand(block, source_info, val);
+                    let slice = self.to_slice_operand(block, source_info, array);
+                    (slice, val)
                 } else {
-                    self.literal_operand(test.span, ty, Literal::Value {
+                    (self.literal_operand(test.span, ty, Literal::Value {
                         value
-                    })
+                    }), val)
                 };
 
                 // Use PartialEq::eq for &str and &[u8] slices, instead of BinOp::Eq.
                 let fail = self.cfg.start_new_block();
+                let ty = expect.ty(&self.local_decls, tcx);
                 if let ty::TyRef(_, mt) = ty.sty {
                     assert!(ty.is_slice());
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
index f76aea19677d9b90f60f17c2f8fd20249886f2b7..f543a33b130b6f9b2f05f402caa84a0ff8e3e9a3 100644 (file)
@@ -131,7 +131,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
 }
 
 impl ReserveOrActivateIndex {
-    fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2)) }
+    fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) }
     fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) }
 
     pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 }
index 5379bf3f5a7aeed0db424d3ab5617e611b170eef..1699ad0f19cf63eed34c815acd17b523e9a0c9fa 100644 (file)
@@ -57,7 +57,6 @@
 extern crate log_settings;
 extern crate rustc_apfloat;
 extern crate byteorder;
-extern crate rustc_trans_utils;
 
 mod diagnostics;
 
index 024334f1c849c2f0464a560658a3b52d078fffb3..072c339813490bbd2e0e450de7674a8379b0eb68 100644 (file)
@@ -26,6 +26,7 @@
 use std::iter;
 use rustc::mir::mono::Linkage;
 use syntax_pos::symbol::Symbol;
+use syntax::codemap::Span;
 pub use rustc::mir::mono::MonoItem;
 
 pub fn linkage_by_name(name: &str) -> Option<Linkage> {
@@ -244,6 +245,18 @@ fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             result
         }
     }
+
+    fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
+        match *self.as_mono_item() {
+            MonoItem::Fn(Instance { def, .. }) => {
+                tcx.hir.as_local_node_id(def.def_id())
+            }
+            MonoItem::Static(node_id) |
+            MonoItem::GlobalAsm(node_id) => {
+                Some(node_id)
+            }
+        }.map(|node_id| tcx.hir.span(node_id))
+    }
 }
 
 impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
index fcf0d71dccb48ab2a7121c28c745f7efa9635fd2..95ebb6c970a588ec4c3758818f4bd7ff88bec703 100644 (file)
 pub mod item;
 pub mod partitioning;
 
+#[inline(never)] // give this a place in the profiler
+pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
+    where I: Iterator<Item=&'a MonoItem<'tcx>>
+{
+    let mut symbols: Vec<_> = trans_items.map(|trans_item| {
+        (trans_item, trans_item.symbol_name(tcx))
+    }).collect();
+
+    (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
+        sym1.cmp(sym2)
+    });
+
+    for pair in (&symbols[..]).windows(2) {
+        let sym1 = &pair[0].1;
+        let sym2 = &pair[1].1;
+
+        if *sym1 == *sym2 {
+            let trans_item1 = pair[0].0;
+            let trans_item2 = pair[1].0;
+
+            let span1 = trans_item1.local_span(tcx);
+            let span2 = trans_item2.local_span(tcx);
+
+            // Deterministically select one of the spans for error reporting
+            let span = match (span1, span2) {
+                (Some(span1), Some(span2)) => {
+                    Some(if span1.lo().0 > span2.lo().0 {
+                        span1
+                    } else {
+                        span2
+                    })
+                }
+                (Some(span), None) |
+                (None, Some(span)) => Some(span),
+                _ => None
+            };
+
+            let error_message = format!("symbol `{}` is already defined", sym1);
+
+            if let Some(span) = span {
+                tcx.sess.span_fatal(span, &error_message)
+            } else {
+                tcx.sess.fatal(&error_message)
+            }
+        }
+    }
+}
+
 fn fn_once_adapter_instance<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     closure_did: DefId,
index 78d55ad34ed45a77fe97d293120c910d543beef6..6ab5fee79c661e72b82d7f7c85cb5dcc1f541c73 100644 (file)
@@ -518,7 +518,7 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(
     w: &mut Write,
 ) -> io::Result<()> {
     write_mir_sig(tcx, src, mir, w)?;
-    writeln!(w, " {{")?;
+    writeln!(w, "{{")?;
 
     // construct a scope tree and write it out
     let mut scope_tree: FxHashMap<VisibilityScope, Vec<VisibilityScope>> = FxHashMap();
@@ -581,13 +581,20 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write) -> io::R
                 write!(w, "{:?}: {}", Place::Local(arg), mir.local_decls[arg].ty)?;
             }
 
-            write!(w, ") -> {}", mir.return_ty())
+            write!(w, ") -> {}", mir.return_ty())?;
         }
         (hir::BodyOwnerKind::Const, _) | (hir::BodyOwnerKind::Static(_), _) | (_, Some(_)) => {
             assert_eq!(mir.arg_count, 0);
-            write!(w, ": {} =", mir.return_ty())
+            write!(w, ": {} =", mir.return_ty())?;
         }
     }
+
+    if let Some(yield_ty) = mir.yield_ty {
+        writeln!(w)?;
+        writeln!(w, "yields {}", yield_ty)?;
+    }
+
+    Ok(())
 }
 
 fn write_temp_decls(mir: &Mir, w: &mut Write) -> io::Result<()> {
index 8a4ec03b20efcc74f14efa5b958ccb04dda050a2..a46b85d93cbb82cc3024e0b533822d26997a7739 100644 (file)
@@ -100,8 +100,8 @@ fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
     fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
         let registrar = self.reader.find_plugin_registrar(span, name);
 
-        if let Some((lib, disambiguator, index)) = registrar {
-            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
+        if let Some((lib, disambiguator)) = registrar {
+            let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator);
             let fun = self.dylink_registrar(span, lib, symbol);
             self.plugins.push(PluginRegistrar {
                 fun,
index 3f0f1a1a4cb58ef2cd5c3e1fef2966955c3e5874..8a29155d12d5b749303ce20e5b10842ad41c5105 100644 (file)
@@ -1621,6 +1621,59 @@ mod SomeModule {
 ```
 "##,
 
+E0659: r##"
+An item usage is ambiguous.
+
+Erroneous code example:
+
+```compile_fail,E0659
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); // ERROR: `foo` is ambiguous
+}
+```
+
+This error generally appears when two items with the same name are imported into
+a module. Here, the `foo` functions are imported and reexported from the
+`collider` module and therefore, when we're using `collider::foo()`, both
+functions collide.
+
+To solve this error, the best solution is generally to keep the path before the
+item when using it. Example:
+
+```
+pub mod moon {
+    pub fn foo() {}
+}
+
+pub mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon;
+    pub use earth;
+}
+
+fn main() {
+    collider::moon::foo(); // ok!
+    collider::earth::foo(); // ok!
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
index 5b9b3767cb62fb34907b8a373b3b1c5090b6125b..d9ae776a4d7b26a9b499578b8714813a50edbe25 100644 (file)
@@ -898,7 +898,7 @@ fn def(self) -> Def {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 enum PathResult<'a> {
     Module(Module<'a>),
     NonModule(PathResolution),
@@ -963,7 +963,7 @@ fn new(parent: Option<Module<'a>>,
             unresolved_invocations: RefCell::new(FxHashSet()),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
-            globs: RefCell::new((Vec::new())),
+            globs: RefCell::new(Vec::new()),
             traits: RefCell::new(None),
             populated: Cell::new(normal_ancestor_id.is_local()),
             span,
@@ -2568,7 +2568,8 @@ fn smart_resolve_path_fragment(&mut self,
             let code = source.error_code(def.is_some());
             let (base_msg, fallback_label, base_span) = if let Some(def) = def {
                 (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
-                 format!("not a {}", expected), span)
+                 format!("not a {}", expected),
+                 span)
             } else {
                 let item_str = path[path.len() - 1].node;
                 let item_span = path[path.len() - 1].span;
@@ -2585,7 +2586,8 @@ fn smart_resolve_path_fragment(&mut self,
                     (mod_prefix, format!("`{}`", names_to_string(mod_path)))
                 };
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
-                 format!("not found in {}", mod_str), item_span)
+                 format!("not found in {}", mod_str),
+                 item_span)
             };
             let code = DiagnosticId::Error(code.into());
             let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
@@ -2700,20 +2702,37 @@ fn smart_resolve_path_fragment(&mut self,
                         }
                         return (err, candidates);
                     },
-                    _ if ns == ValueNS && is_struct_like(def) => {
-                        if let Def::Struct(def_id) = def {
-                            if let Some((ctor_def, ctor_vis))
-                                    = this.struct_constructors.get(&def_id).cloned() {
-                                if is_expected(ctor_def) && !this.is_accessible(ctor_vis) {
-                                    err.span_label(span, format!("constructor is not visible \
-                                                                   here due to private fields"));
-                                }
+                    (Def::Struct(def_id), _) if ns == ValueNS => {
+                        if let Some((ctor_def, ctor_vis))
+                                = this.struct_constructors.get(&def_id).cloned() {
+                            let accessible_ctor = this.is_accessible(ctor_vis);
+                            if is_expected(ctor_def) && !accessible_ctor {
+                                err.span_label(span, format!("constructor is not visible \
+                                                              here due to private fields"));
                             }
+                        } else {
+                            err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
+                                                         path_str));
                         }
+                        return (err, candidates);
+                    }
+                    (Def::Union(..), _) |
+                    (Def::Variant(..), _) |
+                    (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
                         err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
                                                      path_str));
                         return (err, candidates);
                     }
+                    (Def::SelfTy(..), _) if ns == ValueNS => {
+                        err.span_label(span, fallback_label);
+                        err.note("can't use `Self` as a constructor, you must use the \
+                                  implemented struct");
+                        return (err, candidates);
+                    }
+                    (Def::TyAlias(_), _) | (Def::AssociatedTy(..), _) if ns == ValueNS => {
+                        err.note("can't use a type alias as a constructor");
+                        return (err, candidates);
+                    }
                     _ => {}
                 }
             }
@@ -3783,7 +3802,7 @@ fn report_errors(&mut self, krate: &Crate) {
                 self.session.buffer_lint(lint::builtin::LEGACY_IMPORTS, id, span, &msg);
             } else {
                 let mut err =
-                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
+                    struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
                 err.span_note(b1.span, &msg1);
                 match b2.def() {
                     Def::Macro(..) if b2.span == DUMMY_SP =>
@@ -3965,13 +3984,6 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
     }
 }
 
-fn is_struct_like(def: Def) -> bool {
-    match def {
-        Def::VariantCtor(_, CtorKind::Fictive) => true,
-        _ => PathSource::Struct.is_expected(def),
-    }
-}
-
 fn is_self_type(path: &[SpannedIdent], namespace: Namespace) -> bool {
     namespace == TypeNS && path.len() == 1 && path[0].node.name == keywords::SelfType.name()
 }
index 07f9b8fed8b57593c709d94cbef020083e8b732a..5079ce7752354e1021440244a5ee9f3c9bd984c7 100644 (file)
@@ -608,9 +608,6 @@ pub fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>)
     }
 
     pub fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
-        if self.pad.is_some() {
-            *idx += 1;
-        }
         let mut next = || {
             let val = llvm::get_param(bx.llfn(), *idx as c_uint);
             *idx += 1;
index 9abb6d66f9c0f6f210f9770c7540931bb4929899..fd5aa1364d381951bcf3025a77b4f62164064da5 100644 (file)
@@ -19,7 +19,7 @@
 use ModuleLlvm;
 use llvm::{self, False, True};
 
-pub unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
+pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) {
     let llcx = mods.llcx;
     let llmod = mods.llmod;
     let usize = match &tcx.sess.target.target.target_pointer_width[..] {
diff --git a/src/librustc_trans/assert_module_sources.rs b/src/librustc_trans/assert_module_sources.rs
deleted file mode 100644 (file)
index 745197d..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! This pass is only used for UNIT TESTS related to incremental
-//! compilation. It tests whether a particular `.o` file will be re-used
-//! from a previous compilation or whether it must be regenerated.
-//!
-//! The user adds annotations to the crate of the following form:
-//!
-//! ```
-//! #![rustc_partition_reused(module="spike", cfg="rpass2")]
-//! #![rustc_partition_translated(module="spike-x", cfg="rpass2")]
-//! ```
-//!
-//! The first indicates (in the cfg `rpass2`) that `spike.o` will be
-//! reused, the second that `spike-x.o` will be recreated. If these
-//! annotations are inaccurate, errors are reported.
-//!
-//! The reason that we use `cfg=...` and not `#[cfg_attr]` is so that
-//! the HIR doesn't change as a result of the annotations, which might
-//! perturb the reuse results.
-
-use rustc::dep_graph::{DepNode, DepConstructor};
-use rustc::mir::mono::CodegenUnit;
-use rustc::ty::TyCtxt;
-use syntax::ast;
-use syntax_pos::symbol::Symbol;
-use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_TRANSLATED};
-
-const MODULE: &'static str = "module";
-const CFG: &'static str = "cfg";
-
-#[derive(Debug, PartialEq, Clone, Copy)]
-enum Disposition { Reused, Translated }
-
-pub(crate) fn assert_module_sources<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.dep_graph.with_ignore(|| {
-        if tcx.sess.opts.incremental.is_none() {
-            return;
-        }
-
-        let ams = AssertModuleSource { tcx };
-        for attr in &tcx.hir.krate().attrs {
-            ams.check_attr(attr);
-        }
-    })
-}
-
-struct AssertModuleSource<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>
-}
-
-impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> {
-    fn check_attr(&self, attr: &ast::Attribute) {
-        let disposition = if attr.check_name(ATTR_PARTITION_REUSED) {
-            Disposition::Reused
-        } else if attr.check_name(ATTR_PARTITION_TRANSLATED) {
-            Disposition::Translated
-        } else {
-            return;
-        };
-
-        if !self.check_config(attr) {
-            debug!("check_attr: config does not match, ignoring attr");
-            return;
-        }
-
-        let mname = self.field(attr, MODULE);
-        let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str());
-        let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str();
-
-        let dep_node = DepNode::new(self.tcx,
-                                    DepConstructor::CompileCodegenUnit(mangled_cgu_name));
-
-        if let Some(loaded_from_cache) = self.tcx.dep_graph.was_loaded_from_cache(&dep_node) {
-            match (disposition, loaded_from_cache) {
-                (Disposition::Reused, false) => {
-                    self.tcx.sess.span_err(
-                        attr.span,
-                        &format!("expected module named `{}` to be Reused but is Translated",
-                                 mname));
-                }
-                (Disposition::Translated, true) => {
-                    self.tcx.sess.span_err(
-                        attr.span,
-                        &format!("expected module named `{}` to be Translated but is Reused",
-                                 mname));
-                }
-                (Disposition::Reused, true) |
-                (Disposition::Translated, false) => {
-                    // These are what we would expect.
-                }
-            }
-        } else {
-            self.tcx.sess.span_err(attr.span, &format!("no module named `{}`", mname));
-        }
-    }
-
-    fn field(&self, attr: &ast::Attribute, name: &str) -> ast::Name {
-        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
-            if item.check_name(name) {
-                if let Some(value) = item.value_str() {
-                    return value;
-                } else {
-                    self.tcx.sess.span_fatal(
-                        item.span,
-                        &format!("associated value expected for `{}`", name));
-                }
-            }
-        }
-
-        self.tcx.sess.span_fatal(
-            attr.span,
-            &format!("no field `{}`", name));
-    }
-
-    /// Scan for a `cfg="foo"` attribute and check whether we have a
-    /// cfg flag called `foo`.
-    fn check_config(&self, attr: &ast::Attribute) -> bool {
-        let config = &self.tcx.sess.parse_sess.config;
-        let value = self.field(attr, CFG);
-        debug!("check_config(config={:?}, value={:?})", config, value);
-        if config.iter().any(|&(name, _)| name == value) {
-            debug!("check_config: matched");
-            return true;
-        }
-        debug!("check_config: no match found");
-        return false;
-    }
-
-}
index ea68e3b28b668e8047630f476b673c51fc0ec071..3b765a493e0e79a15d98982f4fbb986d7fa0b0be 100644 (file)
 use std::ffi::{OsStr, OsString};
 use std::fmt;
 use std::io;
-use std::process::{self, Output, Child};
+use std::mem;
+use std::process::{self, Output};
 
+#[derive(Clone)]
 pub struct Command {
-    program: OsString,
+    program: Program,
     args: Vec<OsString>,
     env: Vec<(OsString, OsString)>,
 }
 
+#[derive(Clone)]
+enum Program {
+    Normal(OsString),
+    CmdBatScript(OsString),
+}
+
 impl Command {
     pub fn new<P: AsRef<OsStr>>(program: P) -> Command {
-        Command::_new(program.as_ref())
+        Command::_new(Program::Normal(program.as_ref().to_owned()))
+    }
+
+    pub fn bat_script<P: AsRef<OsStr>>(program: P) -> Command {
+        Command::_new(Program::CmdBatScript(program.as_ref().to_owned()))
     }
 
-    fn _new(program: &OsStr) -> Command {
+    fn _new(program: Program) -> Command {
         Command {
-            program: program.to_owned(),
+            program,
             args: Vec::new(),
             env: Vec::new(),
         }
@@ -81,12 +93,15 @@ pub fn output(&mut self) -> io::Result<Output> {
         self.command().output()
     }
 
-    pub fn spawn(&mut self) -> io::Result<Child> {
-        self.command().spawn()
-    }
-
     pub fn command(&self) -> process::Command {
-        let mut ret = process::Command::new(&self.program);
+        let mut ret = match self.program {
+            Program::Normal(ref p) => process::Command::new(p),
+            Program::CmdBatScript(ref p) => {
+                let mut c = process::Command::new("cmd");
+                c.arg("/c").arg(p);
+                c
+            }
+        };
         ret.args(&self.args);
         ret.envs(self.env.clone());
         return ret
@@ -94,16 +109,45 @@ pub fn command(&self) -> process::Command {
 
     // extensions
 
-    pub fn get_program(&self) -> &OsStr {
-        &self.program
+    pub fn take_args(&mut self) -> Vec<OsString> {
+        mem::replace(&mut self.args, Vec::new())
     }
 
-    pub fn get_args(&self) -> &[OsString] {
-        &self.args
-    }
+    /// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
+    /// or `false` if we should attempt to spawn and see what the OS says.
+    pub fn very_likely_to_exceed_some_spawn_limit(&self) -> bool {
+        // We mostly only care about Windows in this method, on Unix the limits
+        // can be gargantuan anyway so we're pretty unlikely to hit them
+        if cfg!(unix) {
+            return false
+        }
 
-    pub fn get_env(&self) -> &[(OsString, OsString)] {
-        &self.env
+        // Ok so on Windows to spawn a process is 32,768 characters in its
+        // command line [1]. Unfortunately we don't actually have access to that
+        // as it's calculated just before spawning. Instead we perform a
+        // poor-man's guess as to how long our command line will be. We're
+        // assuming here that we don't have to escape every character...
+        //
+        // Turns out though that `cmd.exe` has even smaller limits, 8192
+        // characters [2]. Linkers can often be batch scripts (for example
+        // Emscripten, Gecko's current build system) which means that we're
+        // running through batch scripts. These linkers often just forward
+        // arguments elsewhere (and maybe tack on more), so if we blow 8192
+        // bytes we'll typically cause them to blow as well.
+        //
+        // Basically as a result just perform an inflated estimate of what our
+        // command line will look like and test if it's > 8192 (we actually
+        // test against 6k to artificially inflate our estimate). If all else
+        // fails we'll fall back to the normal unix logic of testing the OS
+        // error code if we fail to spawn and automatically re-spawning the
+        // linker with smaller arguments.
+        //
+        // [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
+        // [2]: https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
+
+        let estimated_command_line_len =
+            self.args.iter().map(|a| a.len()).sum::<usize>();
+        estimated_command_line_len > 1024 * 6
     }
 }
 
index f53c5b3f58131399d78887013b99e26512674926..923e5549927de95fe6a2832ed1f17b4ce96661a3 100644 (file)
@@ -36,8 +36,8 @@
 use std::env;
 use std::ffi::OsString;
 use std::fmt;
-use std::fs::{self, File};
-use std::io::{self, Write, BufWriter};
+use std::fs;
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::{Output, Stdio};
 use std::str;
@@ -71,9 +71,7 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)
     let cmd = |linker: &Path| {
         if let Some(linker) = linker.to_str() {
             if cfg!(windows) && linker.ends_with(".bat") {
-                let mut cmd = Command::new("cmd");
-                cmd.arg("/c").arg(linker);
-                return cmd
+                return Command::bat_script(linker)
             }
         }
         Command::new(linker)
@@ -141,10 +139,10 @@ pub fn remove(sess: &Session, path: &Path) {
 
 /// Perform the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
-pub fn link_binary(sess: &Session,
-                   trans: &CrateTranslation,
-                   outputs: &OutputFilenames,
-                   crate_name: &str) -> Vec<PathBuf> {
+pub(crate) fn link_binary(sess: &Session,
+                          trans: &CrateTranslation,
+                          outputs: &OutputFilenames,
+                          crate_name: &str) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
@@ -201,9 +199,9 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen
     out_filename
 }
 
-pub fn each_linked_rlib(sess: &Session,
-                        info: &CrateInfo,
-                        f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
+pub(crate) fn each_linked_rlib(sess: &Session,
+                               info: &CrateInfo,
+                               f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
     let crates = info.used_crates_static.iter();
     let fmts = sess.dependency_formats.borrow();
     let fmts = fmts.get(&config::CrateTypeExecutable)
@@ -247,7 +245,7 @@ pub fn each_linked_rlib(sess: &Session,
 /// It's unusual for a crate to not participate in LTO. Typically only
 /// compiler-specific and unstable crates have a reason to not participate in
 /// LTO.
-pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
+pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
     // If our target enables builtin function lowering in LLVM then the
     // crates providing these functions don't participate in LTO (e.g.
     // no_builtins or compiler builtins crates).
@@ -758,26 +756,26 @@ fn exec_linker(sess: &Session, cmd: &mut Command, tmpdir: &Path)
     // that contains all the arguments. The theory is that this is then
     // accepted on all linkers and the linker will read all its options out of
     // there instead of looking at the command line.
-    match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
-        Ok(child) => return child.wait_with_output(),
-        Err(ref e) if command_line_too_big(e) => {}
-        Err(e) => return Err(e)
+    if !cmd.very_likely_to_exceed_some_spawn_limit() {
+        match cmd.command().stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
+            Ok(child) => return child.wait_with_output(),
+            Err(ref e) if command_line_too_big(e) => {}
+            Err(e) => return Err(e)
+        }
     }
 
-    let file = tmpdir.join("linker-arguments");
-    let mut cmd2 = Command::new(cmd.get_program());
-    cmd2.arg(format!("@{}", file.display()));
-    for &(ref k, ref v) in cmd.get_env() {
-        cmd2.env(k, v);
-    }
-    let mut f = BufWriter::new(File::create(&file)?);
-    for arg in cmd.get_args() {
-        writeln!(f, "{}", Escape {
+    let mut cmd2 = cmd.clone();
+    let mut args = String::new();
+    for arg in cmd2.take_args() {
+        args.push_str(&Escape {
             arg: arg.to_str().unwrap(),
             is_like_msvc: sess.target.target.options.is_like_msvc,
-        })?;
+        }.to_string());
+        args.push_str("\n");
     }
-    f.into_inner()?;
+    let file = tmpdir.join("linker-arguments");
+    fs::write(&file, args.as_bytes())?;
+    cmd2.arg(format!("@{}", file.display()));
     return cmd2.output();
 
     #[cfg(unix)]
index 60b24a578c6b0052b77fce68a8043530d5ce3a65..b612247ffcd42bfbd867cd4677e5ee9000ece992 100644 (file)
@@ -42,7 +42,7 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
     }
 }
 
-pub enum LtoModuleTranslation {
+pub(crate) enum LtoModuleTranslation {
     Fat {
         module: Option<ModuleTranslation>,
         _serialized_bitcode: Vec<SerializedModule>,
@@ -65,9 +65,9 @@ pub fn name(&self) -> &str {
     /// points to LLVM data structures owned by this `LtoModuleTranslation`.
     /// It's intended that the module returned is immediately code generated and
     /// dropped, and then this LTO module is dropped.
-    pub unsafe fn optimize(&mut self,
-                           cgcx: &CodegenContext,
-                           timeline: &mut Timeline)
+    pub(crate) unsafe fn optimize(&mut self,
+                                  cgcx: &CodegenContext,
+                                  timeline: &mut Timeline)
         -> Result<ModuleTranslation, FatalError>
     {
         match *self {
@@ -100,7 +100,7 @@ pub enum LTOMode {
     JustThisCrate,
 }
 
-pub fn run(cgcx: &CodegenContext,
+pub(crate) fn run(cgcx: &CodegenContext,
            modules: Vec<ModuleTranslation>,
            mode: LTOMode,
            timeline: &mut Timeline)
index fa6fe2e9e93ef78a1436d1fd0ee2399b2233b629..15ff59c7df998098603d60a101b40dd164864f77 100644 (file)
@@ -115,9 +115,8 @@ pub fn provide(providers: &mut Providers) {
 
         if let Some(id) = tcx.sess.derive_registrar_fn.get() {
             let def_id = tcx.hir.local_def_id(id);
-            let idx = def_id.index;
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
+            let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator);
             local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
         }
 
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
deleted file mode 100644 (file)
index 825f306..0000000
+++ /dev/null
@@ -1,449 +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.
-
-//! The Rust Linkage Model and Symbol Names
-//! =======================================
-//!
-//! The semantic model of Rust linkage is, broadly, that "there's no global
-//! namespace" between crates. Our aim is to preserve the illusion of this
-//! model despite the fact that it's not *quite* possible to implement on
-//! modern linkers. We initially didn't use system linkers at all, but have
-//! been convinced of their utility.
-//!
-//! There are a few issues to handle:
-//!
-//!  - Linkers operate on a flat namespace, so we have to flatten names.
-//!    We do this using the C++ namespace-mangling technique. Foo::bar
-//!    symbols and such.
-//!
-//!  - Symbols for distinct items with the same *name* need to get different
-//!    linkage-names. Examples of this are monomorphizations of functions or
-//!    items within anonymous scopes that end up having the same path.
-//!
-//!  - Symbols in different crates but with same names "within" the crate need
-//!    to get different linkage-names.
-//!
-//!  - Symbol names should be deterministic: Two consecutive runs of the
-//!    compiler over the same code base should produce the same symbol names for
-//!    the same items.
-//!
-//!  - Symbol names should not depend on any global properties of the code base,
-//!    so that small modifications to the code base do not result in all symbols
-//!    changing. In previous versions of the compiler, symbol names incorporated
-//!    the SVH (Stable Version Hash) of the crate. This scheme turned out to be
-//!    infeasible when used in conjunction with incremental compilation because
-//!    small code changes would invalidate all symbols generated previously.
-//!
-//!  - Even symbols from different versions of the same crate should be able to
-//!    live next to each other without conflict.
-//!
-//! In order to fulfill the above requirements the following scheme is used by
-//! the compiler:
-//!
-//! The main tool for avoiding naming conflicts is the incorporation of a 64-bit
-//! hash value into every exported symbol name. Anything that makes a difference
-//! to the symbol being named, but does not show up in the regular path needs to
-//! be fed into this hash:
-//!
-//! - Different monomorphizations of the same item have the same path but differ
-//!   in their concrete type parameters, so these parameters are part of the
-//!   data being digested for the symbol hash.
-//!
-//! - Rust allows items to be defined in anonymous scopes, such as in
-//!   `fn foo() { { fn bar() {} } { fn bar() {} } }`. Both `bar` functions have
-//!   the path `foo::bar`, since the anonymous scopes do not contribute to the
-//!   path of an item. The compiler already handles this case via so-called
-//!   disambiguating `DefPaths` which use indices to distinguish items with the
-//!   same name. The DefPaths of the functions above are thus `foo[0]::bar[0]`
-//!   and `foo[0]::bar[1]`. In order to incorporate this disambiguation
-//!   information into the symbol name too, these indices are fed into the
-//!   symbol hash, so that the above two symbols would end up with different
-//!   hash values.
-//!
-//! The two measures described above suffice to avoid intra-crate conflicts. In
-//! order to also avoid inter-crate conflicts two more measures are taken:
-//!
-//! - The name of the crate containing the symbol is prepended to the symbol
-//!   name, i.e. symbols are "crate qualified". For example, a function `foo` in
-//!   module `bar` in crate `baz` would get a symbol name like
-//!   `baz::bar::foo::{hash}` instead of just `bar::foo::{hash}`. This avoids
-//!   simple conflicts between functions from different crates.
-//!
-//! - In order to be able to also use symbols from two versions of the same
-//!   crate (which naturally also have the same name), a stronger measure is
-//!   required: The compiler accepts an arbitrary "disambiguator" value via the
-//!   `-C metadata` commandline argument. This disambiguator is then fed into
-//!   the symbol hash of every exported item. Consequently, the symbols in two
-//!   identical crates but with different disambiguators are not in conflict
-//!   with each other. This facility is mainly intended to be used by build
-//!   tools like Cargo.
-//!
-//! A note on symbol name stability
-//! -------------------------------
-//! Previous versions of the compiler resorted to feeding NodeIds into the
-//! symbol hash in order to disambiguate between items with the same path. The
-//! current version of the name generation algorithm takes great care not to do
-//! that, since NodeIds are notoriously unstable: A small change to the
-//! code base will offset all NodeIds after the change and thus, much as using
-//! the SVH in the hash, invalidate an unbounded number of symbol names. This
-//! makes re-using previously compiled code for incremental compilation
-//! virtually impossible. Thus, symbol hash generation exclusively relies on
-//! DefPaths which are much more robust in the face of changes to the code base.
-
-use monomorphize::Instance;
-use trans_item::{BaseMonoItemExt, InstantiationMode};
-
-use rustc::middle::weak_lang_items;
-use rustc::mir::mono::MonoItem;
-use rustc::hir::def_id::DefId;
-use rustc::hir::map as hir_map;
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::fold::TypeVisitor;
-use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
-use rustc::ty::maps::Providers;
-use rustc::ty::subst::Substs;
-use rustc::hir::map::definitions::DefPathData;
-use rustc::util::common::record_time;
-
-use syntax::attr;
-use syntax_pos::symbol::Symbol;
-
-use std::fmt::Write;
-
-pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        def_symbol_name,
-        symbol_name,
-
-        export_name: |tcx, id| {
-            tcx.get_attrs(id).iter().fold(None, |ia, attr| {
-                if attr.check_name("export_name") {
-                    if let s @ Some(_) = attr.value_str() {
-                        s
-                    } else {
-                        struct_span_err!(tcx.sess, attr.span, E0558,
-                                         "export_name attribute has invalid format")
-                            .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
-                            .emit();
-                        None
-                    }
-                } else {
-                    ia
-                }
-            })
-        },
-
-        contains_extern_indicator: |tcx, id| {
-            attr::contains_name(&tcx.get_attrs(id), "no_mangle") ||
-                tcx.export_name(id).is_some()
-        },
-
-        ..*providers
-    };
-}
-
-fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-
-                             // the DefId of the item this name is for
-                             def_id: DefId,
-
-                             // instance this name will be for
-                             instance: Instance<'tcx>,
-
-                             // type of the item, without any generic
-                             // parameters substituted; this is
-                             // included in the hash as a kind of
-                             // safeguard.
-                             item_type: Ty<'tcx>,
-
-                             // values for generic type parameters,
-                             // if any.
-                             substs: &'tcx Substs<'tcx>)
-                             -> u64 {
-    debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
-
-    let mut hasher = ty::util::TypeIdHasher::<u64>::new(tcx);
-
-    record_time(&tcx.sess.perf_stats.symbol_hash_time, || {
-        // the main symbol name is not necessarily unique; hash in the
-        // compiler's internal def-path, guaranteeing each symbol has a
-        // truly unique path
-        hasher.hash(tcx.def_path_hash(def_id));
-
-        // Include the main item-type. Note that, in this case, the
-        // assertions about `needs_subst` may not hold, but this item-type
-        // ought to be the same for every reference anyway.
-        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)
-        assert!(!substs.has_erasable_regions());
-        assert!(!substs.needs_subst());
-        substs.visit_with(&mut hasher);
-
-        let mut avoid_cross_crate_conflicts = false;
-
-        // If this is an instance of a generic function, we also hash in
-        // the ID of the instantiating crate. This avoids symbol conflicts
-        // in case the same instances is emitted in two crates of the same
-        // project.
-        if substs.types().next().is_some() {
-            avoid_cross_crate_conflicts = true;
-        }
-
-        // If we're dealing with an instance of a function that's inlined from
-        // another crate but we're marking it as globally shared to our
-        // compliation (aka we're not making an internal copy in each of our
-        // codegen units) then this symbol may become an exported (but hidden
-        // visibility) symbol. This means that multiple crates may do the same
-        // and we want to be sure to avoid any symbol conflicts here.
-        match MonoItem::Fn(instance).instantiation_mode(tcx) {
-            InstantiationMode::GloballyShared { may_conflict: true } => {
-                avoid_cross_crate_conflicts = true;
-            }
-            _ => {}
-        }
-
-        if avoid_cross_crate_conflicts {
-            hasher.hash(tcx.crate_name.as_str());
-            hasher.hash(tcx.sess.local_crate_disambiguator());
-        }
-    });
-
-    // 64 bits should be enough to avoid collisions.
-    hasher.finish()
-}
-
-fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-                             -> ty::SymbolName
-{
-    let mut buffer = SymbolPathBuffer::new();
-    item_path::with_forced_absolute_paths(|| {
-        tcx.push_item_path(&mut buffer, def_id);
-    });
-    buffer.into_interned()
-}
-
-fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
-                         -> ty::SymbolName
-{
-    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
-}
-
-fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
-    -> String
-{
-    let def_id = instance.def_id();
-    let substs = instance.substs;
-
-    debug!("symbol_name(def_id={:?}, substs={:?})",
-           def_id, substs);
-
-    let node_id = tcx.hir.as_local_node_id(def_id);
-
-    if let Some(id) = node_id {
-        if tcx.sess.plugin_registrar_fn.get() == Some(id) {
-            let idx = def_id.index;
-            let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_plugin_registrar_symbol(disambiguator, idx);
-        }
-        if tcx.sess.derive_registrar_fn.get() == Some(id) {
-            let idx = def_id.index;
-            let disambiguator = tcx.sess.local_crate_disambiguator();
-            return tcx.sess.generate_derive_registrar_symbol(disambiguator, idx);
-        }
-    }
-
-    // FIXME(eddyb) Precompute a custom symbol name based on attributes.
-    let attrs = tcx.get_attrs(def_id);
-    let is_foreign = if let Some(id) = node_id {
-        match tcx.hir.get(id) {
-            hir_map::NodeForeignItem(_) => true,
-            _ => false
-        }
-    } else {
-        tcx.is_foreign_item(def_id)
-    };
-
-    if let Some(name) = weak_lang_items::link_name(&attrs) {
-        return name.to_string();
-    }
-
-    if is_foreign {
-        if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") {
-            return name.to_string();
-        }
-        // Don't mangle foreign items.
-        return tcx.item_name(def_id).to_string();
-    }
-
-    if let Some(name) = tcx.export_name(def_id) {
-        // Use provided name
-        return name.to_string();
-    }
-
-    if attr::contains_name(&attrs, "no_mangle") {
-        // Don't mangle
-        return tcx.item_name(def_id).to_string();
-    }
-
-    // We want to compute the "type" of this item. Unfortunately, some
-    // kinds of items (e.g., closures) don't have an entry in the
-    // item-type array. So walk back up the find the closest parent
-    // that DOES have an entry.
-    let mut ty_def_id = def_id;
-    let instance_ty;
-    loop {
-        let key = tcx.def_key(ty_def_id);
-        match key.disambiguated_data.data {
-            DefPathData::TypeNs(_) |
-            DefPathData::ValueNs(_) => {
-                instance_ty = tcx.type_of(ty_def_id);
-                break;
-            }
-            _ => {
-                // if we're making a symbol for something, there ought
-                // to be a value or type-def or something in there
-                // *somewhere*
-                ty_def_id.index = key.parent.unwrap_or_else(|| {
-                    bug!("finding type for {:?}, encountered def-id {:?} with no \
-                          parent", def_id, ty_def_id);
-                });
-            }
-        }
-    }
-
-    // Erase regions because they may not be deterministic when hashed
-    // and should not matter anyhow.
-    let instance_ty = tcx.erase_regions(&instance_ty);
-
-    let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs);
-
-    SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash)
-}
-
-// Follow C++ namespace-mangling style, see
-// http://en.wikipedia.org/wiki/Name_mangling for more info.
-//
-// It turns out that on macOS you can actually have arbitrary symbols in
-// function names (at least when given to LLVM), but this is not possible
-// when using unix's linker. Perhaps one day when we just use a linker from LLVM
-// we won't need to do this name mangling. The problem with name mangling is
-// that it seriously limits the available characters. For example we can't
-// have things like &T in symbol names when one would theoretically
-// want them for things like impls of traits on that type.
-//
-// To be able to work on all platforms and get *some* reasonable output, we
-// use C++ name-mangling.
-struct SymbolPathBuffer {
-    result: String,
-    temp_buf: String
-}
-
-impl SymbolPathBuffer {
-    fn new() -> Self {
-        let mut result = SymbolPathBuffer {
-            result: String::with_capacity(64),
-            temp_buf: String::with_capacity(16)
-        };
-        result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
-        result
-    }
-
-    fn from_interned(symbol: ty::SymbolName) -> Self {
-        let mut result = SymbolPathBuffer {
-            result: String::with_capacity(64),
-            temp_buf: String::with_capacity(16)
-        };
-        result.result.push_str(&symbol.name);
-        result
-    }
-
-    fn into_interned(self) -> ty::SymbolName {
-        ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
-    }
-
-    fn finish(mut self, hash: u64) -> String {
-        // E = end name-sequence
-        let _ = write!(self.result, "17h{:016x}E", hash);
-        self.result
-    }
-}
-
-impl ItemPathBuffer for SymbolPathBuffer {
-    fn root_mode(&self) -> &RootMode {
-        const ABSOLUTE: &'static RootMode = &RootMode::Absolute;
-        ABSOLUTE
-    }
-
-    fn push(&mut self, text: &str) {
-        self.temp_buf.clear();
-        let need_underscore = sanitize(&mut self.temp_buf, text);
-        let _ = write!(self.result, "{}", self.temp_buf.len() + (need_underscore as usize));
-        if need_underscore {
-            self.result.push('_');
-        }
-        self.result.push_str(&self.temp_buf);
-    }
-}
-
-// Name sanitation. LLVM will happily accept identifiers with weird names, but
-// gas doesn't!
-// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
-//
-// returns true if an underscore must be added at the start
-pub fn sanitize(result: &mut String, s: &str) -> bool {
-    for c in s.chars() {
-        match c {
-            // Escape these with $ sequences
-            '@' => result.push_str("$SP$"),
-            '*' => result.push_str("$BP$"),
-            '&' => result.push_str("$RF$"),
-            '<' => result.push_str("$LT$"),
-            '>' => result.push_str("$GT$"),
-            '(' => result.push_str("$LP$"),
-            ')' => result.push_str("$RP$"),
-            ',' => result.push_str("$C$"),
-
-            // '.' doesn't occur in types and functions, so reuse it
-            // for ':' and '-'
-            '-' | ':' => result.push('.'),
-
-            // These are legal symbols
-            'a' ... 'z'
-            | 'A' ... 'Z'
-            | '0' ... '9'
-            | '_' | '.' | '$' => result.push(c),
-
-            _ => {
-                result.push('$');
-                for c in c.escape_unicode().skip(1) {
-                    match c {
-                        '{' => {},
-                        '}' => result.push('$'),
-                        c => result.push(c),
-                    }
-                }
-            }
-        }
-    }
-
-    // Underscore-qualify anything that didn't start as an ident.
-    !result.is_empty() &&
-        result.as_bytes()[0] != '_' as u8 &&
-        ! (result.as_bytes()[0] as char).is_xid_start()
-}
index db0b045ef1e73aebdb1d62ab9ee46c7e4513ffda..a013af7a4600ef342218823abbbea1d890e26de1 100644 (file)
@@ -363,7 +363,7 @@ pub fn create_diag_handler(&self) -> Handler {
         Handler::with_emitter(true, false, Box::new(self.diag_emitter.clone()))
     }
 
-    pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
+    pub(crate) fn config(&self, kind: ModuleKind) -> &ModuleConfig {
         match kind {
             ModuleKind::Regular => &self.regular_module_config,
             ModuleKind::Metadata => &self.metadata_module_config,
@@ -371,7 +371,7 @@ pub fn config(&self, kind: ModuleKind) -> &ModuleConfig {
         }
     }
 
-    pub fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
+    pub(crate) fn save_temp_bitcode(&self, trans: &ModuleTranslation, name: &str) {
         if !self.save_temps {
             return
         }
@@ -822,7 +822,7 @@ fn binaryen_assemble(cgcx: &CodegenContext,
     }
 }
 
-pub struct CompiledModules {
+pub(crate) struct CompiledModules {
     pub modules: Vec<CompiledModule>,
     pub metadata_module: CompiledModule,
     pub allocator_module: Option<CompiledModule>,
@@ -1162,7 +1162,7 @@ fn produce_final_output_artifacts(sess: &Session,
     // These are used in linking steps and will be cleaned up afterward.
 }
 
-pub fn dump_incremental_data(trans: &CrateTranslation) {
+pub(crate) fn dump_incremental_data(trans: &CrateTranslation) {
     println!("[incremental] Re-using {} out of {} modules",
               trans.modules.iter().filter(|m| m.pre_existing).count(),
               trans.modules.len());
@@ -2144,7 +2144,7 @@ pub struct OngoingCrateTranslation {
 }
 
 impl OngoingCrateTranslation {
-    pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
+    pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
         self.shared_emitter_main.check(sess, true);
         let compiled_modules = match self.future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
@@ -2212,9 +2212,9 @@ pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
         trans
     }
 
-    pub fn submit_pre_translated_module_to_llvm(&self,
-                                                tcx: TyCtxt,
-                                                mtrans: ModuleTranslation) {
+    pub(crate) fn submit_pre_translated_module_to_llvm(&self,
+                                                       tcx: TyCtxt,
+                                                       mtrans: ModuleTranslation) {
         self.wait_for_signal_to_translate_item();
         self.check_for_errors(tcx.sess);
 
@@ -2247,9 +2247,9 @@ pub fn wait_for_signal_to_translate_item(&self) {
     }
 }
 
-pub fn submit_translated_module_to_llvm(tcx: TyCtxt,
-                                        mtrans: ModuleTranslation,
-                                        cost: u64) {
+pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt,
+                                               mtrans: ModuleTranslation,
+                                               cost: u64) {
     let llvm_work_item = WorkItem::Optimize(mtrans);
     drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone {
         llvm_work_item,
index 633ed9b32cd1e59880f0708182e7027495810ec2..734ad8f3929ed0d9ac2e130cf940002a4ca319d9 100644 (file)
@@ -29,7 +29,6 @@
 use super::ModuleKind;
 
 use abi;
-use assert_module_sources;
 use back::link;
 use back::symbol_export;
 use back::write::{self, OngoingCrateTranslation, create_target_machine};
@@ -66,7 +65,7 @@
 use mir;
 use monomorphize::Instance;
 use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
-use symbol_names_test;
+use rustc_trans_utils::symbol_names_test;
 use time_graph;
 use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
 use type_::Type;
@@ -904,7 +903,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             total_trans_time);
 
     if tcx.sess.opts.incremental.is_some() {
-        assert_module_sources::assert_module_sources(tcx);
+        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
     }
 
     symbol_names_test::report_symbol_names(tcx);
@@ -947,54 +946,6 @@ fn assert_and_save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
          || rustc_incremental::save_dep_graph(tcx));
 }
 
-#[inline(never)] // give this a place in the profiler
-fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_items: I)
-    where I: Iterator<Item=&'a MonoItem<'tcx>>
-{
-    let mut symbols: Vec<_> = trans_items.map(|trans_item| {
-        (trans_item, trans_item.symbol_name(tcx))
-    }).collect();
-
-    (&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
-        sym1.cmp(sym2)
-    });
-
-    for pair in (&symbols[..]).windows(2) {
-        let sym1 = &pair[0].1;
-        let sym2 = &pair[1].1;
-
-        if *sym1 == *sym2 {
-            let trans_item1 = pair[0].0;
-            let trans_item2 = pair[1].0;
-
-            let span1 = trans_item1.local_span(tcx);
-            let span2 = trans_item2.local_span(tcx);
-
-            // Deterministically select one of the spans for error reporting
-            let span = match (span1, span2) {
-                (Some(span1), Some(span2)) => {
-                    Some(if span1.lo().0 > span2.lo().0 {
-                        span1
-                    } else {
-                        span2
-                    })
-                }
-                (Some(span), None) |
-                (None, Some(span)) => Some(span),
-                _ => None
-            };
-
-            let error_message = format!("symbol `{}` is already defined", sym1);
-
-            if let Some(span) = span {
-                tcx.sess.span_fatal(span, &error_message)
-            } else {
-                tcx.sess.fatal(&error_message)
-            }
-        }
-    }
-}
-
 fn collect_and_partition_translation_items<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cnum: CrateNum,
@@ -1034,7 +985,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
             collector::collect_crate_mono_items(tcx, collection_mode)
     });
 
-    assert_symbols_are_distinct(tcx, items.iter());
+    ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
 
     let strategy = if tcx.sess.opts.incremental.is_some() {
         PartitioningStrategy::PerModule
index 8f5d836f56f3ffffca87481525ce758d20669e2a..57cc33d09bbea94e1f36f7fa1c82fe58ae831ce5 100644 (file)
@@ -47,27 +47,9 @@ fn main() {
 ```
 "##,
 
-E0558: r##"
-The `export_name` attribute was malformed.
-
-Erroneous code example:
-
-```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
-#[export_name] // error: export_name attribute has invalid format
-pub fn something() {}
-
-fn main() {}
-```
-
-The `export_name` attribute expects a string in order to determine the name of
-the exported symbol. Example:
-
-```
-#[export_name = "some_function"] // ok!
-pub fn something() {}
+}
 
-fn main() {}
-```
-"##,
 
+register_diagnostics! {
+    E0558
 }
index 974c268749b859a5620059aea0f6e6846963aaa7..b67997081aa67c04e79688cd2760710e109f53b4 100644 (file)
@@ -33,6 +33,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
+#![feature(optin_builtin_traits)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 extern crate cc; // Used to locate MSVC
 extern crate tempdir;
 
-pub use base::trans_crate;
 use back::bytecode::RLIB_BYTECODE_EXTENSION;
 
-pub use metadata::LlvmMetadataLoader;
-pub use llvm_util::{init, target_features, print_version, print_passes, print};
+pub use llvm_util::{target_features, print_version, print_passes};
 
 use std::any::Any;
 use std::path::PathBuf;
 use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
-use rustc::session::Session;
-use rustc::session::config::{OutputFilenames, OutputType};
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
-
 use rustc_mir::monomorphize;
+use rustc_trans_utils::trans_crate::TransCrate;
 
 mod diagnostics;
 
-pub mod back {
+mod back {
+    pub use rustc_trans_utils::symbol_names;
     mod archive;
     pub mod bytecode;
     mod command;
-    pub(crate) mod linker;
+    pub mod linker;
     pub mod link;
     mod lto;
-    pub(crate) mod symbol_export;
-    pub(crate) mod symbol_names;
+    pub mod symbol_export;
     pub mod write;
     mod rpath;
 }
@@ -106,7 +105,6 @@ pub mod back {
 mod abi;
 mod allocator;
 mod asm;
-mod assert_module_sources;
 mod attributes;
 mod base;
 mod builder;
@@ -139,7 +137,6 @@ pub mod back {
 mod metadata;
 mod meth;
 mod mir;
-mod symbol_names_test;
 mod time_graph;
 mod trans_item;
 mod type_;
@@ -148,57 +145,118 @@ pub mod back {
 
 pub struct LlvmTransCrate(());
 
+impl !Send for LlvmTransCrate {} // Llvm is on a per-thread basis
+impl !Sync for LlvmTransCrate {}
+
 impl LlvmTransCrate {
-    pub fn new() -> Self {
-        LlvmTransCrate(())
+    pub fn new(sess: &Session) -> Box<TransCrate> {
+        llvm_util::init(sess); // Make sure llvm is inited
+        box LlvmTransCrate(())
     }
 }
 
-impl rustc_trans_utils::trans_crate::TransCrate for LlvmTransCrate {
-    type MetadataLoader = metadata::LlvmMetadataLoader;
-    type OngoingCrateTranslation = back::write::OngoingCrateTranslation;
-    type TranslatedCrate = CrateTranslation;
+impl TransCrate for LlvmTransCrate {
+    fn print(&self, req: PrintRequest, sess: &Session) {
+        match req {
+            PrintRequest::RelocationModels => {
+                println!("Available relocation models:");
+                for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            PrintRequest::CodeModels => {
+                println!("Available code models:");
+                for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            PrintRequest::TlsModels => {
+                println!("Available TLS models:");
+                for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
+                    println!("    {}", name);
+                }
+                println!("");
+            }
+            req => llvm_util::print(req, sess),
+        }
+    }
 
-    fn metadata_loader() -> Box<MetadataLoader> {
+    fn target_features(&self, sess: &Session) -> Vec<Symbol> {
+        target_features(sess)
+    }
+
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box metadata::LlvmMetadataLoader
     }
 
-    fn provide(providers: &mut ty::maps::Providers) {
+    fn provide(&self, providers: &mut ty::maps::Providers) {
         back::symbol_names::provide(providers);
         back::symbol_export::provide(providers);
         base::provide(providers);
         attributes::provide(providers);
     }
 
-    fn provide_extern(providers: &mut ty::maps::Providers) {
+    fn provide_extern(&self, providers: &mut ty::maps::Providers) {
         back::symbol_export::provide_extern(providers);
     }
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
-        base::trans_crate(tcx, rx)
+    ) -> Box<Any> {
+        box base::trans_crate(tcx, rx)
     }
 
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
         sess: &Session,
-        dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate {
-        trans.join(sess, dep_graph)
-    }
+        dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete>{
+        use rustc::util::common::time;
+        let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
+            .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
+            .join(sess, dep_graph);
+        if sess.opts.debugging_opts.incremental_info {
+            back::write::dump_incremental_data(&trans);
+        }
 
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
-        back::link::link_binary(sess, trans, outputs, &trans.crate_name.as_str());
-    }
+        time(sess.time_passes(),
+             "serialize work products",
+             move || rustc_incremental::save_work_products(sess, &dep_graph));
 
-    fn dump_incremental_data(trans: &Self::TranslatedCrate) {
-        back::write::dump_incremental_data(trans);
+        sess.compile_status()?;
+
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
+                                                   i == OutputType::Metadata) {
+            return Ok(());
+        }
+
+        // Run the linker on any artifacts that resulted from the LLVM run.
+        // This should produce either a finished executable or library.
+        time(sess.time_passes(), "linking", || {
+            back::link::link_binary(sess, &trans, outputs, &trans.crate_name.as_str());
+        });
+
+        // Now that we won't touch anything in the incremental compilation directory
+        // any more, we can finalize it (which involves renaming it)
+        rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
+
+        Ok(())
     }
 }
 
-pub struct ModuleTranslation {
+/// This is the entrypoint for a hot plugged rustc_trans
+#[no_mangle]
+pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
+    LlvmTransCrate::new(sess)
+}
+
+struct ModuleTranslation {
     /// The name of the module. When the crate may be saved between
     /// compilations, incremental compilation requires that name be
     /// unique amongst **all** crates.  Therefore, it should contain
@@ -206,26 +264,26 @@ pub struct ModuleTranslation {
     /// as the crate name and disambiguator.
     name: String,
     llmod_id: String,
-    pub source: ModuleSource,
-    pub kind: ModuleKind,
+    source: ModuleSource,
+    kind: ModuleKind,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub enum ModuleKind {
+enum ModuleKind {
     Regular,
     Metadata,
     Allocator,
 }
 
 impl ModuleTranslation {
-    pub fn llvm(&self) -> Option<&ModuleLlvm> {
+    fn llvm(&self) -> Option<&ModuleLlvm> {
         match self.source {
             ModuleSource::Translated(ref llvm) => Some(llvm),
             ModuleSource::Preexisting(_) => None,
         }
     }
 
-    pub fn into_compiled_module(self,
+    fn into_compiled_module(self,
                                 emit_obj: bool,
                                 emit_bc: bool,
                                 emit_bc_compressed: bool,
@@ -264,17 +322,17 @@ pub fn into_compiled_module(self,
 }
 
 #[derive(Debug)]
-pub struct CompiledModule {
-    pub name: String,
-    pub llmod_id: String,
-    pub kind: ModuleKind,
-    pub pre_existing: bool,
-    pub object: Option<PathBuf>,
-    pub bytecode: Option<PathBuf>,
-    pub bytecode_compressed: Option<PathBuf>,
+struct CompiledModule {
+    name: String,
+    llmod_id: String,
+    kind: ModuleKind,
+    pre_existing: bool,
+    object: Option<PathBuf>,
+    bytecode: Option<PathBuf>,
+    bytecode_compressed: Option<PathBuf>,
 }
 
-pub enum ModuleSource {
+enum ModuleSource {
     /// Copy the `.o` files or whatever from the incr. comp. directory.
     Preexisting(WorkProduct),
 
@@ -283,9 +341,9 @@ pub enum ModuleSource {
 }
 
 #[derive(Debug)]
-pub struct ModuleLlvm {
+struct ModuleLlvm {
     llcx: llvm::ContextRef,
-    pub llmod: llvm::ModuleRef,
+    llmod: llvm::ModuleRef,
     tm: llvm::TargetMachineRef,
 }
 
@@ -302,20 +360,20 @@ fn drop(&mut self) {
     }
 }
 
-pub struct CrateTranslation {
-    pub crate_name: Symbol,
-    pub modules: Vec<CompiledModule>,
+struct CrateTranslation {
+    crate_name: Symbol,
+    modules: Vec<CompiledModule>,
     allocator_module: Option<CompiledModule>,
     metadata_module: CompiledModule,
-    pub link: rustc::middle::cstore::LinkMeta,
-    pub metadata: rustc::middle::cstore::EncodedMetadata,
+    link: rustc::middle::cstore::LinkMeta,
+    metadata: rustc::middle::cstore::EncodedMetadata,
     windows_subsystem: Option<String>,
     linker_info: back::linker::LinkerInfo,
     crate_info: CrateInfo,
 }
 
 // Misc info we load from metadata to persist beyond the tcx
-pub struct CrateInfo {
+struct CrateInfo {
     panic_runtime: Option<CrateNum>,
     compiler_builtins: Option<CrateNum>,
     profiler_runtime: Option<CrateNum>,
index 214fdbded4e90bf74a17a290f3ae676f896abdbb..15988008de2fc6981a4e3c44d9a7fb69cfcc7fd7 100644 (file)
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
 
-pub fn init(sess: &Session) {
+static POISONED: AtomicBool = AtomicBool::new(false);
+static INIT: Once = Once::new();
+
+pub(crate) fn init(sess: &Session) {
     unsafe {
         // Before we touch LLVM, make sure that multithreading is enabled.
-        static POISONED: AtomicBool = AtomicBool::new(false);
-        static INIT: Once = Once::new();
         INIT.call_once(|| {
             if llvm::LLVMStartMultithreaded() != 1 {
                 // use an extra bool to make sure that all future usage of LLVM
@@ -40,6 +41,13 @@ pub fn init(sess: &Session) {
     }
 }
 
+fn require_inited() {
+    INIT.call_once(|| bug!("llvm is not initialized"));
+    if POISONED.load(Ordering::SeqCst) {
+        bug!("couldn't enable multi-threaded LLVM");
+    }
+}
+
 unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_c_strs = Vec::new();
     let mut llvm_args = Vec::new();
@@ -125,6 +133,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
 }
 
 pub fn print_version() {
+    // Can be called without initializing LLVM
     unsafe {
         println!("LLVM version: {}.{}",
                  llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
@@ -132,10 +141,12 @@ pub fn print_version() {
 }
 
 pub fn print_passes() {
+    // Can be called without initializing LLVM
     unsafe { llvm::LLVMRustPrintPasses(); }
 }
 
-pub fn print(req: PrintRequest, sess: &Session) {
+pub(crate) fn print(req: PrintRequest, sess: &Session) {
+    require_inited();
     let tm = create_target_machine(sess);
     unsafe {
         match req {
index ddd78f268fadb1e911b2027bd4e293fc6689f206..3064e2f7c7afdab4c9b20b438f079d133f24570b 100644 (file)
@@ -402,6 +402,9 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             for i in 0..tupled_arg_tys.len() {
                 let arg = &fx.fn_ty.args[idx];
                 idx += 1;
+                if arg.pad.is_some() {
+                    llarg_idx += 1;
+                }
                 arg.store_fn_arg(bx, &mut llarg_idx, place.project_field(bx, i));
             }
 
diff --git a/src/librustc_trans/symbol_names_test.rs b/src/librustc_trans/symbol_names_test.rs
deleted file mode 100644 (file)
index 15c142c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Walks the crate looking for items/impl-items/trait-items that have
-//! either a `rustc_symbol_name` or `rustc_item_path` attribute and
-//! generates an error giving, respectively, the symbol name or
-//! item-path. This is used for unit testing the code that generates
-//! paths etc in all kinds of annoying scenarios.
-
-use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
-use rustc::ty::TyCtxt;
-use syntax::ast;
-
-use monomorphize::Instance;
-
-const SYMBOL_NAME: &'static str = "rustc_symbol_name";
-const ITEM_PATH: &'static str = "rustc_item_path";
-
-pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    // if the `rustc_attrs` feature is not enabled, then the
-    // attributes we are interested in cannot be present anyway, so
-    // skip the walk.
-    if !tcx.sess.features.borrow().rustc_attrs {
-        return;
-    }
-
-    tcx.dep_graph.with_ignore(|| {
-        let mut visitor = SymbolNamesTest { tcx: tcx };
-        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
-        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
-    })
-}
-
-struct SymbolNamesTest<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-}
-
-impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
-    fn process_attrs(&mut self,
-                     node_id: ast::NodeId) {
-        let tcx = self.tcx;
-        let def_id = tcx.hir.local_def_id(node_id);
-        for attr in tcx.get_attrs(def_id).iter() {
-            if attr.check_name(SYMBOL_NAME) {
-                // for now, can only use on monomorphic names
-                let instance = Instance::mono(tcx, def_id);
-                let name = self.tcx.symbol_name(instance);
-                tcx.sess.span_err(attr.span, &format!("symbol-name({})", name));
-            } else if attr.check_name(ITEM_PATH) {
-                let path = tcx.item_path_str(def_id);
-                tcx.sess.span_err(attr.span, &format!("item-path({})", path));
-            }
-
-            // (*) The formatting of `tag({})` is chosen so that tests can elect
-            // to test the entirety of the string, if they choose, or else just
-            // some subset.
-        }
-    }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::None
-    }
-
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.process_attrs(item.id);
-        intravisit::walk_item(self, item);
-    }
-
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
-        self.process_attrs(ti.id);
-        intravisit::walk_trait_item(self, ti)
-    }
-
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
-        self.process_attrs(ii.id);
-        intravisit::walk_impl_item(self, ii)
-    }
-}
index cc270ab5f2d25264f9d50ca79a794105bd493fe4..5eb6679fe252c0480d176e2419f90595d2840dc7 100644 (file)
 use type_of::LayoutLlvmExt;
 use rustc::hir;
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::ty::{TyCtxt, TypeFoldable};
+use rustc::ty::TypeFoldable;
 use rustc::ty::layout::LayoutOf;
 use syntax::ast;
 use syntax::attr;
-use syntax_pos::Span;
 use std::fmt;
 
 pub use rustc::mir::mono::MonoItem;
@@ -107,18 +106,6 @@ fn predefine(&self,
                cx.codegen_unit.name());
     }
 
-    fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
-        match *self.as_mono_item() {
-            MonoItem::Fn(Instance { def, .. }) => {
-                tcx.hir.as_local_node_id(def.def_id())
-            }
-            MonoItem::Static(node_id) |
-            MonoItem::GlobalAsm(node_id) => {
-                Some(node_id)
-            }
-        }.map(|node_id| tcx.hir.span(node_id))
-    }
-
     fn to_raw_string(&self) -> String {
         match *self.as_mono_item() {
             MonoItem::Fn(instance) => {
index 7b9537ee23e23c8f729a6f622e82390f5126c7dc..7a01b6d261a34cca1cb90c6c6cad730037aabbb4 100644 (file)
@@ -19,3 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_mir = { path = "../librustc_mir" }
+rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_trans_utils/diagnostics.rs b/src/librustc_trans_utils/diagnostics.rs
new file mode 100644 (file)
index 0000000..13fa15f
--- /dev/null
@@ -0,0 +1,38 @@
+// 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.
+
+#![allow(non_snake_case)]
+
+register_long_diagnostics! {
+
+E0558: r##"
+The `export_name` attribute was malformed.
+
+Erroneous code example:
+
+```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
+#[export_name] // error: export_name attribute has invalid format
+pub fn something() {}
+
+fn main() {}
+```
+
+The `export_name` attribute expects a string in order to determine the name of
+the exported symbol. Example:
+
+```
+#[export_name = "some_function"] // ok!
+pub fn something() {}
+
+fn main() {}
+```
+"##,
+
+}
index 77afc2899c329517e5958e4568871f85a8fe2995..9b7ab204492aeec6e44fa51bd0b5867c47990f96 100644 (file)
 #[macro_use]
 extern crate rustc;
 extern crate rustc_back;
+extern crate rustc_mir;
+extern crate rustc_incremental;
+#[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
+pub extern crate rustc as __rustc;
+
 use rustc::ty::{TyCtxt, Instance};
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::map as hir_map;
 use rustc::util::nodemap::NodeSet;
 
+pub mod diagnostics;
 pub mod link;
 pub mod trans_crate;
+pub mod symbol_names;
+pub mod symbol_names_test;
 
 /// check for the #[rustc_error] annotation, which forces an
 /// error in trans. This is used to write compile-fail tests
@@ -110,3 +118,6 @@ pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
         }
     }).collect()
 }
+
+#[cfg(not(stage0))] // remove after the next snapshot
+__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }
diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs
new file mode 100644 (file)
index 0000000..fb299bf
--- /dev/null
@@ -0,0 +1,445 @@
+// 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.
+
+//! The Rust Linkage Model and Symbol Names
+//! =======================================
+//!
+//! The semantic model of Rust linkage is, broadly, that "there's no global
+//! namespace" between crates. Our aim is to preserve the illusion of this
+//! model despite the fact that it's not *quite* possible to implement on
+//! modern linkers. We initially didn't use system linkers at all, but have
+//! been convinced of their utility.
+//!
+//! There are a few issues to handle:
+//!
+//!  - Linkers operate on a flat namespace, so we have to flatten names.
+//!    We do this using the C++ namespace-mangling technique. Foo::bar
+//!    symbols and such.
+//!
+//!  - Symbols for distinct items with the same *name* need to get different
+//!    linkage-names. Examples of this are monomorphizations of functions or
+//!    items within anonymous scopes that end up having the same path.
+//!
+//!  - Symbols in different crates but with same names "within" the crate need
+//!    to get different linkage-names.
+//!
+//!  - Symbol names should be deterministic: Two consecutive runs of the
+//!    compiler over the same code base should produce the same symbol names for
+//!    the same items.
+//!
+//!  - Symbol names should not depend on any global properties of the code base,
+//!    so that small modifications to the code base do not result in all symbols
+//!    changing. In previous versions of the compiler, symbol names incorporated
+//!    the SVH (Stable Version Hash) of the crate. This scheme turned out to be
+//!    infeasible when used in conjunction with incremental compilation because
+//!    small code changes would invalidate all symbols generated previously.
+//!
+//!  - Even symbols from different versions of the same crate should be able to
+//!    live next to each other without conflict.
+//!
+//! In order to fulfill the above requirements the following scheme is used by
+//! the compiler:
+//!
+//! The main tool for avoiding naming conflicts is the incorporation of a 64-bit
+//! hash value into every exported symbol name. Anything that makes a difference
+//! to the symbol being named, but does not show up in the regular path needs to
+//! be fed into this hash:
+//!
+//! - Different monomorphizations of the same item have the same path but differ
+//!   in their concrete type parameters, so these parameters are part of the
+//!   data being digested for the symbol hash.
+//!
+//! - Rust allows items to be defined in anonymous scopes, such as in
+//!   `fn foo() { { fn bar() {} } { fn bar() {} } }`. Both `bar` functions have
+//!   the path `foo::bar`, since the anonymous scopes do not contribute to the
+//!   path of an item. The compiler already handles this case via so-called
+//!   disambiguating `DefPaths` which use indices to distinguish items with the
+//!   same name. The DefPaths of the functions above are thus `foo[0]::bar[0]`
+//!   and `foo[0]::bar[1]`. In order to incorporate this disambiguation
+//!   information into the symbol name too, these indices are fed into the
+//!   symbol hash, so that the above two symbols would end up with different
+//!   hash values.
+//!
+//! The two measures described above suffice to avoid intra-crate conflicts. In
+//! order to also avoid inter-crate conflicts two more measures are taken:
+//!
+//! - The name of the crate containing the symbol is prepended to the symbol
+//!   name, i.e. symbols are "crate qualified". For example, a function `foo` in
+//!   module `bar` in crate `baz` would get a symbol name like
+//!   `baz::bar::foo::{hash}` instead of just `bar::foo::{hash}`. This avoids
+//!   simple conflicts between functions from different crates.
+//!
+//! - In order to be able to also use symbols from two versions of the same
+//!   crate (which naturally also have the same name), a stronger measure is
+//!   required: The compiler accepts an arbitrary "disambiguator" value via the
+//!   `-C metadata` commandline argument. This disambiguator is then fed into
+//!   the symbol hash of every exported item. Consequently, the symbols in two
+//!   identical crates but with different disambiguators are not in conflict
+//!   with each other. This facility is mainly intended to be used by build
+//!   tools like Cargo.
+//!
+//! A note on symbol name stability
+//! -------------------------------
+//! Previous versions of the compiler resorted to feeding NodeIds into the
+//! symbol hash in order to disambiguate between items with the same path. The
+//! current version of the name generation algorithm takes great care not to do
+//! that, since NodeIds are notoriously unstable: A small change to the
+//! code base will offset all NodeIds after the change and thus, much as using
+//! the SVH in the hash, invalidate an unbounded number of symbol names. This
+//! makes re-using previously compiled code for incremental compilation
+//! virtually impossible. Thus, symbol hash generation exclusively relies on
+//! DefPaths which are much more robust in the face of changes to the code base.
+
+use rustc::middle::weak_lang_items;
+use rustc_mir::monomorphize::Instance;
+use rustc_mir::monomorphize::item::{MonoItem, MonoItemExt, InstantiationMode};
+use rustc::hir::def_id::DefId;
+use rustc::hir::map as hir_map;
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::fold::TypeVisitor;
+use rustc::ty::item_path::{self, ItemPathBuffer, RootMode};
+use rustc::ty::maps::Providers;
+use rustc::ty::subst::Substs;
+use rustc::hir::map::definitions::DefPathData;
+use rustc::util::common::record_time;
+
+use syntax::attr;
+use syntax_pos::symbol::Symbol;
+
+use std::fmt::Write;
+
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        def_symbol_name,
+        symbol_name,
+
+        export_name: |tcx, id| {
+            tcx.get_attrs(id).iter().fold(None, |ia, attr| {
+                if attr.check_name("export_name") {
+                    if let s @ Some(_) = attr.value_str() {
+                        s
+                    } else {
+                        struct_span_err!(tcx.sess, attr.span, E0558,
+                                         "export_name attribute has invalid format")
+                            .span_label(attr.span, "did you mean #[export_name=\"*\"]?")
+                            .emit();
+                        None
+                    }
+                } else {
+                    ia
+                }
+            })
+        },
+
+        contains_extern_indicator: |tcx, id| {
+            attr::contains_name(&tcx.get_attrs(id), "no_mangle") ||
+                tcx.export_name(id).is_some()
+        },
+
+        ..*providers
+    };
+}
+
+fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+
+                             // the DefId of the item this name is for
+                             def_id: DefId,
+
+                             // instance this name will be for
+                             instance: Instance<'tcx>,
+
+                             // type of the item, without any generic
+                             // parameters substituted; this is
+                             // included in the hash as a kind of
+                             // safeguard.
+                             item_type: Ty<'tcx>,
+
+                             // values for generic type parameters,
+                             // if any.
+                             substs: &'tcx Substs<'tcx>)
+                             -> u64 {
+    debug!("get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs);
+
+    let mut hasher = ty::util::TypeIdHasher::<u64>::new(tcx);
+
+    record_time(&tcx.sess.perf_stats.symbol_hash_time, || {
+        // the main symbol name is not necessarily unique; hash in the
+        // compiler's internal def-path, guaranteeing each symbol has a
+        // truly unique path
+        hasher.hash(tcx.def_path_hash(def_id));
+
+        // Include the main item-type. Note that, in this case, the
+        // assertions about `needs_subst` may not hold, but this item-type
+        // ought to be the same for every reference anyway.
+        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)
+        assert!(!substs.has_erasable_regions());
+        assert!(!substs.needs_subst());
+        substs.visit_with(&mut hasher);
+
+        let mut avoid_cross_crate_conflicts = false;
+
+        // If this is an instance of a generic function, we also hash in
+        // the ID of the instantiating crate. This avoids symbol conflicts
+        // in case the same instances is emitted in two crates of the same
+        // project.
+        if substs.types().next().is_some() {
+            avoid_cross_crate_conflicts = true;
+        }
+
+        // If we're dealing with an instance of a function that's inlined from
+        // another crate but we're marking it as globally shared to our
+        // compliation (aka we're not making an internal copy in each of our
+        // codegen units) then this symbol may become an exported (but hidden
+        // visibility) symbol. This means that multiple crates may do the same
+        // and we want to be sure to avoid any symbol conflicts here.
+        match MonoItem::Fn(instance).instantiation_mode(tcx) {
+            InstantiationMode::GloballyShared { may_conflict: true } => {
+                avoid_cross_crate_conflicts = true;
+            }
+            _ => {}
+        }
+
+        if avoid_cross_crate_conflicts {
+            hasher.hash(tcx.crate_name.as_str());
+            hasher.hash(tcx.sess.local_crate_disambiguator());
+        }
+    });
+
+    // 64 bits should be enough to avoid collisions.
+    hasher.finish()
+}
+
+fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+                             -> ty::SymbolName
+{
+    let mut buffer = SymbolPathBuffer::new();
+    item_path::with_forced_absolute_paths(|| {
+        tcx.push_item_path(&mut buffer, def_id);
+    });
+    buffer.into_interned()
+}
+
+fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
+                         -> ty::SymbolName
+{
+    ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() }
+}
+
+fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>)
+    -> String
+{
+    let def_id = instance.def_id();
+    let substs = instance.substs;
+
+    debug!("symbol_name(def_id={:?}, substs={:?})",
+           def_id, substs);
+
+    let node_id = tcx.hir.as_local_node_id(def_id);
+
+    if let Some(id) = node_id {
+        if tcx.sess.plugin_registrar_fn.get() == Some(id) {
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
+        }
+        if tcx.sess.derive_registrar_fn.get() == Some(id) {
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_derive_registrar_symbol(disambiguator);
+        }
+    }
+
+    // FIXME(eddyb) Precompute a custom symbol name based on attributes.
+    let attrs = tcx.get_attrs(def_id);
+    let is_foreign = if let Some(id) = node_id {
+        match tcx.hir.get(id) {
+            hir_map::NodeForeignItem(_) => true,
+            _ => false
+        }
+    } else {
+        tcx.is_foreign_item(def_id)
+    };
+
+    if let Some(name) = weak_lang_items::link_name(&attrs) {
+        return name.to_string();
+    }
+
+    if is_foreign {
+        if let Some(name) = attr::first_attr_value_str_by_name(&attrs, "link_name") {
+            return name.to_string();
+        }
+        // Don't mangle foreign items.
+        return tcx.item_name(def_id).to_string();
+    }
+
+    if let Some(name) = tcx.export_name(def_id) {
+        // Use provided name
+        return name.to_string();
+    }
+
+    if attr::contains_name(&attrs, "no_mangle") {
+        // Don't mangle
+        return tcx.item_name(def_id).to_string();
+    }
+
+    // We want to compute the "type" of this item. Unfortunately, some
+    // kinds of items (e.g., closures) don't have an entry in the
+    // item-type array. So walk back up the find the closest parent
+    // that DOES have an entry.
+    let mut ty_def_id = def_id;
+    let instance_ty;
+    loop {
+        let key = tcx.def_key(ty_def_id);
+        match key.disambiguated_data.data {
+            DefPathData::TypeNs(_) |
+            DefPathData::ValueNs(_) => {
+                instance_ty = tcx.type_of(ty_def_id);
+                break;
+            }
+            _ => {
+                // if we're making a symbol for something, there ought
+                // to be a value or type-def or something in there
+                // *somewhere*
+                ty_def_id.index = key.parent.unwrap_or_else(|| {
+                    bug!("finding type for {:?}, encountered def-id {:?} with no \
+                          parent", def_id, ty_def_id);
+                });
+            }
+        }
+    }
+
+    // Erase regions because they may not be deterministic when hashed
+    // and should not matter anyhow.
+    let instance_ty = tcx.erase_regions(&instance_ty);
+
+    let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs);
+
+    SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash)
+}
+
+// Follow C++ namespace-mangling style, see
+// http://en.wikipedia.org/wiki/Name_mangling for more info.
+//
+// It turns out that on macOS you can actually have arbitrary symbols in
+// function names (at least when given to LLVM), but this is not possible
+// when using unix's linker. Perhaps one day when we just use a linker from LLVM
+// we won't need to do this name mangling. The problem with name mangling is
+// that it seriously limits the available characters. For example we can't
+// have things like &T in symbol names when one would theoretically
+// want them for things like impls of traits on that type.
+//
+// To be able to work on all platforms and get *some* reasonable output, we
+// use C++ name-mangling.
+struct SymbolPathBuffer {
+    result: String,
+    temp_buf: String
+}
+
+impl SymbolPathBuffer {
+    fn new() -> Self {
+        let mut result = SymbolPathBuffer {
+            result: String::with_capacity(64),
+            temp_buf: String::with_capacity(16)
+        };
+        result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
+        result
+    }
+
+    fn from_interned(symbol: ty::SymbolName) -> Self {
+        let mut result = SymbolPathBuffer {
+            result: String::with_capacity(64),
+            temp_buf: String::with_capacity(16)
+        };
+        result.result.push_str(&symbol.name);
+        result
+    }
+
+    fn into_interned(self) -> ty::SymbolName {
+        ty::SymbolName { name: Symbol::intern(&self.result).as_str() }
+    }
+
+    fn finish(mut self, hash: u64) -> String {
+        // E = end name-sequence
+        let _ = write!(self.result, "17h{:016x}E", hash);
+        self.result
+    }
+}
+
+impl ItemPathBuffer for SymbolPathBuffer {
+    fn root_mode(&self) -> &RootMode {
+        const ABSOLUTE: &'static RootMode = &RootMode::Absolute;
+        ABSOLUTE
+    }
+
+    fn push(&mut self, text: &str) {
+        self.temp_buf.clear();
+        let need_underscore = sanitize(&mut self.temp_buf, text);
+        let _ = write!(self.result, "{}", self.temp_buf.len() + (need_underscore as usize));
+        if need_underscore {
+            self.result.push('_');
+        }
+        self.result.push_str(&self.temp_buf);
+    }
+}
+
+// Name sanitation. LLVM will happily accept identifiers with weird names, but
+// gas doesn't!
+// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
+//
+// returns true if an underscore must be added at the start
+pub fn sanitize(result: &mut String, s: &str) -> bool {
+    for c in s.chars() {
+        match c {
+            // Escape these with $ sequences
+            '@' => result.push_str("$SP$"),
+            '*' => result.push_str("$BP$"),
+            '&' => result.push_str("$RF$"),
+            '<' => result.push_str("$LT$"),
+            '>' => result.push_str("$GT$"),
+            '(' => result.push_str("$LP$"),
+            ')' => result.push_str("$RP$"),
+            ',' => result.push_str("$C$"),
+
+            // '.' doesn't occur in types and functions, so reuse it
+            // for ':' and '-'
+            '-' | ':' => result.push('.'),
+
+            // These are legal symbols
+            'a' ... 'z'
+            | 'A' ... 'Z'
+            | '0' ... '9'
+            | '_' | '.' | '$' => result.push(c),
+
+            _ => {
+                result.push('$');
+                for c in c.escape_unicode().skip(1) {
+                    match c {
+                        '{' => {},
+                        '}' => result.push('$'),
+                        c => result.push(c),
+                    }
+                }
+            }
+        }
+    }
+
+    // Underscore-qualify anything that didn't start as an ident.
+    !result.is_empty() &&
+        result.as_bytes()[0] != '_' as u8 &&
+        ! (result.as_bytes()[0] as char).is_xid_start()
+}
diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs
new file mode 100644 (file)
index 0000000..5d7d4f3
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Walks the crate looking for items/impl-items/trait-items that have
+//! either a `rustc_symbol_name` or `rustc_item_path` attribute and
+//! generates an error giving, respectively, the symbol name or
+//! item-path. This is used for unit testing the code that generates
+//! paths etc in all kinds of annoying scenarios.
+
+use rustc::hir;
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use rustc::ty::TyCtxt;
+use syntax::ast;
+
+use rustc_mir::monomorphize::Instance;
+
+const SYMBOL_NAME: &'static str = "rustc_symbol_name";
+const ITEM_PATH: &'static str = "rustc_item_path";
+
+pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    // if the `rustc_attrs` feature is not enabled, then the
+    // attributes we are interested in cannot be present anyway, so
+    // skip the walk.
+    if !tcx.sess.features.borrow().rustc_attrs {
+        return;
+    }
+
+    tcx.dep_graph.with_ignore(|| {
+        let mut visitor = SymbolNamesTest { tcx: tcx };
+        // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like
+        tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
+    })
+}
+
+struct SymbolNamesTest<'a, 'tcx:'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> {
+    fn process_attrs(&mut self,
+                     node_id: ast::NodeId) {
+        let tcx = self.tcx;
+        let def_id = tcx.hir.local_def_id(node_id);
+        for attr in tcx.get_attrs(def_id).iter() {
+            if attr.check_name(SYMBOL_NAME) {
+                // for now, can only use on monomorphic names
+                let instance = Instance::mono(tcx, def_id);
+                let name = self.tcx.symbol_name(instance);
+                tcx.sess.span_err(attr.span, &format!("symbol-name({})", name));
+            } else if attr.check_name(ITEM_PATH) {
+                let path = tcx.item_path_str(def_id);
+                tcx.sess.span_err(attr.span, &format!("item-path({})", path));
+            }
+
+            // (*) The formatting of `tag({})` is chosen so that tests can elect
+            // to test the entirety of the string, if they choose, or else just
+            // some subset.
+        }
+    }
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        self.process_attrs(item.id);
+        intravisit::walk_item(self, item);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) {
+        self.process_attrs(ti.id);
+        intravisit::walk_trait_item(self, ti)
+    }
+
+    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) {
+        self.process_attrs(ii.id);
+        intravisit::walk_impl_item(self, ii)
+    }
+}
index 47143893e59e23393da133feff95be4f6aa17100..49756d754fe55edead0878dda179bb50d59aa575 100644 (file)
@@ -26,6 +26,7 @@
 use std::io::{self, Cursor};
 use std::fs::File;
 use std::path::Path;
+use std::rc::Rc;
 use std::sync::mpsc;
 
 use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
 
 use syntax::symbol::Symbol;
 use rustc::hir::def_id::LOCAL_CRATE;
-use rustc::session::Session;
-use rustc::session::config::{CrateType, OutputFilenames};
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::{CrateType, OutputFilenames, PrintRequest};
 use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::middle::cstore::EncodedMetadata;
-use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
+use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
 use rustc_back::target::Target;
+use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
 
 pub trait TransCrate {
-    type MetadataLoader: MetadataLoaderTrait;
-    type OngoingCrateTranslation;
-    type TranslatedCrate;
+    fn print(&self, _req: PrintRequest, _sess: &Session) {}
+    fn target_features(&self, _sess: &Session) -> Vec<Symbol> { vec![] }
 
-    fn metadata_loader() -> Box<MetadataLoaderTrait>;
-    fn provide(_providers: &mut Providers);
-    fn provide_extern(_providers: &mut Providers);
+    fn metadata_loader(&self) -> Box<MetadataLoader>;
+    fn provide(&self, _providers: &mut Providers);
+    fn provide_extern(&self, _providers: &mut Providers);
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation;
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
+    ) -> Box<Any>;
+
+    /// This is called on the returned `Box<Any>` from `trans_crate`
+    ///
+    /// # Panics
+    ///
+    /// Panics when the passed `Box<Any>` was not returned by `trans_crate`.
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
         sess: &Session,
-        dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate;
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
-    fn dump_incremental_data(trans: &Self::TranslatedCrate);
+        dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete>;
 }
 
 pub struct DummyTransCrate;
 
 impl TransCrate for DummyTransCrate {
-    type MetadataLoader = DummyMetadataLoader;
-    type OngoingCrateTranslation = ();
-    type TranslatedCrate = ();
-
-    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box DummyMetadataLoader(())
     }
 
-    fn provide(_providers: &mut Providers) {
+    fn provide(&self, _providers: &mut Providers) {
         bug!("DummyTransCrate::provide");
     }
 
-    fn provide_extern(_providers: &mut Providers) {
+    fn provide_extern(&self, _providers: &mut Providers) {
         bug!("DummyTransCrate::provide_extern");
     }
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         _tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
+    ) -> Box<Any> {
         bug!("DummyTransCrate::trans_crate");
     }
 
-    fn join_trans(
-        _trans: Self::OngoingCrateTranslation,
+    fn join_trans_and_link(
+        &self,
+        _trans: Box<Any>,
         _sess: &Session,
-        _dep_graph: &DepGraph
-    ) -> Self::TranslatedCrate {
-        bug!("DummyTransCrate::join_trans");
-    }
-
-    fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
-        bug!("DummyTransCrate::link_binary");
-    }
-
-    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
-        bug!("DummyTransCrate::dump_incremental_data");
+        _dep_graph: &DepGraph,
+        _outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        bug!("DummyTransCrate::join_trans_and_link");
     }
 }
 
 pub struct DummyMetadataLoader(());
 
-impl MetadataLoaderTrait for DummyMetadataLoader {
+impl MetadataLoader for DummyMetadataLoader {
     fn get_rlib_metadata(
         &self,
         _target: &Target,
@@ -131,7 +130,7 @@ fn get_dylib_metadata(
 
 pub struct NoLlvmMetadataLoader;
 
-impl MetadataLoaderTrait for NoLlvmMetadataLoader {
+impl MetadataLoader for NoLlvmMetadataLoader {
     fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
         let file = File::open(filename)
             .map_err(|e| format!("metadata file open err: {:?}", e))?;
@@ -161,87 +160,132 @@ fn get_dylib_metadata(
     }
 }
 
-pub struct MetadataOnlyTransCrate;
+pub struct MetadataOnlyTransCrate(());
 pub struct OngoingCrateTranslation {
     metadata: EncodedMetadata,
     metadata_version: Vec<u8>,
     crate_name: Symbol,
 }
-pub struct TranslatedCrate(OngoingCrateTranslation);
 
 impl MetadataOnlyTransCrate {
-    #[allow(dead_code)]
-    pub fn new() -> Self {
-        MetadataOnlyTransCrate
+    pub fn new(sess: &Session) -> Box<TransCrate> {
+        for cty in sess.opts.crate_types.iter() {
+            match *cty {
+                CrateType::CrateTypeRlib | CrateType::CrateTypeDylib |
+                CrateType::CrateTypeExecutable => {},
+                _ => {
+                    sess.parse_sess.span_diagnostic.warn(
+                        &format!("LLVM unsupported, so output type {} is not supported", cty)
+                    );
+                },
+            }
+        }
+
+        box MetadataOnlyTransCrate(())
     }
 }
 
 impl TransCrate for MetadataOnlyTransCrate {
-    type MetadataLoader = NoLlvmMetadataLoader;
-    type OngoingCrateTranslation = OngoingCrateTranslation;
-    type TranslatedCrate = TranslatedCrate;
-
-    fn metadata_loader() -> Box<MetadataLoaderTrait> {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
         box NoLlvmMetadataLoader
     }
 
-    fn provide(_providers: &mut Providers) {}
-    fn provide_extern(_providers: &mut Providers) {}
+    fn provide(&self, providers: &mut Providers) {
+        ::symbol_names::provide(providers);
+        providers.target_features_enabled = |_tcx, _id| {
+            Rc::new(Vec::new()) // Just a dummy
+        };
+    }
+    fn provide_extern(&self, _providers: &mut Providers) {}
 
     fn trans_crate<'a, 'tcx>(
+        &self,
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _rx: mpsc::Receiver<Box<Any + Send>>
-    ) -> Self::OngoingCrateTranslation {
+    ) -> Box<Any> {
+        use rustc_mir::monomorphize::item::MonoItem;
+
         ::check_for_rustc_errors_attr(tcx);
+        ::symbol_names_test::report_symbol_names(tcx);
+        ::rustc_incremental::assert_dep_graph(tcx);
+        ::rustc_incremental::assert_module_sources::assert_module_sources(tcx);
+        ::rustc_mir::monomorphize::assert_symbols_are_distinct(tcx,
+            collector::collect_crate_mono_items(
+                tcx,
+                collector::MonoItemCollectionMode::Eager
+            ).0.iter()
+        );
+        ::rustc::middle::dependency_format::calculate(tcx);
         let _ = tcx.link_args(LOCAL_CRATE);
         let _ = tcx.native_libraries(LOCAL_CRATE);
+        for trans_item in
+            collector::collect_crate_mono_items(
+                tcx,
+                collector::MonoItemCollectionMode::Eager
+            ).0 {
+            match trans_item {
+                MonoItem::Fn(inst) => {
+                    let def_id = inst.def_id();
+                    if def_id.is_local()  {
+                        let _ = tcx.export_name(def_id);
+                        let _ = tcx.contains_extern_indicator(def_id);
+                        let _ = inst.def.is_inline(tcx);
+                        let attrs = inst.def.attrs(tcx);
+                        let _ =
+                            ::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
+                    }
+                }
+                _ => {}
+            }
+        }
         tcx.sess.abort_if_errors();
 
         let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
         let exported_symbols = ::find_exported_symbols(tcx);
         let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
 
-        OngoingCrateTranslation {
+        box OngoingCrateTranslation {
             metadata: metadata,
             metadata_version: tcx.metadata_encoding_version().to_vec(),
             crate_name: tcx.crate_name(LOCAL_CRATE),
         }
     }
 
-    fn join_trans(
-        trans: Self::OngoingCrateTranslation,
-        _sess: &Session,
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
+        sess: &Session,
         _dep_graph: &DepGraph,
-    ) -> Self::TranslatedCrate {
-        TranslatedCrate(trans)
-    }
-
-    fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        let trans = trans.downcast::<OngoingCrateTranslation>()
+            .expect("Expected MetadataOnlyTransCrate's OngoingCrateTranslation, found Box<Any>");
         for &crate_type in sess.opts.crate_types.iter() {
             if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
                 continue;
             }
             let output_name =
-                out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
-            let mut compressed = trans.0.metadata_version.clone();
+                out_filename(sess, crate_type, &outputs, &trans.crate_name.as_str());
+            let mut compressed = trans.metadata_version.clone();
             let metadata = if crate_type == CrateType::CrateTypeDylib {
                 DeflateEncoder::new(&mut compressed, Compression::fast())
-                    .write_all(&trans.0.metadata.raw_data)
+                    .write_all(&trans.metadata.raw_data)
                     .unwrap();
                 &compressed
             } else {
-                &trans.0.metadata.raw_data
+                &trans.metadata.raw_data
             };
             let mut builder = Builder::new(File::create(&output_name).unwrap());
             let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
             builder.append(&header, Cursor::new(metadata)).unwrap();
         }
 
+        sess.abort_if_errors();
         if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
-            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
+            && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib)
+        {
             sess.fatal("Executables are not supported by the metadata-only backend.");
         }
+        Ok(())
     }
-
-    fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
 }
index df1694a601056b8e0c66414ef2753b9959599710..5c5e5f2735b712a7f789e61688c79a82e6c6ee64 100644 (file)
@@ -210,15 +210,25 @@ fn confirm_builtin_call(&self,
                         }
                     }
                 }
-                let mut err = type_error_struct!(self.tcx.sess, call_expr.span, callee_ty, E0618,
-                                                 "expected function, found `{}`",
-                                                 if let Some(ref path) = unit_variant {
-                                                     path.to_string()
-                                                 } else {
-                                                     callee_ty.to_string()
-                                                 });
-                if let Some(path) = unit_variant {
-                    err.help(&format!("did you mean to write `{}`?", path));
+
+                let mut err = type_error_struct!(
+                    self.tcx.sess,
+                    call_expr.span,
+                    callee_ty,
+                    E0618,
+                    "expected function, found {}",
+                    match unit_variant {
+                        Some(ref path) => format!("enum variant `{}`", path),
+                        None => format!("`{}`", callee_ty),
+                    });
+
+                err.span_label(call_expr.span, "not a function");
+
+                if let Some(ref path) = unit_variant {
+                    err.span_suggestion(call_expr.span,
+                                        &format!("`{}` is a unit variant, you need to write it \
+                                                  without the parenthesis", path),
+                                        path.to_string());
                 }
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
@@ -235,7 +245,11 @@ fn confirm_builtin_call(&self,
                         _ => self.tcx.hir.span_if_local(def.def_id())
                     };
                     if let Some(span) = def_span {
-                        err.span_note(span, "defined here");
+                        let name = match unit_variant {
+                            Some(path) => path,
+                            None => callee_ty.to_string(),
+                        };
+                        err.span_label(span, format!("`{}` defined here", name));
                     }
                 }
 
index 734287f5f7d2992d89afe8b15406e96e0be89af8..570eecfc267deea3ff5fa8f7fe7dc044c5bfc141 100644 (file)
@@ -518,7 +518,10 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            self_descr);
             err.span_label(impl_m_span, format!("`{}` used in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
-                err.span_label(span, format!("trait declared without `{}`", self_descr));
+                err.span_label(span, format!("trait method declared without `{}`", self_descr));
+            } else {
+                err.note_trait_signature(trait_m.name.to_string(),
+                                         trait_m.signature(&tcx));
             }
             err.emit();
             return Err(ErrorReported);
@@ -533,8 +536,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             not in the impl",
                                            trait_m.name,
                                            self_descr);
-            err.span_label(impl_m_span,
-                           format!("expected `{}` in impl", self_descr));
+            err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr));
             if let Some(span) = tcx.hir.span_if_local(trait_m.def_id) {
                 err.span_label(span, format!("`{}` used in trait", self_descr));
             } else {
index 6703bbba86b1c9db37271eefd9767c4477e1ac90..b6b863cfea6e66394a3f9749a447883eacb275ac 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::traits::ObligationCause;
 
 use syntax::ast;
+use syntax::util::parser::AssocOp;
 use syntax_pos::{self, Span};
 use rustc::hir;
 use rustc::hir::print;
@@ -137,7 +138,7 @@ pub fn demand_coerce_diag(&self,
 
         if let Some((msg, suggestion)) = self.check_ref(expr, checked_ty, expected) {
             err.span_suggestion(expr.span, msg, suggestion);
-        } else {
+        } else if !self.check_for_cast(&mut err, expr, expr_ty, expected) {
             let methods = self.get_conversion_methods(expected, checked_ty);
             if let Ok(expr_text) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
                 let suggestions = iter::repeat(expr_text).zip(methods.iter())
@@ -287,8 +288,7 @@ fn check_ref(&self,
                         // Maybe remove `&`?
                         hir::ExprAddrOf(_, ref expr) => {
                             if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                                return Some(("consider removing the borrow",
-                                             code));
+                                return Some(("consider removing the borrow", code));
                             }
                         }
 
@@ -303,7 +303,7 @@ fn check_ref(&self,
                                                  format!("*{}", code)));
                                 }
                             }
-                        },
+                        }
                     }
                 }
                 None
@@ -311,4 +311,240 @@ fn check_ref(&self,
             _ => None,
         }
     }
+
+    fn check_for_cast(&self,
+                      err: &mut DiagnosticBuilder<'tcx>,
+                      expr: &hir::Expr,
+                      checked_ty: Ty<'tcx>,
+                      expected_ty: Ty<'tcx>)
+                      -> bool {
+        let will_truncate = "will truncate the source value";
+        let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
+                                  `isize`";
+        let depending_on_usize = "will truncate or zero-extend depending on the bit width of \
+                                  `usize`";
+        let will_sign_extend = "will sign-extend the source value";
+        let will_zero_extend = "will zero-extend the source value";
+
+        // If casting this expression to a given numeric type would be appropriate in case of a type
+        // mismatch.
+        //
+        // We want to minimize the amount of casting operations that are suggested, as it can be a
+        // lossy operation with potentially bad side effects, so we only suggest when encountering
+        // an expression that indicates that the original type couldn't be directly changed.
+        //
+        // For now, don't suggest casting with `as`.
+        let can_cast = false;
+
+        let needs_paren = expr.precedence().order() < (AssocOp::As.precedence() as i8);
+
+        if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
+            let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
+            let cast_suggestion = format!("{}{}{} as {}",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" },
+                                          expected_ty);
+            let into_suggestion = format!("{}{}{}.into()",
+                                          if needs_paren { "(" } else { "" },
+                                          src,
+                                          if needs_paren { ")" } else { "" });
+
+            match (&expected_ty.sty, &checked_ty.sty) {
+                (&ty::TyInt(ref exp), &ty::TyInt(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_sign_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyUint(ref found)) => {
+                    match (found.bit_width(), exp.bit_width()) {
+                        (Some(found), Some(exp)) if found > exp => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                        }
+                        (None, _) | (_, None) => {
+                            if can_cast {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                        }
+                        _ => {
+                            err.span_suggestion(expr.span,
+                                                &format!("{}, which {}", msg, will_zero_extend),
+                                                into_suggestion);
+                        }
+                    }
+                    true
+                }
+                (&ty::TyInt(ref exp), &ty::TyUint(ref found)) => {
+                    if can_cast {
+                        match (found.bit_width(), exp.bit_width()) {
+                            (Some(found), Some(exp)) if found > exp - 1 => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_zero_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyUint(ref exp), &ty::TyInt(ref found)) => {
+                    if can_cast {
+                        match (found.bit_width(), exp.bit_width()) {
+                            (Some(found), Some(exp)) if found - 1 > exp => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_truncate),
+                                                    cast_suggestion);
+                            }
+                            (None, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                            (None, _) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_usize),
+                                                    cast_suggestion);
+                            }
+                            (_, None) => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}",
+                                                             msg,
+                                                             depending_on_isize),
+                                                    cast_suggestion);
+                            }
+                            _ => {
+                                err.span_suggestion(expr.span,
+                                                    &format!("{}, which {}", msg, will_sign_extend),
+                                                    cast_suggestion);
+                            }
+                        }
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyFloat(ref found)) => {
+                    if found.bit_width() < exp.bit_width() {
+                        err.span_suggestion(expr.span,
+                                            &format!("{} in a lossless way",
+                                                     msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the closest possible value",
+                                                     msg),
+                                            cast_suggestion);
+                        err.warn("casting here will cause undefined behavior if the value is \
+                                  finite but larger or smaller than the largest or smallest \
+                                  finite value representable by `f32` (this is a bug and will be \
+                                  fixed)");
+                    }
+                    true
+                }
+                (&ty::TyUint(_), &ty::TyFloat(_)) | (&ty::TyInt(_), &ty::TyFloat(_)) => {
+                    if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, rounding the float towards zero",
+                                                     msg),
+                                            cast_suggestion);
+                        err.warn("casting here will cause undefined behavior if the rounded value \
+                                  cannot be represented by the target integer type, including \
+                                  `Inf` and `NaN` (this is a bug and will be fixed)");
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyUint(ref found)) => {
+                    // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                (&ty::TyFloat(ref exp), &ty::TyInt(ref found)) => {
+                    // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
+                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer",
+                                                      msg),
+                                            into_suggestion);
+                    } else if can_cast {
+                        err.span_suggestion(expr.span,
+                                            &format!("{}, producing the floating point \
+                                                      representation of the integer, rounded if \
+                                                      necessary",
+                                                      msg),
+                                            cast_suggestion);
+                    }
+                    true
+                }
+                _ => false,
+            }
+        } else {
+            false
+        }
+    }
 }
index 69236d77ed328a44fa97f3f559f9713abe18f11d..cb8ce8d5ac331296e971ac3f02bef1cbf36d5331 100644 (file)
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
+use rustc::ty::layout::LayoutOf;
 use errors::{DiagnosticBuilder, DiagnosticId};
 use require_c_abi_if_variadic;
 use session::{CompileIncomplete, config, Session};
@@ -1104,6 +1105,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         check_simd(tcx, span, def_id);
     }
 
+    check_transparent(tcx, span, def_id);
     check_packed(tcx, span, def_id);
 }
 
@@ -1517,6 +1519,42 @@ fn check_packed_inner<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     false
 }
 
+fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId) {
+    let adt = tcx.adt_def(def_id);
+    if !adt.repr.transparent() {
+        return;
+    }
+
+    // For each field, figure out if it's known to be a ZST and align(1)
+    let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| {
+        let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did));
+        let param_env = tcx.param_env(field.did);
+        let layout = (tcx, param_env).layout_of(ty);
+        // We are currently checking the type this field came from, so it must be local
+        let span = tcx.hir.span_if_local(field.did).unwrap();
+        let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
+        let align1 = layout.map(|layout| layout.align.abi() == 1).unwrap_or(false);
+        (span, zst, align1)
+    }).collect();
+
+    let non_zst_fields = field_infos.iter().filter(|(_span, zst, _align1)| !*zst);
+    let non_zst_count = non_zst_fields.clone().count();
+    if non_zst_count != 1 {
+        let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| *span).collect();
+        struct_span_err!(tcx.sess, sp, E0690,
+                         "transparent struct needs exactly one non-zero-sized field, but has {}",
+                          non_zst_count)
+        .span_note(field_spans, "non-zero-sized field")
+        .emit();
+    }
+    for &(span, zst, align1) in &field_infos {
+        if zst && !align1 {
+            span_err!(tcx.sess, span, E0691,
+                      "zero-sized field in transparent struct has alignment larger than 1");
+        }
+    }
+}
+
 #[allow(trivial_numeric_casts)]
 pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             sp: Span,
index 1913b940c08fe2db38d48fbe297c00cb322bca6a..4f661a4f5e67d739a01c549d8d952609ffb4529f 100644 (file)
@@ -4605,6 +4605,99 @@ fn foo<U: Iterator>(&self, _: &U) { } // error method `foo` has incompatible
 let _ = (2.0 as f32).powi(2);
 ```
 "##,
+
+E0690: r##"
+A struct with the representation hint `repr(transparent)` had zero or more than
+on fields that were not guaranteed to be zero-sized.
+
+Erroneous code example:
+
+```compile_fail,E0690
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct LengthWithUnit<U> { // error: transparent struct needs exactly one
+    value: f32,            //        non-zero-sized field, but has 2
+    unit: U,
+}
+```
+
+Because transparent structs are represented exactly like one of their fields at
+run time, said field must be uniquely determined. If there is no field, or if
+there are multiple fields, it is not clear how the struct should be represented.
+Note that fields of zero-typed types (e.g., `PhantomData`) can also exist
+alongside the field that contains the actual data, they do not count for this
+error. When generic types are involved (as in the above example), an error is
+reported because the type parameter could be non-zero-sized.
+
+To combine `repr(transparent)` with type parameters, `PhantomData` may be
+useful:
+
+```
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+#[repr(transparent)]
+struct LengthWithUnit<U> {
+    value: f32,
+    unit: PhantomData<U>,
+}
+```
+"##,
+
+E0691: r##"
+A struct with the `repr(transparent)` representation hint contains a zero-sized
+field that requires non-trivial alignment.
+
+Erroneous code example:
+
+```compile_fail,E0691
+#![feature(repr_transparent, repr_align, attr_literals)]
+
+#[repr(align(32))]
+struct ForceAlign32;
+
+#[repr(transparent)]
+struct Wrapper(f32, ForceAlign32); // error: zero-sized field in transparent
+                                   //        struct has alignment larger than 1
+```
+
+A transparent struct is supposed to be represented exactly like the piece of
+data it contains. Zero-sized fields with different alignment requirements
+potentially conflict with this property. In the example above, `Wrapper` would
+have to be aligned to 32 bytes even though `f32` has a smaller alignment
+requirement.
+
+Consider removing the over-aligned zero-sized field:
+
+```
+#![feature(repr_transparent)]
+
+#[repr(transparent)]
+struct Wrapper(f32);
+```
+
+Alternatively, `PhantomData<T>` has alignment 1 for all `T`, so you can use it
+if you need to keep the field for some reason:
+
+```
+#![feature(repr_transparent, repr_align, attr_literals)]
+
+use std::marker::PhantomData;
+
+#[repr(align(32))]
+struct ForceAlign32;
+
+#[repr(transparent)]
+struct Wrapper(f32, PhantomData<ForceAlign32>);
+```
+
+Note that empty arrays `[T; 0]` have the same alignment requirement as the
+element type `T`. Also note that the error is conservatively reported even when
+the alignment of the zero-sized type is less than or equal to the data field's
+alignment.
+"##,
 }
 
 register_diagnostics! {
index 1dc98bc7a0072825a7ed32b1939f687774b3985b..786a6783440640011f5a9101300242e06654c544 100644 (file)
@@ -77,6 +77,7 @@
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
 #![feature(conservative_impl_trait)]
+#![feature(copy_closures, clone_closures)]
 #![feature(from_ref)]
 #![feature(match_default_bindings)]
 #![feature(never_type)]
index b353c0da865c86cfa5fbf66b78add79382845fa8..ef7d5b5ff84afb8926f1c3743a253d6899034a88 100644 (file)
@@ -19,7 +19,6 @@
 use rustc::lint;
 use rustc::util::nodemap::FxHashMap;
 use rustc_trans;
-use rustc_trans::back::link;
 use rustc_resolve as resolve;
 use rustc_metadata::cstore::CStore;
 
@@ -140,22 +139,22 @@ pub fn run_core(search_paths: SearchPaths,
                                                                false,
                                                                Some(codemap.clone()));
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, cpath, diagnostic_handler, codemap,
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
-    target_features::add_configuration(&mut cfg, &sess);
+    target_features::add_configuration(&mut cfg, &sess, &*trans);
     sess.parse_sess.config = cfg;
 
     let control = &driver::CompileController::basic();
 
     let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
 
-    let name = link::find_crate_name(Some(&sess), &krate.attrs, &input);
+    let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
 
     let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
         let result = driver::phase_2_configure_and_expand(&sess,
@@ -177,7 +176,8 @@ pub fn run_core(search_paths: SearchPaths,
                                                           &[],
                                                           &sess);
 
-    abort_on_err(driver::phase_3_run_analysis_passes(control,
+    abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
+                                                     control,
                                                      &sess,
                                                      &*cstore,
                                                      hir_map,
index 61de5f4bc4c4500e9155024cb9edcb179ddf53a4..3a18c6b8a809e0de0c15fc7ed87fe6d18a83b154 100644 (file)
@@ -94,20 +94,22 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                 <h2>Keyboard Shortcuts</h2>
 
                 <dl>
-                    <dt>?</dt>
+                    <dt><kbd>?</kbd></dt>
                     <dd>Show this help dialog</dd>
-                    <dt>S</dt>
+                    <dt><kbd>S</kbd></dt>
                     <dd>Focus the search field</dd>
-                    <dt>↑</dt>
+                    <dt><kbd>↑</kbd></dt>
                     <dd>Move up in search results</dd>
-                    <dt>↓</dt>
+                    <dt><kbd>↓</kbd></dt>
                     <dd>Move down in search results</dd>
-                    <dt>↹</dt>
+                    <dt><kbd>↹</kbd></dt>
                     <dd>Switch tab</dd>
-                    <dt>&#9166;</dt>
+                    <dt><kbd>&#9166;</kbd></dt>
                     <dd>Go to active search result</dd>
-                    <dt style="width:31px;">+ / -</dt>
-                    <dd>Collapse/expand all sections</dd>
+                    <dt><kbd>+</kbd></dt>
+                    <dd>Expand all sections</dd>
+                    <dt><kbd>-</kbd></dt>
+                    <dd>Collapse all sections</dd>
                 </dl>
             </div>
 
index b41874a56b8e722e357fb3dc67769f8c9cf3aee4..34b04de86735e60f08f7550bc52bd2049c29b9e4 100644 (file)
@@ -585,18 +585,13 @@ body.blur > :not(#help) {
        flex: 0 0 auto;
        box-shadow: 0 0 6px rgba(0,0,0,.2);
        width: 550px;
-       height: 354px;
+       height: auto;
        border: 1px solid;
 }
 #help dt {
        float: left;
-       border-radius: 4px;
-       border: 1px solid;
-       width: 23px;
-       text-align: center;
        clear: left;
        display: block;
-       margin-top: -1px;
 }
 #help dd { margin: 5px 35px; }
 #help .infos { padding-left: 0; }
@@ -1134,3 +1129,14 @@ h3.important {
        left: -42px;
        margin-top: 2px;
 }
+
+kbd {
+       display: inline-block;
+       padding: 3px 5px;
+       font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+       line-height: 10px;
+       vertical-align: middle;
+       border: solid 1px;
+       border-radius: 3px;
+       box-shadow: inset 0 -1px 0;
+}
index c79413c0852cec3de8c876fd2361790c4db10ecd..bd74056242442e2a66b3f3fd63c2d06a52ac85ed 100644 (file)
@@ -194,11 +194,6 @@ a.test-arrow {
        border-color: #bfbfbf;
 }
 
-#help dt {
-       border-color: #bfbfbf;
-       background: #fff;
-}
-
 .since {
        color: grey;
 }
@@ -348,3 +343,11 @@ pre.ignore:hover, .information:hover + pre.ignore {
                border-bottom-color: #e0e0e0;
        }
 }
+
+kbd {
+       color: #444d56;
+       background-color: #fafbfc;
+       border-color: #d1d5da;
+       border-bottom-color: #c6cbd1;
+       box-shadow-color: #c6cbd1;
+}
index 0b57d5d26cecf8d110ebe5d42c930cdb28e225fd..2e2dba7681cc39a9c3156bf28028e70b162949e7 100644 (file)
@@ -34,7 +34,7 @@
 extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_const_math;
-extern crate rustc_trans;
+extern crate rustc_trans_utils;
 extern crate rustc_driver;
 extern crate rustc_resolve;
 extern crate rustc_lint;
@@ -63,6 +63,8 @@
 use std::process;
 use std::sync::mpsc::channel;
 
+use rustc_driver::rustc_trans;
+
 use externalfiles::ExternalHtml;
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options,
index 5432f5cb6e1656b4c0f8891c4a1d2d007fee0873..10850f88f2d624d2944d0aef915f9a4ba2f65638 100644 (file)
@@ -34,7 +34,6 @@
 use rustc_metadata::cstore::CStore;
 use rustc_resolve::MakeGlobMap;
 use rustc_trans;
-use rustc_trans::back::link;
 use syntax::ast;
 use syntax::codemap::CodeMap;
 use syntax::feature_gate::UnstableFeatures;
@@ -82,11 +81,11 @@ pub fn run(input_path: &Path,
                                           true, false,
                                           Some(codemap.clone()));
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     sess.parse_sess.config =
         config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
@@ -108,7 +107,7 @@ pub fn run(input_path: &Path,
     };
 
     let crate_name = crate_name.unwrap_or_else(|| {
-        link::find_crate_name(None, &hir_forest.krate().attrs, &input)
+        ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
     });
     let opts = scrape_test_config(hir_forest.krate());
     let mut collector = Collector::new(crate_name,
@@ -247,11 +246,11 @@ fn drop(&mut self) {
     // Compile the code
     let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
 
-    let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
         sessopts, None, diagnostic_handler, codemap,
     );
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
@@ -266,7 +265,17 @@ fn drop(&mut self) {
     }
 
     let res = panic::catch_unwind(AssertUnwindSafe(|| {
-        driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control)
+        driver::compile_input(
+            trans,
+            &sess,
+            &cstore,
+            &None,
+            &input,
+            &out,
+            &None,
+            None,
+            &control
+        )
     }));
 
     let compile_result = match res {
index a9638717c66fa47dc860adafdf9434d7ab6848a4..1786e2960825dfb7b6340c8c8a84872fc2c21a2c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #[inline]
-fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
+pub fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
     if position == vec.len() {
         vec.push(byte);
     } else {
@@ -17,56 +17,86 @@ fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
     }
 }
 
-#[inline]
-/// encodes an integer using unsigned leb128 encoding and stores
-/// the result using a callback function.
-///
-/// The callback `write` is called once for each position
-/// that is to be written to with the byte to be encoded
-/// at that position.
-pub fn write_unsigned_leb128_to<W>(mut value: u128, mut write: W) -> usize
-    where W: FnMut(usize, u8)
-{
-    let mut position = 0;
-    loop {
-        let mut byte = (value & 0x7F) as u8;
-        value >>= 7;
-        if value != 0 {
-            byte |= 0x80;
-        }
-
-        write(position, byte);
-        position += 1;
+#[cfg(target_pointer_width = "32")]
+const USIZE_LEB128_SIZE: usize = 5;
+#[cfg(target_pointer_width = "64")]
+const USIZE_LEB128_SIZE: usize = 10;
+
+macro_rules! leb128_size {
+    (u16) => (3);
+    (u32) => (5);
+    (u64) => (10);
+    (u128) => (19);
+    (usize) => (USIZE_LEB128_SIZE);
+}
 
-        if value == 0 {
-            break;
+macro_rules! impl_write_unsigned_leb128 {
+    ($fn_name:ident, $int_ty:ident) => (
+        #[inline]
+        pub fn $fn_name(out: &mut Vec<u8>, start_position: usize, mut value: $int_ty) -> usize {
+            let mut position = start_position;
+            for _ in 0 .. leb128_size!($int_ty) {
+                let mut byte = (value & 0x7F) as u8;
+                value >>= 7;
+                if value != 0 {
+                    byte |= 0x80;
+                }
+
+                write_to_vec(out, position, byte);
+                position += 1;
+
+                if value == 0 {
+                    break;
+                }
+            }
+
+            position - start_position
         }
-    }
-
-    position
+    )
 }
 
-pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u128) -> usize {
-    write_unsigned_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
+impl_write_unsigned_leb128!(write_u16_leb128, u16);
+impl_write_unsigned_leb128!(write_u32_leb128, u32);
+impl_write_unsigned_leb128!(write_u64_leb128, u64);
+impl_write_unsigned_leb128!(write_u128_leb128, u128);
+impl_write_unsigned_leb128!(write_usize_leb128, usize);
+
+
+macro_rules! impl_read_unsigned_leb128 {
+    ($fn_name:ident, $int_ty:ident) => (
+        #[inline]
+        pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
+            let mut result: $int_ty = 0;
+            let mut shift = 0;
+            let mut position = 0;
+
+            for _ in 0 .. leb128_size!($int_ty) {
+                let byte = unsafe {
+                    *slice.get_unchecked(position)
+                };
+                position += 1;
+                result |= ((byte & 0x7F) as $int_ty) << shift;
+                if (byte & 0x80) == 0 {
+                    break;
+                }
+                shift += 7;
+            }
+
+            // Do a single bounds check at the end instead of for every byte.
+            assert!(position <= slice.len());
+
+            (result, position)
+        }
+    )
 }
 
-#[inline]
-pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u128, usize) {
-    let mut result = 0;
-    let mut shift = 0;
-    let mut position = start_position;
-    loop {
-        let byte = data[position];
-        position += 1;
-        result |= ((byte & 0x7F) as u128) << shift;
-        if (byte & 0x80) == 0 {
-            break;
-        }
-        shift += 7;
-    }
+impl_read_unsigned_leb128!(read_u16_leb128, u16);
+impl_read_unsigned_leb128!(read_u32_leb128, u32);
+impl_read_unsigned_leb128!(read_u64_leb128, u64);
+impl_read_unsigned_leb128!(read_u128_leb128, u128);
+impl_read_unsigned_leb128!(read_usize_leb128, usize);
+
 
-    (result, position - start_position)
-}
 
 #[inline]
 /// encodes an integer using signed leb128 encoding and stores
@@ -130,26 +160,36 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
     (result, position - start_position)
 }
 
-#[test]
-fn test_unsigned_leb128() {
-    let mut stream = Vec::with_capacity(10000);
-
-    for x in 0..62 {
-        let pos = stream.len();
-        let bytes_written = write_unsigned_leb128(&mut stream, pos, 3 << x);
-        assert_eq!(stream.len(), pos + bytes_written);
-    }
-
-    let mut position = 0;
-    for x in 0..62 {
-        let expected = 3 << x;
-        let (actual, bytes_read) = read_unsigned_leb128(&stream, position);
-        assert_eq!(expected, actual);
-        position += bytes_read;
-    }
-    assert_eq!(stream.len(), position);
+macro_rules! impl_test_unsigned_leb128 {
+    ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => (
+        #[test]
+        fn $test_name() {
+            let mut stream = Vec::new();
+
+            for x in 0..62 {
+                let pos = stream.len();
+                let bytes_written = $write_fn_name(&mut stream, pos, (3u64 << x) as $int_ty);
+                assert_eq!(stream.len(), pos + bytes_written);
+            }
+
+            let mut position = 0;
+            for x in 0..62 {
+                let expected = (3u64 << x) as $int_ty;
+                let (actual, bytes_read) = $read_fn_name(&stream[position ..]);
+                assert_eq!(expected, actual);
+                position += bytes_read;
+            }
+            assert_eq!(stream.len(), position);
+        }
+    )
 }
 
+impl_test_unsigned_leb128!(test_u16_leb128, write_u16_leb128, read_u16_leb128, u16);
+impl_test_unsigned_leb128!(test_u32_leb128, write_u32_leb128, read_u32_leb128, u32);
+impl_test_unsigned_leb128!(test_u64_leb128, write_u64_leb128, read_u64_leb128, u64);
+impl_test_unsigned_leb128!(test_u128_leb128, write_u128_leb128, read_u128_leb128, u128);
+impl_test_unsigned_leb128!(test_usize_leb128, write_usize_leb128, read_usize_leb128, usize);
+
 #[test]
 fn test_signed_leb128() {
     let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
index 409366102bacd81e2678169a152c6c69e4f6dd0d..077efadd60af88823876634ce0524ee0311f060a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128};
+use leb128::{self, read_signed_leb128, write_signed_leb128};
 use std::borrow::Cow;
 use std::io::{self, Write};
 use serialize;
@@ -35,9 +35,9 @@ pub fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
 
 
 macro_rules! write_uleb128 {
-    ($enc:expr, $value:expr) => {{
+    ($enc:expr, $value:expr, $fun:ident) => {{
         let pos = $enc.cursor.position() as usize;
-        let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128);
+        let bytes_written = leb128::$fun($enc.cursor.get_mut(), pos, $value);
         $enc.cursor.set_position((pos + bytes_written) as u64);
         Ok(())
     }}
@@ -55,61 +55,76 @@ macro_rules! write_sleb128 {
 impl<'a> serialize::Encoder for Encoder<'a> {
     type Error = io::Error;
 
+    #[inline]
     fn emit_nil(&mut self) -> EncodeResult {
         Ok(())
     }
 
+    #[inline]
     fn emit_usize(&mut self, v: usize) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_usize_leb128)
     }
 
+    #[inline]
     fn emit_u128(&mut self, v: u128) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u128_leb128)
     }
 
+    #[inline]
     fn emit_u64(&mut self, v: u64) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u64_leb128)
     }
 
+    #[inline]
     fn emit_u32(&mut self, v: u32) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u32_leb128)
     }
 
+    #[inline]
     fn emit_u16(&mut self, v: u16) -> EncodeResult {
-        write_uleb128!(self, v)
+        write_uleb128!(self, v, write_u16_leb128)
     }
 
+    #[inline]
     fn emit_u8(&mut self, v: u8) -> EncodeResult {
-        let _ = self.cursor.write_all(&[v]);
+        let pos = self.cursor.position() as usize;
+        leb128::write_to_vec(self.cursor.get_mut(), pos, v);
+        self.cursor.set_position((pos + 1) as u64);
         Ok(())
     }
 
+    #[inline]
     fn emit_isize(&mut self, v: isize) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i128(&mut self, v: i128) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i64(&mut self, v: i64) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i32(&mut self, v: i32) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i16(&mut self, v: i16) -> EncodeResult {
         write_sleb128!(self, v)
     }
 
+    #[inline]
     fn emit_i8(&mut self, v: i8) -> EncodeResult {
         let as_u8: u8 = unsafe { ::std::mem::transmute(v) };
-        let _ = self.cursor.write_all(&[as_u8]);
-        Ok(())
+        self.emit_u8(as_u8)
     }
 
+    #[inline]
     fn emit_bool(&mut self, v: bool) -> EncodeResult {
         self.emit_u8(if v {
             1
@@ -118,20 +133,24 @@ fn emit_bool(&mut self, v: bool) -> EncodeResult {
         })
     }
 
+    #[inline]
     fn emit_f64(&mut self, v: f64) -> EncodeResult {
         let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
         self.emit_u64(as_u64)
     }
 
+    #[inline]
     fn emit_f32(&mut self, v: f32) -> EncodeResult {
         let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
         self.emit_u32(as_u32)
     }
 
+    #[inline]
     fn emit_char(&mut self, v: char) -> EncodeResult {
         self.emit_u32(v as u32)
     }
 
+    #[inline]
     fn emit_str(&mut self, v: &str) -> EncodeResult {
         self.emit_usize(v.len())?;
         let _ = self.cursor.write_all(v.as_bytes());
@@ -140,6 +159,7 @@ fn emit_str(&mut self, v: &str) -> EncodeResult {
 }
 
 impl<'a> Encoder<'a> {
+    #[inline]
     pub fn position(&self) -> usize {
         self.cursor.position() as usize
     }
@@ -162,14 +182,17 @@ pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
         }
     }
 
+    #[inline]
     pub fn position(&self) -> usize {
         self.position
     }
 
+    #[inline]
     pub fn set_position(&mut self, pos: usize) {
         self.position = pos
     }
 
+    #[inline]
     pub fn advance(&mut self, bytes: usize) {
         self.position += bytes;
     }
@@ -187,10 +210,10 @@ pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
 }
 
 macro_rules! read_uleb128 {
-    ($dec:expr, $t:ty) => ({
-        let (value, bytes_read) = read_unsigned_leb128($dec.data, $dec.position);
+    ($dec:expr, $t:ty, $fun:ident) => ({
+        let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position ..]);
         $dec.position += bytes_read;
-        Ok(value as $t)
+        Ok(value)
     })
 }
 
@@ -213,22 +236,22 @@ fn read_nil(&mut self) -> Result<(), Self::Error> {
 
     #[inline]
     fn read_u128(&mut self) -> Result<u128, Self::Error> {
-        read_uleb128!(self, u128)
+        read_uleb128!(self, u128, read_u128_leb128)
     }
 
     #[inline]
     fn read_u64(&mut self) -> Result<u64, Self::Error> {
-        read_uleb128!(self, u64)
+        read_uleb128!(self, u64, read_u64_leb128)
     }
 
     #[inline]
     fn read_u32(&mut self) -> Result<u32, Self::Error> {
-        read_uleb128!(self, u32)
+        read_uleb128!(self, u32, read_u32_leb128)
     }
 
     #[inline]
     fn read_u16(&mut self) -> Result<u16, Self::Error> {
-        read_uleb128!(self, u16)
+        read_uleb128!(self, u16, read_u16_leb128)
     }
 
     #[inline]
@@ -240,7 +263,7 @@ fn read_u8(&mut self) -> Result<u8, Self::Error> {
 
     #[inline]
     fn read_usize(&mut self) -> Result<usize, Self::Error> {
-        read_uleb128!(self, usize)
+        read_uleb128!(self, usize, read_usize_leb128)
     }
 
     #[inline]
index 96f98efe4aaa8d8fc7c32b6e9b3855dea5cee80c..73bd5747c105a98fd66d470264ab421c33cef817 100644 (file)
@@ -16,7 +16,7 @@
 use mem::{align_of, size_of, needs_drop};
 use mem;
 use ops::{Deref, DerefMut};
-use ptr::{self, Unique, Shared};
+use ptr::{self, Unique, NonNull};
 
 use self::BucketState::*;
 
@@ -873,7 +873,7 @@ pub fn drain(&mut self) -> Drain<K, V> {
                 elems_left,
                 marker: marker::PhantomData,
             },
-            table: Shared::from(self),
+            table: NonNull::from(self),
             marker: marker::PhantomData,
         }
     }
@@ -1020,7 +1020,7 @@ pub fn iter(&self) -> Iter<K, V> {
 
 /// Iterator over the entries in a table, clearing the table.
 pub struct Drain<'a, K: 'a, V: 'a> {
-    table: Shared<RawTable<K, V>>,
+    table: NonNull<RawTable<K, V>>,
     iter: RawBuckets<'static, K, V>,
     marker: marker::PhantomData<&'a RawTable<K, V>>,
 }
index b8a6a66eaa65d60201d107319749cc7336af40a6..e9a150f34a51efdc31afe6b251d0ec780150a2fa 100644 (file)
 //! * You want a map, with no extra functionality.
 //!
 //! ### Use a `BTreeMap` when:
+//! * You want a map sorted by its keys.
+//! * You want to be able to get a range of entries on-demand.
 //! * You're interested in what the smallest or largest key-value pair is.
 //! * You want to find the largest or smallest key that is smaller or larger
 //!   than something.
-//! * You want to be able to get all of the entries in order on-demand.
-//! * You want a map sorted by its keys.
 //!
 //! ### Use the `Set` variant of any of these `Map`s when:
 //! * You just want to remember which keys you've seen.
index bb38fc550917fb8307d97f2171ee17940ea3b298..91cc6d25cce01016601c16b1fc0c1a31f024747a 100644 (file)
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(prelude_import)]
+#![feature(ptr_internals)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(repr_align)]
 #![feature(rustc_attrs)]
-#![feature(shared)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
 #![feature(slice_concat_ext)]
 #![feature(try_from)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unique)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
index 1ca7e66ed9ca91aa1755ff896535b7ea6bafde71..fa430939f058c45e7e3c0ffc86ab0138bd89ee4c 100644 (file)
@@ -12,7 +12,9 @@
 use hash;
 use io;
 use mem;
-use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
+#[allow(deprecated)]
+use net::lookup_host;
 use option;
 use sys::net::netc as c;
 use sys_common::{FromInner, AsInner, IntoInner};
@@ -845,6 +847,7 @@ fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
     }
 }
 
+#[allow(deprecated)]
 fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
     let ips = lookup_host(s)?;
     let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();
index 9fcb93e2032b3ce40489f2cb6d4be9cd103cdb24..eb0e2e13b4cd2099100c85cdccb8f9c13879adb5 100644 (file)
@@ -134,12 +134,15 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
 pub struct LookupHost(net_imp::LookupHost);
 
 #[unstable(feature = "lookup_host", reason = "unsure about the returned \
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 impl Iterator for LookupHost {
     type Item = SocketAddr;
     fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
@@ -149,6 +152,8 @@ fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 impl fmt::Debug for LookupHost {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.pad("LookupHost { .. }")
@@ -181,6 +186,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                                               iterator and returning socket \
                                               addresses",
            issue = "27705")]
+#[rustc_deprecated(since = "1.25", reason = "Use the ToSocketAddrs trait instead")]
+#[allow(deprecated)]
 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     net_imp::lookup_host(host).map(LookupHost)
 }
index 53c2211745c328dda26a9d50025525b6c2ee6e19..560876006d3f348999cb6568a1381306d7bbc39c 100644 (file)
@@ -17,7 +17,7 @@
 use fmt;
 use ops::{Deref, DerefMut};
 use panicking;
-use ptr::{Unique, Shared};
+use ptr::{Unique, NonNull};
 use rc::Rc;
 use sync::{Arc, Mutex, RwLock, atomic};
 use thread::Result;
@@ -196,10 +196,10 @@ impl<'a, T: RefUnwindSafe + ?Sized> UnwindSafe for &'a T {}
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *const T {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: RefUnwindSafe + ?Sized> UnwindSafe for *mut T {}
-#[unstable(feature = "unique", issue = "27730")]
+#[unstable(feature = "ptr_internals", issue = "0")]
 impl<T: UnwindSafe + ?Sized> UnwindSafe for Unique<T> {}
-#[unstable(feature = "shared", issue = "27730")]
-impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Shared<T> {}
+#[stable(feature = "nonnull", since = "1.24.0")]
+impl<T: RefUnwindSafe + ?Sized> UnwindSafe for NonNull<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
 impl<T: ?Sized> UnwindSafe for Mutex<T> {}
 #[stable(feature = "catch_unwind", since = "1.9.0")]
index 7631a9a44bbe72f1b1c2b911a0638fbe554755ab..ed102c2949ede7a667afc435e9f7d1c0a4ea88a1 100644 (file)
@@ -1869,7 +1869,11 @@ pub fn file_name(&self) -> Option<&OsStr> {
     ///
     /// let path = Path::new("/test/haha/foo.txt");
     ///
+    /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
     /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
     /// assert_eq!(path.strip_prefix("test").is_ok(), false);
     /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
     /// ```
@@ -1900,6 +1904,9 @@ fn _strip_prefix<'a>(&'a self, base: &'a Path)
     /// let path = Path::new("/etc/passwd");
     ///
     /// assert!(path.starts_with("/etc"));
+    /// assert!(path.starts_with("/etc/"));
+    /// assert!(path.starts_with("/etc/passwd"));
+    /// assert!(path.starts_with("/etc/passwd/"));
     ///
     /// assert!(!path.starts_with("/e"));
     /// ```
index c3e8d0b7d95a8b31ca22b36dd8078bfd3fa078ec..21218489679393a92a655bf0012caa5ad242f962 100644 (file)
@@ -437,9 +437,5 @@ unsafe impl Send for LookupHost {}
     pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
         unimpl!();
     }
-
-    pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
-        unimpl!();
-    }
 }
 
index e775f857f2b40a84b8df717f9ed6d30649a02b3c..3f65975e608800a7198d6c36bb84832e4a437a62 100644 (file)
@@ -51,6 +51,10 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 {
         return Ok(())
     }
+
+    // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+    on_resolver_failure();
+
     if err == EAI_SYSTEM {
         return Err(io::Error::last_os_error())
     }
@@ -377,21 +381,22 @@ fn into_inner(self) -> c_int { self.0.into_raw() }
 // res_init unconditionally, we call it only when we detect we're linking
 // against glibc version < 2.26. (That is, when we both know its needed and
 // believe it's thread-safe).
-pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
     // If the version fails to parse, we treat it the same as "not glibc".
     if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
         if let Some(version) = parse_glibc_version(version_str) {
             if version < (2, 26) {
-                let ret = unsafe { libc::res_init() };
-                if ret != 0 {
-                    return Err(io::Error::last_os_error());
-                }
+                unsafe { libc::res_init() };
             }
         }
     }
-    Ok(())
 }
 
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
+
+#[cfg(target_env = "gnu")]
 fn glibc_version_cstr() -> Option<&'static CStr> {
     weak! {
         fn gnu_get_libc_version() -> *const libc::c_char
@@ -405,6 +410,7 @@ fn gnu_get_libc_version() -> *const libc::c_char
 
 // Returns Some((major, minor)) if the string is a valid "x.y" version,
 // ignoring any extra dot-separated parts. Otherwise return None.
+#[cfg(target_env = "gnu")]
 fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
     match (parsed_ints.next(), parsed_ints.next()) {
@@ -413,7 +419,7 @@ fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
     }
 }
 
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
 mod test {
     use super::*;
 
index cb249af4254083f57363afdc7f860cca846f6e49..525882c1e1ebb8134973b2c989474a0242da40e9 100644 (file)
@@ -311,8 +311,8 @@ pub unsafe fn current() -> Option<usize> {
 
     #[cfg(target_os = "macos")]
     pub unsafe fn current() -> Option<usize> {
-        Some((libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
-              libc::pthread_get_stacksize_np(libc::pthread_self())))
+        Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+             libc::pthread_get_stacksize_np(libc::pthread_self()))
     }
 
     #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
index c70b39995ebb0c45d3ae91a0c2959518baa79054..b841afe1a5141dfd2db749ad09077400c8cc1933 100644 (file)
@@ -166,27 +166,9 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     hints.ai_socktype = c::SOCK_STREAM;
     let mut res = ptr::null_mut();
     unsafe {
-        match cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)) {
-            Ok(_) => {
-                Ok(LookupHost { original: res, cur: res })
-            },
-            #[cfg(unix)]
-            Err(e) => {
-                // If we're running glibc prior to version 2.26, the lookup
-                // failure could be caused by caching a stale /etc/resolv.conf.
-                // We need to call libc::res_init() to clear the cache. But we
-                // shouldn't call it in on any other platform, because other
-                // res_init implementations aren't thread-safe. See
-                // https://github.com/rust-lang/rust/issues/41570 and
-                // https://github.com/rust-lang/rust/issues/43592.
-                use sys::net::res_init_if_glibc_before_2_26;
-                let _ = res_init_if_glibc_before_2_26();
-                Err(e)
-            },
-            // the cfg is needed here to avoid an "unreachable pattern" warning
-            #[cfg(not(unix))]
-            Err(e) => Err(e),
-        }
+        cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| {
+            LookupHost { original: res, cur: res }
+        })
     }
 }
 
index 9c0622e7bef9740a16b7112debd5d5ef6be14753..a64f1e9e4002cc098a9718e46c2000ec1ef5081c 100644 (file)
@@ -15,6 +15,7 @@
 pub use self::PathParameters::*;
 pub use symbol::{Ident, Symbol as Name};
 pub use util::ThinVec;
+pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
@@ -730,6 +731,7 @@ pub fn is_shift(&self) -> bool {
             _ => false
         }
     }
+
     pub fn is_comparison(&self) -> bool {
         use self::BinOpKind::*;
         match *self {
@@ -740,6 +742,7 @@ pub fn is_comparison(&self) -> bool {
             false,
         }
     }
+
     /// Returns `true` if the binary operator takes its arguments by value
     pub fn is_by_value(&self) -> bool {
         !self.is_comparison()
@@ -966,6 +969,49 @@ pub(super) fn to_ty(&self) -> Option<P<Ty>> {
 
         Some(P(Ty { node, id: self.id, span: self.span }))
     }
+
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.node {
+            ExprKind::Box(_) => ExprPrecedence::Box,
+            ExprKind::InPlace(..) => ExprPrecedence::InPlace,
+            ExprKind::Array(_) => ExprPrecedence::Array,
+            ExprKind::Call(..) => ExprPrecedence::Call,
+            ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
+            ExprKind::Tup(_) => ExprPrecedence::Tup,
+            ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node),
+            ExprKind::Unary(..) => ExprPrecedence::Unary,
+            ExprKind::Lit(_) => ExprPrecedence::Lit,
+            ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
+            ExprKind::If(..) => ExprPrecedence::If,
+            ExprKind::IfLet(..) => ExprPrecedence::IfLet,
+            ExprKind::While(..) => ExprPrecedence::While,
+            ExprKind::WhileLet(..) => ExprPrecedence::WhileLet,
+            ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
+            ExprKind::Loop(..) => ExprPrecedence::Loop,
+            ExprKind::Match(..) => ExprPrecedence::Match,
+            ExprKind::Closure(..) => ExprPrecedence::Closure,
+            ExprKind::Block(..) => ExprPrecedence::Block,
+            ExprKind::Catch(..) => ExprPrecedence::Catch,
+            ExprKind::Assign(..) => ExprPrecedence::Assign,
+            ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
+            ExprKind::Field(..) => ExprPrecedence::Field,
+            ExprKind::TupField(..) => ExprPrecedence::TupField,
+            ExprKind::Index(..) => ExprPrecedence::Index,
+            ExprKind::Range(..) => ExprPrecedence::Range,
+            ExprKind::Path(..) => ExprPrecedence::Path,
+            ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
+            ExprKind::Break(..) => ExprPrecedence::Break,
+            ExprKind::Continue(..) => ExprPrecedence::Continue,
+            ExprKind::Ret(..) => ExprPrecedence::Ret,
+            ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::Mac(..) => ExprPrecedence::Mac,
+            ExprKind::Struct(..) => ExprPrecedence::Struct,
+            ExprKind::Repeat(..) => ExprPrecedence::Repeat,
+            ExprKind::Paren(..) => ExprPrecedence::Paren,
+            ExprKind::Try(..) => ExprPrecedence::Try,
+            ExprKind::Yield(..) => ExprPrecedence::Yield,
+        }
+    }
 }
 
 impl fmt::Debug for Expr {
index 4291f811f3f74ba1e63b65e91bdbf0c9aaaa608a..d18d6f5e6bd0d8a9b05447c6aec2eee9ffded2b3 100644 (file)
@@ -992,7 +992,8 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute],
 /// Valid repr contents: any of the primitive integral type names (see
 /// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
 /// the same discriminant size that the corresponding C enum would or C
-/// structure layout, and `packed` to remove padding.
+/// structure layout, `packed` to remove padding, and `transparent` to elegate representation
+/// concerns to the only non-ZST field.
 pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr> {
     let mut acc = Vec::new();
     if attr.path == "repr" {
@@ -1011,6 +1012,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
                         "C" => Some(ReprC),
                         "packed" => Some(ReprPacked),
                         "simd" => Some(ReprSimd),
+                        "transparent" => Some(ReprTransparent),
                         _ => match int_type_of_word(word) {
                             Some(ity) => Some(ReprInt(ity)),
                             None => {
@@ -1082,6 +1084,7 @@ pub enum ReprAttr {
     ReprC,
     ReprPacked,
     ReprSimd,
+    ReprTransparent,
     ReprAlign(u32),
 }
 
index 0c4bcf4f6c7662fe4e7ae9e7a2a38cf47136d11c..ac5a10ec70364674bc46c5abf810ee108667ec88 100644 (file)
@@ -452,6 +452,9 @@ pub fn new() -> Features {
 
     // `extern` in paths
     (active, extern_in_paths, "1.23.0", Some(44660)),
+
+    // Allows `#[repr(transparent)]` attribute on newtype structs
+    (active, repr_transparent, "1.25.0", Some(43036)),
 );
 
 declare_features! (
@@ -1524,6 +1527,11 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                                "the struct `#[repr(align(u16))]` attribute \
                                                 is experimental");
                         }
+                        if item.check_name("transparent") {
+                            gate_feature_post!(&self, repr_transparent, attr.span,
+                                               "the `#[repr(transparent)]` attribute \
+                                               is experimental");
+                        }
                     }
                 }
             }
index 5374bf180f49a1172228dc1ac3d52b883638b438..ff065b57b8d0b45b557d30b00045f044795a989f 100644 (file)
@@ -1839,7 +1839,7 @@ fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
     }
 
     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) -> io::Result<()> {
-        let needs_par = parser::expr_precedence(expr) < prec;
+        let needs_par = expr.precedence().order() < prec;
         if needs_par {
             self.popen()?;
         }
index 6014ec5aa92a5b36daac1cbf5a6349ee31bcdc6a..86963c4000bd16c84e40a6c77a24e4f13b54b196 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 use parse::token::{Token, BinOpToken};
 use symbol::keywords;
-use ast::{self, BinOpKind, ExprKind};
+use ast::{self, BinOpKind};
+
+use std::cmp::Ordering;
 
 /// Associative operator with precedence.
 ///
@@ -228,66 +230,130 @@ pub fn to_ast_binop(&self) -> Option<BinOpKind> {
 pub const PREC_PAREN: i8 = 99;
 pub const PREC_FORCE_PAREN: i8 = 100;
 
-pub fn expr_precedence(expr: &ast::Expr) -> i8 {
-    match expr.node {
-        ExprKind::Closure(..) => PREC_CLOSURE,
-
-        ExprKind::Break(..) |
-        ExprKind::Continue(..) |
-        ExprKind::Ret(..) |
-        ExprKind::Yield(..) => PREC_JUMP,
-
-        // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to parse,
-        // instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence ensures that
-        // `pprust` will add parentheses in the right places to get the desired parse.
-        ExprKind::Range(..) => PREC_RANGE,
-
-        // Binop-like expr kinds, handled by `AssocOp`.
-        ExprKind::Binary(op, _, _) =>
-            AssocOp::from_ast_binop(op.node).precedence() as i8,
-
-        ExprKind::InPlace(..) => AssocOp::Inplace.precedence() as i8,
-        ExprKind::Cast(..) => AssocOp::As.precedence() as i8,
-        ExprKind::Type(..) => AssocOp::Colon.precedence() as i8,
-
-        ExprKind::Assign(..) |
-        ExprKind::AssignOp(..) => AssocOp::Assign.precedence() as i8,
-
-        // Unary, prefix
-        ExprKind::Box(..) |
-        ExprKind::AddrOf(..) |
-        ExprKind::Unary(..) => PREC_PREFIX,
-
-        // Unary, postfix
-        ExprKind::Call(..) |
-        ExprKind::MethodCall(..) |
-        ExprKind::Field(..) |
-        ExprKind::TupField(..) |
-        ExprKind::Index(..) |
-        ExprKind::Try(..) |
-        ExprKind::InlineAsm(..) |
-        ExprKind::Mac(..) => PREC_POSTFIX,
-
-        // Never need parens
-        ExprKind::Array(..) |
-        ExprKind::Repeat(..) |
-        ExprKind::Tup(..) |
-        ExprKind::Lit(..) |
-        ExprKind::Path(..) |
-        ExprKind::Paren(..) |
-        ExprKind::If(..) |
-        ExprKind::IfLet(..) |
-        ExprKind::While(..) |
-        ExprKind::WhileLet(..) |
-        ExprKind::ForLoop(..) |
-        ExprKind::Loop(..) |
-        ExprKind::Match(..) |
-        ExprKind::Block(..) |
-        ExprKind::Catch(..) |
-        ExprKind::Struct(..) => PREC_PAREN,
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ExprPrecedence {
+    Closure,
+    Break,
+    Continue,
+    Ret,
+    Yield,
+
+    Range,
+
+    Binary(BinOpKind),
+
+    InPlace,
+    Cast,
+    Type,
+
+    Assign,
+    AssignOp,
+
+    Box,
+    AddrOf,
+    Unary,
+
+    Call,
+    MethodCall,
+    Field,
+    TupField,
+    Index,
+    Try,
+    InlineAsm,
+    Mac,
+
+    Array,
+    Repeat,
+    Tup,
+    Lit,
+    Path,
+    Paren,
+    If,
+    IfLet,
+    While,
+    WhileLet,
+    ForLoop,
+    Loop,
+    Match,
+    Block,
+    Catch,
+    Struct,
+}
+
+impl PartialOrd for ExprPrecedence {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.order().cmp(&other.order()))
+    }
+}
+
+impl Ord for ExprPrecedence {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.order().cmp(&other.order())
     }
 }
 
+impl ExprPrecedence {
+    pub fn order(self) -> i8 {
+        match self {
+            ExprPrecedence::Closure => PREC_CLOSURE,
+
+            ExprPrecedence::Break |
+            ExprPrecedence::Continue |
+            ExprPrecedence::Ret |
+            ExprPrecedence::Yield => PREC_JUMP,
+
+            // `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
+            // parse, instead of parsing as `(x .. x) = x`.  Giving `Range` a lower precedence
+            // ensures that `pprust` will add parentheses in the right places to get the desired
+            // parse.
+            ExprPrecedence::Range => PREC_RANGE,
+
+            // Binop-like expr kinds, handled by `AssocOp`.
+            ExprPrecedence::Binary(op) => AssocOp::from_ast_binop(op).precedence() as i8,
+            ExprPrecedence::InPlace => AssocOp::Inplace.precedence() as i8,
+            ExprPrecedence::Cast => AssocOp::As.precedence() as i8,
+            ExprPrecedence::Type => AssocOp::Colon.precedence() as i8,
+
+            ExprPrecedence::Assign |
+            ExprPrecedence::AssignOp => AssocOp::Assign.precedence() as i8,
+
+            // Unary, prefix
+            ExprPrecedence::Box |
+            ExprPrecedence::AddrOf |
+            ExprPrecedence::Unary => PREC_PREFIX,
+
+            // Unary, postfix
+            ExprPrecedence::Call |
+            ExprPrecedence::MethodCall |
+            ExprPrecedence::Field |
+            ExprPrecedence::TupField |
+            ExprPrecedence::Index |
+            ExprPrecedence::Try |
+            ExprPrecedence::InlineAsm |
+            ExprPrecedence::Mac => PREC_POSTFIX,
+
+            // Never need parens
+            ExprPrecedence::Array |
+            ExprPrecedence::Repeat |
+            ExprPrecedence::Tup |
+            ExprPrecedence::Lit |
+            ExprPrecedence::Path |
+            ExprPrecedence::Paren |
+            ExprPrecedence::If |
+            ExprPrecedence::IfLet |
+            ExprPrecedence::While |
+            ExprPrecedence::WhileLet |
+            ExprPrecedence::ForLoop |
+            ExprPrecedence::Loop |
+            ExprPrecedence::Match |
+            ExprPrecedence::Block |
+            ExprPrecedence::Catch |
+            ExprPrecedence::Struct => PREC_PAREN,
+        }
+    }
+}
+
+
 /// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
 /// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
index 08a7f85d14b2f5be0b2b419825780bde38612a7e..3660d2fe46a92b0ff86c22a91627a484495fd6fa 100644 (file)
@@ -830,7 +830,9 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
     for a in type_attrs {
         for r in &attr::find_repr_attrs(diagnostic, a) {
             repr_type_name = match *r {
-                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) => continue,
+                attr::ReprPacked | attr::ReprSimd | attr::ReprAlign(_) | attr::ReprTransparent =>
+                    continue,
+
                 attr::ReprC => "i32",
 
                 attr::ReprInt(attr::SignedInt(ast::IntTy::Isize)) => "isize",
diff --git a/src/test/codegen/issue-47278.rs b/src/test/codegen/issue-47278.rs
new file mode 100644 (file)
index 0000000..21858b4
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 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.
+
+// -C no-prepopulate-passes
+#![crate_type="staticlib"]
+
+#[repr(C)]
+pub struct Foo(u64);
+
+// CHECK: define {{.*}} @foo(
+#[no_mangle]
+pub extern fn foo(_: Foo) -> Foo { loop {} }
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
new file mode 100644 (file)
index 0000000..2eeed2b
--- /dev/null
@@ -0,0 +1,53 @@
+// 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: -C no-prepopulate-passes
+
+// ignore-arm
+// ignore-mips
+// ignore-mips64
+// ignore-powerpc
+// ignore-powerpc64
+// See repr-transparent.rs
+
+#![crate_type="lib"]
+#![feature(repr_transparent)]
+
+
+#[repr(C)]
+pub struct Big([u32; 16]);
+
+#[repr(transparent)]
+pub struct BigW(Big);
+
+// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], %Big* [[BIG_ARG_ATTRS:.*]])
+#[no_mangle]
+pub extern fn test_Big(_: Big) -> Big { loop {} }
+
+// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], %BigW* [[BIG_ARG_ATTRS]])
+#[no_mangle]
+pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
+
+
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct BigUw(BigU);
+
+// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], %BigU* [[BIGU_ARG_ATTRS:.*]])
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], %BigUw* [[BIGU_ARG_ATTRS]])
+#[no_mangle]
+pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs
new file mode 100644 (file)
index 0000000..e637492
--- /dev/null
@@ -0,0 +1,54 @@
+// 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: -C no-prepopulate-passes
+
+// ignore-aarch64
+// ignore-asmjs
+// ignore-s390x
+// ignore-wasm
+// ignore-x86
+// ignore-x86_64
+// See repr-transparent.rs
+
+#![crate_type="lib"]
+#![feature(repr_transparent)]
+
+
+#[repr(C)]
+pub struct Big([u32; 16]);
+
+#[repr(transparent)]
+pub struct BigW(Big);
+
+// CHECK: define void @test_Big(%Big* [[BIG_RET_ATTRS:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_Big(_: Big) -> Big { loop {} }
+
+// CHECK: define void @test_BigW(%BigW* [[BIG_RET_ATTRS]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigW(_: BigW) -> BigW { loop {} }
+
+
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct BigUw(BigU);
+
+// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS:.*]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define void @test_BigUw(%BigUw* [[BIGU_RET_ATTRS]], [16 x i32]
+#[no_mangle]
+pub extern fn test_BigUw(_: BigUw) -> BigUw { loop {} }
diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs
new file mode 100644 (file)
index 0000000..31020d8
--- /dev/null
@@ -0,0 +1,177 @@
+// 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: -C no-prepopulate-passes
+
+#![crate_type="lib"]
+#![feature(repr_transparent, repr_simd)]
+
+use std::marker::PhantomData;
+
+pub struct Zst1;
+pub struct Zst2(());
+
+#[repr(transparent)]
+pub struct F32(f32);
+
+// CHECK: define float @test_F32(float %arg0)
+#[no_mangle]
+pub extern fn test_F32(_: F32) -> F32 { loop {} }
+
+#[repr(transparent)]
+pub struct Ptr(*mut u8);
+
+// CHECK: define i8* @test_Ptr(i8* %arg0)
+#[no_mangle]
+pub extern fn test_Ptr(_: Ptr) -> Ptr { loop {} }
+
+#[repr(transparent)]
+pub struct WithZst(u64, Zst1);
+
+// CHECK: define i64 @test_WithZst(i64 %arg0)
+#[no_mangle]
+pub extern fn test_WithZst(_: WithZst) -> WithZst { loop {} }
+
+#[repr(transparent)]
+pub struct WithZeroSizedArray(*const f32, [i8; 0]);
+
+// Apparently we use i32* when newtype-unwrapping f32 pointers. Whatever.
+// CHECK: define i32* @test_WithZeroSizedArray(i32* %arg0)
+#[no_mangle]
+pub extern fn test_WithZeroSizedArray(_: WithZeroSizedArray) -> WithZeroSizedArray { loop {} }
+
+#[repr(transparent)]
+pub struct Generic<T>(T);
+
+// CHECK: define double @test_Generic(double %arg0)
+#[no_mangle]
+pub extern fn test_Generic(_: Generic<f64>) -> Generic<f64> { loop {} }
+
+#[repr(transparent)]
+pub struct GenericPlusZst<T>(T, Zst2);
+
+#[repr(u8)]
+pub enum Bool { True, False, FileNotFound }
+
+// CHECK: define{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %arg0)
+#[no_mangle]
+pub extern fn test_Gpz(_: GenericPlusZst<Bool>) -> GenericPlusZst<Bool> { loop {} }
+
+#[repr(transparent)]
+pub struct LifetimePhantom<'a, T: 'a>(*const T, PhantomData<&'a T>);
+
+// CHECK: define i16* @test_LifetimePhantom(i16* %arg0)
+#[no_mangle]
+pub extern fn test_LifetimePhantom(_: LifetimePhantom<i16>) -> LifetimePhantom<i16> { loop {} }
+
+// This works despite current alignment resrictions because PhantomData is always align(1)
+#[repr(transparent)]
+pub struct UnitPhantom<T, U> { val: T, unit: PhantomData<U> }
+
+pub struct Px;
+
+// CHECK: define float @test_UnitPhantom(float %arg0)
+#[no_mangle]
+pub extern fn test_UnitPhantom(_: UnitPhantom<f32, Px>) -> UnitPhantom<f32, Px> { loop {} }
+
+#[repr(transparent)]
+pub struct TwoZsts(Zst1, i8, Zst2);
+
+// CHECK: define{{( signext)?}} i8 @test_TwoZsts(i8{{( signext)?}} %arg0)
+#[no_mangle]
+pub extern fn test_TwoZsts(_: TwoZsts) -> TwoZsts { loop {} }
+
+#[repr(transparent)]
+pub struct Nested1(Zst2, Generic<f64>);
+
+// CHECK: define double @test_Nested1(double %arg0)
+#[no_mangle]
+pub extern fn test_Nested1(_: Nested1) -> Nested1 { loop {} }
+
+#[repr(transparent)]
+pub struct Nested2(Nested1, Zst1);
+
+// CHECK: define double @test_Nested2(double %arg0)
+#[no_mangle]
+pub extern fn test_Nested2(_: Nested2) -> Nested2 { loop {} }
+
+#[repr(simd)]
+struct f32x4(f32, f32, f32, f32);
+
+#[repr(transparent)]
+pub struct Vector(f32x4);
+
+// CHECK: define <4 x float> @test_Vector(<4 x float> %arg0)
+#[no_mangle]
+pub extern fn test_Vector(_: Vector) -> Vector { loop {} }
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(<f32 as Mirror>::It);
+
+// CHECK: define float @test_Projection(float %arg0)
+#[no_mangle]
+pub extern fn test_Projection(_: StructWithProjection) -> StructWithProjection { loop {} }
+
+
+// The rest of this file tests newtypes around small aggregates on an ABI where small aggregates are
+// packed into one register. This is ABI-dependent, so instead we focus on one ABI and supply a
+// dummy definition for other ABIs to keep FileCheck happy.
+//
+// Bigger aggregates are tested in separate files called repr-transparent-aggregate-*.rs because
+// there, the expected LLVM IR function signatures vary so much that it's not reasonably possible to
+// cover all of them with a single CHECK line. Instead we group ABIs by the general "shape" of the
+// signature and have a separate test file for each bin.
+//
+// PS: You may be wondering why we don't just compare the return types and argument types for
+// equality with FileCheck regex captures. Well, rustc doesn't perform newtype unwrapping on
+// newtypes containing aggregates. This is OK on all ABIs we support, but because LLVM has not
+// gotten rid of pointee types yet, the IR function signature will be syntactically different (%Foo*
+// vs %FooWrapper*).
+
+#[repr(C)]
+pub struct Rgb8 { r: u8, g: u8, b: u8 }
+
+#[repr(transparent)]
+pub struct Rgb8Wrap(Rgb8);
+
+// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
+// CHECK: define i32 @test_Rgb8Wrap(i32
+#[no_mangle]
+#[cfg(all(target_arch="x86_64", target_os="linux"))]
+pub extern fn test_Rgb8Wrap(_: Rgb8Wrap) -> Rgb8Wrap { loop {} }
+
+#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
+#[no_mangle]
+pub extern fn test_Rgb8Wrap(_: u32) -> u32 { loop {} }
+
+// Same as with the small struct above: ABI-dependent, we only test the interesting case
+// (ABIs that pack the aggregate into a scalar) and stub it out on other ABIs
+
+#[repr(C)]
+pub union FloatBits {
+    float: f32,
+    bits: u32,
+}
+
+#[repr(transparent)]
+pub struct SmallUnion(FloatBits);
+
+// NB: closing parenthesis is missing because sometimes the argument has a name and sometimes not
+// CHECK: define i32 @test_SmallUnion(i32
+#[no_mangle]
+#[cfg(all(target_arch="x86_64", target_os="linux"))]
+pub extern fn test_SmallUnion(_: SmallUnion) -> SmallUnion { loop {} }
+
+#[cfg(not(all(target_arch="x86_64", target_os="linux")))]
+#[no_mangle]
+pub extern fn test_SmallUnion(_: u32) -> u32 { loop {} }
index be54c3754ea1fe98e7aef7f4aaef686d8282f629..0cd3d00a735767608e015f85205229c0e85c8669 100644 (file)
@@ -9,14 +9,16 @@
 // except according to those terms.
 
 trait Foo {
-    fn foo(); //~ trait declared without `&self`
+    fn foo();
+    //~^ NOTE trait method declared without `&self`
 }
 
 struct Bar;
 
 impl Foo for Bar {
-    fn foo(&self) {} //~ ERROR E0185
-    //~^ `&self` used in impl
+    fn foo(&self) {}
+    //~^ ERROR E0185
+    //~| NOTE `&self` used in impl
 }
 
 fn main() {
index f28ac200dea5a29fe6be2ec6fafb8e8028fb4729..f46bdb9980142fce754a261e94ba91ff00e96216 100644 (file)
@@ -13,7 +13,9 @@ enum X {
 }
 
 fn main() {
-    X::Entry(); //~ ERROR expected function, found `X::Entry` [E0618]
+    X::Entry();
+    //~^ ERROR expected function, found enum variant `X::Entry` [E0618]
     let x = 0i32;
-    x(); //~ ERROR expected function, found `i32` [E0618]
+    x();
+    //~^ ERROR expected function, found `i32` [E0618]
 }
diff --git a/src/test/compile-fail/E0659.rs b/src/test/compile-fail/E0659.rs
new file mode 100644 (file)
index 0000000..4bd452b
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 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 moon {
+    pub fn foo() {}
+}
+
+mod earth {
+    pub fn foo() {}
+}
+
+mod collider {
+    pub use moon::*;
+    pub use earth::*;
+}
+
+fn main() {
+    collider::foo(); //~ ERROR E0659
+}
diff --git a/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs b/src/test/compile-fail/closure-expected-type/expect-region-supply-region.rs
deleted file mode 100644 (file)
index 9da12dc..0000000
+++ /dev/null
@@ -1,80 +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.
-
-#![allow(warnings)]
-
-fn closure_expecting_bound<F>(_: F)
-    where F: FnOnce(&u32)
-{
-}
-
-fn closure_expecting_free<'a, F>(_: F)
-    where F: FnOnce(&'a u32)
-{
-}
-
-fn expect_bound_supply_nothing() {
-    // Because `x` is inferred to have a bound region, we cannot allow
-    // it to escape into `f`:
-    let mut f: Option<&u32> = None;
-    closure_expecting_bound(|x| {
-        f = Some(x); //~ ERROR E0495
-    });
-}
-
-fn expect_bound_supply_bound() {
-    // Because `x` is inferred to have a bound region, we cannot allow
-    // it to escape into `f`, even with an explicit type annotation on
-    // closure:
-    let mut f: Option<&u32> = None;
-    closure_expecting_bound(|x: &u32| {
-        f = Some(x); //~ ERROR E0495
-    });
-}
-
-fn expect_bound_supply_named<'x>() {
-    let mut f: Option<&u32> = None;
-
-    // Here we give a type annotation that `x` should be free. We get
-    // an error because of that.
-    closure_expecting_bound(|x: &'x u32| {
-        //~^ ERROR mismatched types
-        //~| ERROR mismatched types
-
-        // And we still cannot let `x` escape into `f`.
-        f = Some(x);
-        //~^ ERROR cannot infer
-    });
-}
-
-fn expect_free_supply_nothing() {
-    let mut f: Option<&u32> = None;
-    closure_expecting_free(|x| f = Some(x)); // OK
-}
-
-fn expect_free_supply_bound() {
-    let mut f: Option<&u32> = None;
-
-    // Here, even though the annotation `&u32` could be seen as being
-    // bound in the closure, we permit it to be defined as a free
-    // region (which is inferred to something in the fn body).
-    closure_expecting_free(|x: &u32| f = Some(x)); // OK
-}
-
-fn expect_free_supply_named<'x>() {
-    let mut f: Option<&u32> = None;
-
-    // Here, even though the annotation `&u32` could be seen as being
-    // bound in the closure, we permit it to be defined as a free
-    // region (which is inferred to something in the fn body).
-    closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
-}
-
-fn main() { }
diff --git a/src/test/compile-fail/issue-7573.rs b/src/test/compile-fail/issue-7573.rs
deleted file mode 100644 (file)
index d13da1d..0000000
+++ /dev/null
@@ -1,49 +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.
-
-
-pub struct CrateId {
-    local_path: String,
-    junk: String
-}
-
-impl CrateId {
-    fn new(s: &str) -> CrateId {
-        CrateId {
-            local_path: s.to_string(),
-            junk: "wutevs".to_string()
-        }
-    }
-}
-
-pub fn remove_package_from_database() {
-    let mut lines_to_use: Vec<&CrateId> = Vec::new(); //~ ERROR E0495
-    let push_id = |installed_id: &CrateId| {
-        lines_to_use.push(installed_id);
-    };
-    list_database(push_id);
-
-    for l in &lines_to_use {
-        println!("{}", l.local_path);
-    }
-
-}
-
-pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
-    let stuff = ["foo", "bar"];
-
-    for l in &stuff {
-        f(&CrateId::new(*l));
-    }
-}
-
-pub fn main() {
-    remove_package_from_database();
-}
index fd825563eba197cb10960ec650f4030ce4688a8f..c22239dee0a80868c82144338eb9d6dd817ba3ee 100644 (file)
@@ -9,10 +9,12 @@
 // except according to those terms.
 
 #![deny(improper_ctypes)]
-#![feature(libc, i128_type)]
+#![feature(libc, i128_type, repr_transparent)]
 
 extern crate libc;
 
+use std::marker::PhantomData;
+
 trait Mirror { type It: ?Sized; }
 impl<T: ?Sized> Mirror for T { type It = Self; }
 #[repr(C)]
@@ -28,6 +30,22 @@ pub struct StructWithProjectionAndLifetime<'a>(
 pub type RustBadRet = extern fn() -> Box<u32>;
 pub type CVoidRet = ();
 pub struct Foo;
+#[repr(transparent)]
+pub struct TransparentI128(i128);
+#[repr(transparent)]
+pub struct TransparentStr(&'static str);
+#[repr(transparent)]
+pub struct TransparentBadFn(RustBadRet);
+#[repr(transparent)]
+pub struct TransparentInt(u32);
+#[repr(transparent)]
+pub struct TransparentRef<'a>(&'a TransparentInt);
+#[repr(transparent)]
+pub struct TransparentLifetime<'a>(*const u8, PhantomData<&'a ()>);
+#[repr(transparent)]
+pub struct TransparentUnit<U>(f32, PhantomData<U>);
+#[repr(transparent)]
+pub struct TransparentCustomZst(i32, ZeroSize);
 
 #[repr(C)]
 pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
@@ -51,6 +69,9 @@ pub fn zero_size_phantom_toplevel()
     pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
     pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
     pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without
+    pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128`
+    pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str`
+    pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without
 
     pub fn good3(fptr: Option<extern fn()>);
     pub fn good4(aptr: &[u8; 4 as usize]);
@@ -62,6 +83,11 @@ pub fn zero_size_phantom_toplevel()
     pub fn good10() -> CVoidRet;
     pub fn good11(size: isize);
     pub fn good12(size: usize);
+    pub fn good13(n: TransparentInt);
+    pub fn good14(p: TransparentRef);
+    pub fn good15(p: TransparentLifetime);
+    pub fn good16(p: TransparentUnit<ZeroSize>);
+    pub fn good17(p: TransparentCustomZst);
 }
 
 #[cfg(not(target_arch = "wasm32"))]
index b5eac73a55d1c84fe3056da1fc8bb6751a64b0b8..7cd0a6bbf0fd0ec4fdb9082553bcb0d1e85bcbb7 100644 (file)
 #[derive(Eq, PartialEq)]
 struct X { y: bool }
 impl X {
-    fn foo(&self) -> bool { self.y }
+    fn foo(&self, conjunct: bool) -> bool { self.y && conjunct }
 }
 
 fn foo() -> isize {
     return (1); //~ ERROR unnecessary parentheses around `return` value
 }
-fn bar() -> X {
-    return (X { y: true }); //~ ERROR unnecessary parentheses around `return` value
+fn bar(y: bool) -> X {
+    return (X { y }); //~ ERROR unnecessary parentheses around `return` value
 }
 
 fn main() {
     foo();
-    bar();
+    bar((true)); //~ ERROR unnecessary parentheses around function argument
 
     if (true) {} //~ ERROR unnecessary parentheses around `if` condition
     while (true) {} //~ ERROR unnecessary parentheses around `while` condition
@@ -40,13 +40,15 @@ fn main() {
     if (X { y: true } == v) {}
     if (X { y: false }.y) {}
 
-    while (X { y: false }.foo()) {}
+    while (X { y: false }.foo(true)) {}
     while (true | X { y: false }.y) {}
 
     match (X { y: false }) {
         _ => {}
     }
 
+    X { y: false }.foo((true)); //~ ERROR unnecessary parentheses around method argument
+
     let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a = (0); //~ ERROR unnecessary parentheses around assigned value
     _a += (1); //~ ERROR unnecessary parentheses around assigned value
diff --git a/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs b/src/test/compile-fail/nll/constant-thread-locals-issue-47053.rs
new file mode 100644 (file)
index 0000000..c7dc84c
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #47053
+
+#![feature(nll)]
+#![feature(thread_local)]
+
+#[thread_local]
+static FOO: isize = 5;
+
+fn main() {
+    FOO = 6; //~ ERROR cannot assign to immutable item `FOO` [E0594]
+}
diff --git a/src/test/compile-fail/regions-escape-bound-fn-2.rs b/src/test/compile-fail/regions-escape-bound-fn-2.rs
deleted file mode 100644 (file)
index 1329d05..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.
-
-fn with_int<F>(f: F) where F: FnOnce(&isize) {
-    let x = 3;
-    f(&x);
-}
-
-fn main() {
-    let mut x = None;
-    with_int(|y| x = Some(y));
-         //~^ ERROR cannot infer
-}
diff --git a/src/test/compile-fail/regions-escape-bound-fn.rs b/src/test/compile-fail/regions-escape-bound-fn.rs
deleted file mode 100644 (file)
index 02e62ff..0000000
+++ /dev/null
@@ -1,19 +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 with_int<F>(f: F) where F: FnOnce(&isize) {
-    let x = 3;
-    f(&x);
-}
-
-fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(|y| x = Some(y));   //~ ERROR cannot infer
-}
diff --git a/src/test/compile-fail/regions-escape-unboxed-closure.rs b/src/test/compile-fail/regions-escape-unboxed-closure.rs
deleted file mode 100644 (file)
index cf41fad..0000000
+++ /dev/null
@@ -1,17 +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 with_int(f: &mut FnMut(&isize)) {
-}
-
-fn main() {
-    let mut x: Option<&isize> = None;
-    with_int(&mut |y| x = Some(y));   //~ ERROR cannot infer
-}
diff --git a/src/test/compile-fail/repr-transparent-other-items.rs b/src/test/compile-fail/repr-transparent-other-items.rs
new file mode 100644 (file)
index 0000000..cf08708
--- /dev/null
@@ -0,0 +1,40 @@
+// 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(repr_transparent)]
+
+// See also repr-transparent.rs
+
+#[repr(transparent)] //~ ERROR unsupported representation for zero-variant enum
+enum Void {}         //~| ERROR should be applied to struct
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum FieldlessEnum {
+    Foo,
+    Bar,
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+enum Enum {
+    Foo(String),
+    Bar(u32),
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+union Foo {
+    u: u32,
+    s: i32
+}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+fn cant_repr_this() {}
+
+#[repr(transparent)] //~ ERROR should be applied to struct
+static CANT_REPR_THIS: u32 = 0;
diff --git a/src/test/compile-fail/repr-transparent-other-reprs.rs b/src/test/compile-fail/repr-transparent-other-reprs.rs
new file mode 100644 (file)
index 0000000..7b91a6f
--- /dev/null
@@ -0,0 +1,28 @@
+// 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(repr_transparent, repr_align, attr_literals)]
+
+// See also repr-transparent.rs
+
+#[repr(transparent, C)] //~ ERROR cannot have other repr
+struct TransparentPlusC {
+    ptr: *const u8
+}
+
+#[repr(transparent, packed)] //~ ERROR cannot have other repr
+struct TransparentPlusPacked(*const u8);
+
+#[repr(transparent, align(2))] //~ ERROR cannot have other repr
+struct TransparentPlusAlign(u8);
+
+#[repr(transparent)] //~ ERROR cannot have other repr
+#[repr(C)]
+struct SeparateAttributes(*mut u8);
diff --git a/src/test/compile-fail/repr-transparent.rs b/src/test/compile-fail/repr-transparent.rs
new file mode 100644 (file)
index 0000000..b5e6a0f
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+// This file tests repr(transparent)-related errors reported during typeck. Other errors
+// that are reported earlier and therefore preempt these are tested in:
+// - repr-transparent-other-reprs.rs
+// - repr-transparent-other-items.rs
+
+#![feature(repr_align, attr_literals)]
+#![feature(repr_transparent)]
+
+use std::marker::PhantomData;
+
+#[repr(transparent)]
+struct NoFields; //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZst(()); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsOnlyZstArray([bool; 0]); //~ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct ContainsMultipleZst(PhantomData<*const i32>, NoFields);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct MultipleNonZst(u8, u8); //~ ERROR needs exactly one non-zero-sized field
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+
+#[repr(transparent)]
+pub struct StructWithProjection(f32, <f32 as Mirror>::It);
+//~^ ERROR needs exactly one non-zero-sized field
+
+#[repr(transparent)]
+struct NontrivialAlignZst(u32, [u16; 0]); //~ ERROR alignment larger than 1
+
+#[repr(align(32))]
+struct ZstAlign32<T>(PhantomData<T>);
+
+#[repr(transparent)]
+struct GenericAlign<T>(ZstAlign32<T>, u32); //~ ERROR alignment larger than 1
diff --git a/src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs b/src/test/incremental-fulldeps/auxiliary/incremental_proc_macro_aux.rs
new file mode 100644 (file)
index 0000000..e9f9ba8
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+// Add a function to shift DefIndex of registrar function
+#[cfg(cfail2)]
+fn foo() {}
+
+#[proc_macro_derive(IncrementalMacro)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    #[cfg(cfail2)]
+    {
+        foo();
+    }
+
+    "".parse().unwrap()
+}
diff --git a/src/test/incremental-fulldeps/incremental_proc_macro.rs b/src/test/incremental-fulldeps/incremental_proc_macro.rs
new file mode 100644 (file)
index 0000000..e434507
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:incremental_proc_macro_aux.rs
+// ignore-stage1
+// revisions: cfail1 cfail2
+// must-compile-successfully
+
+// This test makes sure that we still find the proc-macro registrar function
+// when we compile proc-macros incrementally (see #47292).
+
+#![crate_type = "rlib"]
+
+#[macro_use]
+extern crate incremental_proc_macro_aux;
+
+#[derive(IncrementalMacro)]
+pub struct Foo {
+    x: u32
+}
diff --git a/src/test/run-make/hotplug_codegen_backend/Makefile b/src/test/run-make/hotplug_codegen_backend/Makefile
new file mode 100644 (file)
index 0000000..9a216d1
--- /dev/null
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+all:
+       /bin/echo || exit 0 # This test requires /bin/echo to exist
+       $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \
+               -o $(TMPDIR)/the_backend.dylib
+       $(RUSTC) some_crate.rs --crate-name some_crate --crate-type bin -o $(TMPDIR)/some_crate \
+               -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options
+       grep -x "This has been \"compiled\" succesfully." $(TMPDIR)/some_crate
diff --git a/src/test/run-make/hotplug_codegen_backend/some_crate.rs b/src/test/run-make/hotplug_codegen_backend/some_crate.rs
new file mode 100644 (file)
index 0000000..26ffce0
--- /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() {
+    ::std::process::exit(1);
+}
diff --git a/src/test/run-make/hotplug_codegen_backend/the_backend.rs b/src/test/run-make/hotplug_codegen_backend/the_backend.rs
new file mode 100644 (file)
index 0000000..0de404e
--- /dev/null
@@ -0,0 +1,82 @@
+// 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(rustc_private)]
+
+extern crate syntax;
+extern crate rustc;
+extern crate rustc_trans_utils;
+
+use std::any::Any;
+use std::sync::mpsc;
+use syntax::symbol::Symbol;
+use rustc::session::{Session, CompileIncomplete};
+use rustc::session::config::OutputFilenames;
+use rustc::ty::TyCtxt;
+use rustc::ty::maps::Providers;
+use rustc::middle::cstore::MetadataLoader;
+use rustc::dep_graph::DepGraph;
+use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate};
+
+struct TheBackend(Box<TransCrate>);
+
+impl TransCrate for TheBackend {
+    fn metadata_loader(&self) -> Box<MetadataLoader> {
+        self.0.metadata_loader()
+    }
+
+    fn provide(&self, providers: &mut Providers) {
+        self.0.provide(providers);
+    }
+
+    fn provide_extern(&self, providers: &mut Providers) {
+        self.0.provide_extern(providers);
+    }
+
+    fn trans_crate<'a, 'tcx>(
+        &self,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        _rx: mpsc::Receiver<Box<Any + Send>>
+    ) -> Box<Any> {
+        use rustc::hir::def_id::LOCAL_CRATE;
+
+        Box::new(tcx.crate_name(LOCAL_CRATE) as Symbol)
+    }
+
+    fn join_trans_and_link(
+        &self,
+        trans: Box<Any>,
+        sess: &Session,
+        _dep_graph: &DepGraph,
+        outputs: &OutputFilenames,
+    ) -> Result<(), CompileIncomplete> {
+        use std::io::Write;
+        use rustc::session::config::CrateType;
+        use rustc_trans_utils::link::out_filename;
+        let crate_name = trans.downcast::<Symbol>()
+            .expect("in join_trans_and_link: trans is not a Symbol");
+        for &crate_type in sess.opts.crate_types.iter() {
+            if crate_type != CrateType::CrateTypeExecutable {
+                sess.fatal(&format!("Crate type is {:?}", crate_type));
+            }
+            let output_name =
+                out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+            let mut out_file = ::std::fs::File::create(output_name).unwrap();
+            write!(out_file, "This has been \"compiled\" succesfully.").unwrap();
+        }
+        Ok(())
+    }
+}
+
+/// This is the entrypoint for a hot plugged rustc_trans
+#[no_mangle]
+pub fn __rustc_codegen_backend(sess: &Session) -> Box<TransCrate> {
+    Box::new(TheBackend(MetadataOnlyTransCrate::new(sess)))
+}
index f0ab1d5dc0fec7eabec80afd1a2bb6c1c907e803..c360dde618ef54f2f2a7167c0081f4643a505716 100644 (file)
@@ -16,6 +16,7 @@
 extern crate rustc_metadata;
 extern crate rustc_errors;
 extern crate rustc_trans;
+extern crate rustc_trans_utils;
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
@@ -25,6 +26,7 @@
 use rustc_metadata::cstore::CStore;
 use rustc_errors::registry::Registry;
 use syntax::codemap::FileName;
+use rustc_trans_utils::trans_crate::TransCrate;
 
 use std::path::PathBuf;
 use std::rc::Rc;
@@ -51,7 +53,7 @@ fn main() {}
     compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
 }
 
-fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
+fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<TransCrate>) {
     let mut opts = basic_options();
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
@@ -60,16 +62,26 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
     }
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
-    let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
     let sess = build_session(opts, None, descriptions);
-    rustc_trans::init(&sess);
+    let trans = rustc_trans::LlvmTransCrate::new(&sess);
+    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-    (sess, cstore)
+    (sess, cstore, trans)
 }
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
-    let (sess, cstore) = basic_sess(sysroot);
+    let (sess, cstore, trans) = basic_sess(sysroot);
     let control = CompileController::basic();
     let input = Input::Str { name: FileName::Anon, input: code };
-    let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control);
+    let _ = compile_input(
+        trans,
+        &sess,
+        &cstore,
+        &None,
+        &input,
+        &None,
+        &Some(output),
+        None,
+        &control
+    );
 }
diff --git a/src/test/run-make/llvm-phase/Makefile b/src/test/run-make/llvm-phase/Makefile
deleted file mode 100644 (file)
index 6a8e172..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
--include ../tools.mk
-
-all:
-       $(RUSTC) test.rs
-       $(call RUN,test $(RUSTC))
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
deleted file mode 100644 (file)
index 2ff4593..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(plugin, rustc_private, box_syntax)]
-
-extern crate rustc;
-extern crate rustc_driver;
-extern crate rustc_llvm;
-extern crate rustc_trans;
-#[macro_use] extern crate syntax;
-extern crate getopts;
-
-use rustc_driver::{CompilerCalls, Compilation};
-use rustc_driver::driver::CompileController;
-use rustc_trans::ModuleSource;
-use rustc::session::Session;
-use syntax::codemap::FileLoader;
-use std::env;
-use std::io;
-use std::path::{PathBuf, Path};
-
-struct JitLoader;
-
-impl FileLoader for JitLoader {
-    fn file_exists(&self, _: &Path) -> bool { true }
-    fn abs_path(&self, _: &Path) -> Option<PathBuf> { None }
-    fn read_file(&self, _: &Path) -> io::Result<String> {
-        Ok(r#"
-#[no_mangle]
-pub fn test_add(a: i32, b: i32) -> i32 { a + b }
-"#.to_string())
-    }
-}
-
-#[derive(Copy, Clone)]
-struct JitCalls;
-
-impl<'a> CompilerCalls<'a> for JitCalls {
-    fn build_controller(&mut self,
-                        _: &Session,
-                        _: &getopts::Matches)
-                        -> CompileController<'a> {
-        let mut cc = CompileController::basic();
-        cc.after_llvm.stop = Compilation::Stop;
-        cc.after_llvm.run_callback_on_error = true;
-        cc.after_llvm.callback = Box::new(|state| {
-            state.session.abort_if_errors();
-            let trans = state.trans.unwrap();
-            assert_eq!(trans.modules.len(), 1);
-            println!("name of compiled module = {}", trans.modules[0].name);
-        });
-        cc
-    }
-}
-
-fn main() {
-    use rustc_driver;
-
-    let mut path = match std::env::args().nth(2) {
-        Some(path) => PathBuf::from(&path),
-        None => panic!("missing rustc path")
-    };
-
-    // Remove two segments from rustc path to get sysroot.
-    path.pop();
-    path.pop();
-
-    let mut args: Vec<String> =
-        format!("_ _ --sysroot {} --crate-type dylib", path.to_str().unwrap())
-        .split(' ').map(|s| s.to_string()).collect();
-    args.push("--out-dir".to_string());
-    args.push(env::var("TMPDIR").unwrap());
-    args.push("-Ccodegen-units=1".to_string());
-
-    let (result, _) = rustc_driver::run_compiler(
-        &args, &mut JitCalls, Some(box JitLoader), None);
-    if let Err(n) = result {
-        panic!("Error {:?}", n);
-    }
-}
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile b/src/test/run-make/long-linker-command-lines-cmd-exe/Makefile
new file mode 100644 (file)
index 0000000..debe9e9
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) foo.rs -g
+       cp foo.bat $(TMPDIR)/
+       OUT_DIR="$(TMPDIR)" RUSTC="$(RUSTC_ORIGINAL)" $(call RUN,foo)
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.bat
new file mode 100644 (file)
index 0000000..a9350f1
--- /dev/null
@@ -0,0 +1 @@
+%MY_LINKER% %*
diff --git a/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs b/src/test/run-make/long-linker-command-lines-cmd-exe/foo.rs
new file mode 100644 (file)
index 0000000..f9168a8
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2018 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.
+
+// Like the `long-linker-command-lines` test this test attempts to blow
+// a command line limit for running the linker. Unlike that test, however,
+// this test is testing `cmd.exe` specifically rather than the OS.
+//
+// Unfortunately `cmd.exe` has a 8192 limit which is relatively small
+// in the grand scheme of things and anyone sripting rustc's linker
+// is probably using a `*.bat` script and is likely to hit this limit.
+//
+// This test uses a `foo.bat` script as the linker which just simply
+// delegates back to this program. The compiler should use a lower
+// limit for arguments before passing everything via `@`, which
+// means that everything should still succeed here.
+
+use std::env;
+use std::fs::{self, File};
+use std::io::{BufWriter, Write, Read};
+use std::path::PathBuf;
+use std::process::Command;
+
+fn main() {
+    if !cfg!(windows) {
+        return
+    }
+
+    let tmpdir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
+    let ok = tmpdir.join("ok");
+    let not_ok = tmpdir.join("not_ok");
+    if env::var("YOU_ARE_A_LINKER").is_ok() {
+        match env::args().find(|a| a.contains("@")) {
+            Some(file) => { fs::copy(&file[1..], &ok).unwrap(); }
+            None => { File::create(&not_ok).unwrap(); }
+        }
+        return
+    }
+
+    let rustc = env::var_os("RUSTC").unwrap_or("rustc".into());
+    let me = env::current_exe().unwrap();
+    let bat = me.parent()
+        .unwrap()
+        .join("foo.bat");
+    let bat_linker = format!("linker={}", bat.display());
+    for i in (1..).map(|i| i * 10) {
+        println!("attempt: {}", i);
+
+        let file = tmpdir.join("bar.rs");
+        let mut f = BufWriter::new(File::create(&file).unwrap());
+        let mut lib_name = String::new();
+        for _ in 0..i {
+            lib_name.push_str("foo");
+        }
+        for j in 0..i {
+            writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap();
+        }
+        writeln!(f, "extern {{}}\nfn main() {{}}").unwrap();
+        f.into_inner().unwrap();
+
+        drop(fs::remove_file(&ok));
+        drop(fs::remove_file(&not_ok));
+        let status = Command::new(&rustc)
+            .arg(&file)
+            .arg("-C").arg(&bat_linker)
+            .arg("--out-dir").arg(&tmpdir)
+            .env("YOU_ARE_A_LINKER", "1")
+            .env("MY_LINKER", &me)
+            .status()
+            .unwrap();
+
+        if !status.success() {
+            panic!("rustc didn't succeed: {}", status);
+        }
+
+        if !ok.exists() {
+            assert!(not_ok.exists());
+            continue
+        }
+
+        let mut contents = String::new();
+        File::open(&ok).unwrap().read_to_string(&mut contents).unwrap();
+
+        for j in 0..i {
+            assert!(contents.contains(&format!("{}{}", lib_name, j)));
+        }
+
+        break
+    }
+}
index b5c1ee099037cac9ea64d425cd5b8d710906f6f2..85aa92ce26076059b10fd46ba0e80d0581f56db6 100644 (file)
@@ -18,6 +18,7 @@
 extern crate getopts;
 extern crate rustc;
 extern crate rustc_driver;
+extern crate rustc_trans_utils;
 extern crate syntax;
 extern crate rustc_errors as errors;
 
@@ -25,6 +26,7 @@
 use rustc::session::Session;
 use rustc::session::config::{self, Input};
 use rustc_driver::{driver, CompilerCalls, Compilation};
+use rustc_trans_utils::trans_crate::TransCrate;
 use syntax::ast;
 
 use std::path::PathBuf;
@@ -46,6 +48,7 @@ fn early_callback(&mut self,
     }
 
     fn late_callback(&mut self,
+                     _: &TransCrate,
                      _: &getopts::Matches,
                      _: &Session,
                      _: &CrateStore,
index 712fa2d6001774b23ddb64226629f413f4682443..eaa5bc90805768e7643c8725eb6bd291b87bd78b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(allocator_api, unique)]
+#![feature(allocator_api, nonnull)]
 
 use std::heap::{Heap, Alloc};
 
index 5ea4b1fe93c8024684954d1995173b6221426aa1..7e8a0d1e2b925de0641fd6c0ae550e83b0560e4e 100644 (file)
@@ -8,6 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// revisions:lexical nll
+#![cfg_attr(nll, feature(nll))]
+
 #![feature(generators)]
 
 fn bar<'a>() {
index aa13d6fad47c9f188bf4e855438559467caa99ec..7af732f561deb5d68cbdb6fb7d3eb2e5b4b1ef9e 100644 (file)
 
 // Don't fail if we encounter a NonZero<*T> where T is an unsized type
 
-#![feature(unique)]
-
-use std::ptr::Unique;
+use std::ptr::NonNull;
 
 fn main() {
     let mut a = [0u8; 5];
-    let b: Option<Unique<[u8]>> = Some(Unique::from(&mut a));
+    let b: Option<NonNull<[u8]>> = Some(NonNull::from(&mut a));
     match b {
         Some(_) => println!("Got `Some`"),
         None => panic!("Unexpected `None`"),
diff --git a/src/test/run-pass/issue-46920-byte-array-patterns.rs b/src/test/run-pass/issue-46920-byte-array-patterns.rs
new file mode 100644 (file)
index 0000000..236f699
--- /dev/null
@@ -0,0 +1,37 @@
+// 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.
+
+const CURSOR_PARTITION_LABEL: &'static [u8] = b"partition";
+const CURSOR_EVENT_TYPE_LABEL: &'static [u8] = b"event_type";
+const BYTE_PATTERN: &'static [u8; 5] = b"hello";
+
+fn match_slice(x: &[u8]) -> u32 {
+    match x {
+        CURSOR_PARTITION_LABEL => 0,
+        CURSOR_EVENT_TYPE_LABEL => 1,
+        _ => 2,
+    }
+}
+
+fn match_array(x: &[u8; 5]) -> bool {
+    match x {
+        BYTE_PATTERN => true,
+        _ => false
+    }
+}
+
+fn main() {
+    assert_eq!(match_slice(b"abcde"), 2);
+    assert_eq!(match_slice(b"event_type"), 1);
+    assert_eq!(match_slice(b"partition"), 0);
+
+    assert_eq!(match_array(b"hello"), true);
+    assert_eq!(match_array(b"hella"), false);
+}
diff --git a/src/test/run-pass/issue-46964.rs b/src/test/run-pass/issue-46964.rs
new file mode 100644 (file)
index 0000000..2a82c6d
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+mod my_mod {
+    #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash)]
+    pub struct Name<'a> {
+        source: &'a str,
+    }
+
+    pub const JSON: Name = Name { source: "JSON" };
+}
+
+pub fn crash() -> bool {
+  match (my_mod::JSON, None) {
+    (_, Some(my_mod::JSON)) => true,
+    (my_mod::JSON, None) => true,
+    _ => false,
+  }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/nll/issue-47153-generic-const.rs b/src/test/run-pass/nll/issue-47153-generic-const.rs
new file mode 100644 (file)
index 0000000..9708ca1
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #47153: constants in a generic context (such as
+// a trait) used to ICE.
+
+#![feature(nll)]
+#![allow(warnings)]
+
+trait Foo {
+    const B: bool = true;
+}
+
+struct Bar<T> { x: T }
+
+impl<T> Bar<T> {
+    const B: bool = true;
+}
+
+fn main() { }
diff --git a/src/test/run-pass/result-opt-conversions.rs b/src/test/run-pass/result-opt-conversions.rs
new file mode 100644 (file)
index 0000000..0f6da00
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright 2018 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(transpose_result)]
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+struct BadNumErr;
+
+fn try_num(x: i32) -> Result<i32, BadNumErr> {
+    if x <= 5 {
+        Ok(x + 1)
+    } else {
+        Err(BadNumErr)
+    }
+}
+
+type ResOpt = Result<Option<i32>, BadNumErr>;
+type OptRes = Option<Result<i32, BadNumErr>>;
+
+fn main() {
+    let mut x: ResOpt = Ok(Some(5));
+    let mut y: OptRes = Some(Ok(5));
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    x = Ok(None);
+    y = None;
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    x = Err(BadNumErr);
+    y = Some(Err(BadNumErr));
+    assert_eq!(x, y.transpose());
+    assert_eq!(x.transpose(), y);
+
+    let res: Result<Vec<i32>, BadNumErr> =
+        (0..10)
+            .map(|x| {
+                let y = try_num(x)?;
+                Ok(if y % 2 == 0 {
+                    Some(y - 1)
+                } else {
+                    None
+                })
+            })
+            .filter_map(Result::transpose)
+            .collect();
+
+    assert_eq!(res, Err(BadNumErr))
+}
index 920620a9aeed57489d1a4fbeda8b5d3446ab8dab..0296788f7a0f5402f94de16eb0ba06a7ced0fec7 100644 (file)
@@ -15,7 +15,6 @@ const EXPECTED = {
         { 'path': 'std::char', 'name': 'from_u32' },
         { 'path': 'std::str', 'name': 'from_utf8' },
         { 'path': 'std::string::String', 'name': 'from_utf8' },
-        { 'path': 'std::boxed::Box', 'name': 'from_unique' },
         { 'path': 'std::i32', 'name': 'from_unsigned' },
         { 'path': 'std::i128', 'name': 'from_unsigned' },
     ],
index 7c88d789fd36eeb55fb971886484b42bc5f1a066..3b4f514de7dcaf82e3df8f2bf15b977826e8c6cb 100644 (file)
@@ -13,7 +13,7 @@ error[E0618]: expected function, found `()`
   --> $DIR/issue-20862.rs:17:13
    |
 17 |     let x = foo(5)(2);
-   |             ^^^^^^^^^
+   |             ^^^^^^^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/borrowck/issue-45983.rs b/src/test/ui/borrowck/issue-45983.rs
new file mode 100644 (file)
index 0000000..a6e5067
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 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 give_any<F: for<'r> FnOnce(&'r ())>(f: F) {
+    f(&());
+}
+
+fn main() {
+    let x = None;
+    give_any(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/issue-45983.stderr b/src/test/ui/borrowck/issue-45983.stderr
new file mode 100644 (file)
index 0000000..496f15c
--- /dev/null
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-45983.rs:17:27
+   |
+16 |     let x = None;
+   |         - borrowed data cannot be stored into here...
+17 |     give_any(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/issue-7573.rs b/src/test/ui/borrowck/issue-7573.rs
new file mode 100644 (file)
index 0000000..8f1545f
--- /dev/null
@@ -0,0 +1,54 @@
+// 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.
+
+
+pub struct CrateId {
+    local_path: String,
+    junk: String
+}
+
+impl CrateId {
+    fn new(s: &str) -> CrateId {
+        CrateId {
+            local_path: s.to_string(),
+            junk: "wutevs".to_string()
+        }
+    }
+}
+
+pub fn remove_package_from_database() {
+    let mut lines_to_use: Vec<&CrateId> = Vec::new();
+        //~^ NOTE cannot infer an appropriate lifetime
+    let push_id = |installed_id: &CrateId| {
+        //~^ NOTE borrowed data cannot outlive this closure
+        //~| NOTE ...so that variable is valid at time of its declaration
+        lines_to_use.push(installed_id);
+        //~^ ERROR borrowed data cannot be stored outside of its closure
+        //~| NOTE cannot be stored outside of its closure
+    };
+    list_database(push_id);
+
+    for l in &lines_to_use {
+        println!("{}", l.local_path);
+    }
+
+}
+
+pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
+    let stuff = ["foo", "bar"];
+
+    for l in &stuff {
+        f(&CrateId::new(*l));
+    }
+}
+
+pub fn main() {
+    remove_package_from_database();
+}
diff --git a/src/test/ui/borrowck/issue-7573.stderr b/src/test/ui/borrowck/issue-7573.stderr
new file mode 100644 (file)
index 0000000..99b48d9
--- /dev/null
@@ -0,0 +1,16 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/issue-7573.rs:32:27
+   |
+27 |     let mut lines_to_use: Vec<&CrateId> = Vec::new();
+   |                               - cannot infer an appropriate lifetime...
+28 |         //~^ NOTE cannot infer an appropriate lifetime
+29 |     let push_id = |installed_id: &CrateId| {
+   |         -------   ------------------------ borrowed data cannot outlive this closure
+   |         |
+   |         ...so that variable is valid at time of its declaration
+...
+32 |         lines_to_use.push(installed_id);
+   |                           ^^^^^^^^^^^^ cannot be stored outside of its closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.rs b/src/test/ui/borrowck/regions-escape-bound-fn-2.rs
new file mode 100644 (file)
index 0000000..1c38dee
--- /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.
+
+fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    let x = 3;
+    f(&x);
+}
+
+fn main() {
+    let mut x = None;
+    with_int(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.stderr
new file mode 100644 (file)
index 0000000..3d88f4f
--- /dev/null
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn-2.rs:18:27
+   |
+17 |     let mut x = None;
+   |         ----- borrowed data cannot be stored into here...
+18 |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.rs b/src/test/ui/borrowck/regions-escape-bound-fn.rs
new file mode 100644 (file)
index 0000000..c227423
--- /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.
+
+fn with_int<F>(f: F) where F: FnOnce(&isize) {
+    let x = 3;
+    f(&x);
+}
+
+fn main() {
+    let mut x: Option<&isize> = None;
+    with_int(|y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.stderr
new file mode 100644 (file)
index 0000000..a2ad7c3
--- /dev/null
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-bound-fn.rs:18:27
+   |
+17 |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+18 |     with_int(|y| x = Some(y));
+   |              ---          ^ cannot be stored outside of its closure
+   |              |
+   |              ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.rs b/src/test/ui/borrowck/regions-escape-unboxed-closure.rs
new file mode 100644 (file)
index 0000000..5a21450
--- /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 with_int(f: &mut FnMut(&isize)) {
+}
+
+fn main() {
+    let mut x: Option<&isize> = None;
+    with_int(&mut |y| x = Some(y));
+    //~^ ERROR borrowed data cannot be stored outside of its closure
+}
diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.stderr
new file mode 100644 (file)
index 0000000..4b01e42
--- /dev/null
@@ -0,0 +1,12 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/regions-escape-unboxed-closure.rs:16:32
+   |
+15 |     let mut x: Option<&isize> = None;
+   |         ----- borrowed data cannot be stored into here...
+16 |     with_int(&mut |y| x = Some(y));
+   |                   ---          ^ cannot be stored outside of its closure
+   |                   |
+   |                   ...because it cannot outlive this closure
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.rs b/src/test/ui/closure-expected-type/expect-region-supply-region.rs
new file mode 100644 (file)
index 0000000..a464c58
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(warnings)]
+
+fn closure_expecting_bound<F>(_: F)
+    where F: FnOnce(&u32)
+{
+}
+
+fn closure_expecting_free<'a, F>(_: F)
+    where F: FnOnce(&'a u32)
+{
+}
+
+fn expect_bound_supply_nothing() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x| {
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_bound_supply_bound() {
+    // Because `x` is inferred to have a bound region, we cannot allow
+    // it to escape into `f`, even with an explicit type annotation on
+    // closure:
+    let mut f: Option<&u32> = None;
+    closure_expecting_bound(|x: &u32| {
+        f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_bound_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here we give a type annotation that `x` should be free. We get
+    // an error because of that.
+    closure_expecting_bound(|x: &'x u32| {
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
+
+        // And we still cannot let `x` escape into `f`.
+        f = Some(x);
+        //~^ ERROR borrowed data cannot be stored outside of its closure
+    });
+}
+
+fn expect_free_supply_nothing() {
+    let mut f: Option<&u32> = None;
+    closure_expecting_free(|x| f = Some(x)); // OK
+}
+
+fn expect_free_supply_bound() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &u32| f = Some(x)); // OK
+}
+
+fn expect_free_supply_named<'x>() {
+    let mut f: Option<&u32> = None;
+
+    // Here, even though the annotation `&u32` could be seen as being
+    // bound in the closure, we permit it to be defined as a free
+    // region (which is inferred to something in the fn body).
+    closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
+}
+
+fn main() { }
diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.stderr
new file mode 100644 (file)
index 0000000..ebb1e56
--- /dev/null
@@ -0,0 +1,98 @@
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:28:18
+   |
+26 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+27 |     closure_expecting_bound(|x| {
+   |                             --- ...because it cannot outlive this closure
+28 |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^ cannot be stored outside of its closure
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:38:18
+   |
+36 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+37 |     closure_expecting_bound(|x: &u32| {
+   |                             --------- ...because it cannot outlive this closure
+38 |         f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
+   |                  ^ cannot be stored outside of its closure
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:47:33
+   |
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the anonymous lifetime #2 defined on the body at 47:29...
+  --> $DIR/expect-region-supply-region.rs:47:29
+   |
+47 |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+48 | |         //~^ ERROR mismatched types
+49 | |         //~| ERROR mismatched types
+50 | |
+...  |
+53 | |         //~^ ERROR borrowed data cannot be stored outside of its closure
+54 | |     });
+   | |_____^
+note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1
+  --> $DIR/expect-region-supply-region.rs:42:1
+   |
+42 | / fn expect_bound_supply_named<'x>() {
+43 | |     let mut f: Option<&u32> = None;
+44 | |
+45 | |     // Here we give a type annotation that `x` should be free. We get
+...  |
+54 | |     });
+55 | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/expect-region-supply-region.rs:47:33
+   |
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                                 ^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `&u32`
+              found type `&'x u32`
+note: the lifetime 'x as defined on the function body at 42:1...
+  --> $DIR/expect-region-supply-region.rs:42:1
+   |
+42 | / fn expect_bound_supply_named<'x>() {
+43 | |     let mut f: Option<&u32> = None;
+44 | |
+45 | |     // Here we give a type annotation that `x` should be free. We get
+...  |
+54 | |     });
+55 | | }
+   | |_^
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29
+  --> $DIR/expect-region-supply-region.rs:47:29
+   |
+47 |       closure_expecting_bound(|x: &'x u32| {
+   |  _____________________________^
+48 | |         //~^ ERROR mismatched types
+49 | |         //~| ERROR mismatched types
+50 | |
+...  |
+53 | |         //~^ ERROR borrowed data cannot be stored outside of its closure
+54 | |     });
+   | |_____^
+
+error: borrowed data cannot be stored outside of its closure
+  --> $DIR/expect-region-supply-region.rs:52:18
+   |
+43 |     let mut f: Option<&u32> = None;
+   |         ----- borrowed data cannot be stored into here...
+...
+47 |     closure_expecting_bound(|x: &'x u32| {
+   |                             ------------ ...because it cannot outlive this closure
+...
+52 |         f = Some(x);
+   |                  ^ cannot be stored outside of its closure
+
+error: aborting due to 5 previous errors
+
index c33960193b0526b2b677ed5606cb832779294dbb..941292a7ec27d0bb08065ec4c55b3195adf0823b 100644 (file)
@@ -24,8 +24,8 @@ enum E {
 fn main() {
     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
     let e4 = E::Empty4();
-    //~^ ERROR expected function, found `E::Empty4` [E0618]
+    //~^ ERROR expected function, found enum variant `E::Empty4` [E0618]
     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
     let xe4 = XE::XEmpty4();
-    //~^ ERROR expected function, found `XE::XEmpty4` [E0618]
+    //~^ ERROR expected function, found enum variant `XE::XEmpty4` [E0618]
 }
index 3ce63ed9f423bfd46d61c2b8185f39648bef0f3f..aa242a530d0e322c1078d9822720a8d32044a3e3 100644 (file)
@@ -1,41 +1,40 @@
 error[E0618]: expected function, found `Empty2`
   --> $DIR/empty-struct-unit-expr.rs:25:14
    |
-25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
-   |              ^^^^^^^^
-   |
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:18:1
-   |
 18 | struct Empty2;
-   | ^^^^^^^^^^^^^^
+   | -------------- `Empty2` defined here
+...
+25 |     let e2 = Empty2(); //~ ERROR expected function, found `Empty2`
+   |              ^^^^^^^^ not a function
 
-error[E0618]: expected function, found `E::Empty4`
+error[E0618]: expected function, found enum variant `E::Empty4`
   --> $DIR/empty-struct-unit-expr.rs:26:14
    |
+21 |     Empty4
+   |     ------ `E::Empty4` defined here
+...
 26 |     let e4 = E::Empty4();
-   |              ^^^^^^^^^^^
-   |
-   = help: did you mean to write `E::Empty4`?
-note: defined here
-  --> $DIR/empty-struct-unit-expr.rs:21:5
+   |              ^^^^^^^^^^^ not a function
+help: `E::Empty4` is a unit variant, you need to write it without the parenthesis
    |
-21 |     Empty4
-   |     ^^^^^^
+26 |     let e4 = E::Empty4;
+   |              ^^^^^^^^^
 
 error[E0618]: expected function, found `empty_struct::XEmpty2`
   --> $DIR/empty-struct-unit-expr.rs:28:15
    |
 28 |     let xe2 = XEmpty2(); //~ ERROR expected function, found `empty_struct::XEmpty2`
-   |               ^^^^^^^^^
+   |               ^^^^^^^^^ not a function
 
-error[E0618]: expected function, found `XE::XEmpty4`
+error[E0618]: expected function, found enum variant `XE::XEmpty4`
   --> $DIR/empty-struct-unit-expr.rs:29:15
    |
 29 |     let xe4 = XE::XEmpty4();
-   |               ^^^^^^^^^^^^^
+   |               ^^^^^^^^^^^^^ not a function
+help: `XE::XEmpty4` is a unit variant, you need to write it without the parenthesis
    |
-   = help: did you mean to write `XE::XEmpty4`?
+29 |     let xe4 = XE::XEmpty4;
+   |               ^^^^^^^^^^^
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/feature-gate-repr_transparent.rs b/src/test/ui/feature-gate-repr_transparent.rs
new file mode 100644 (file)
index 0000000..deadf2e
--- /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.
+
+#[repr(transparent)] //~ error: the `#[repr(transparent)]` attribute is experimental
+struct Foo(u64);
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-repr_transparent.stderr b/src/test/ui/feature-gate-repr_transparent.stderr
new file mode 100644 (file)
index 0000000..d1292e9
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0658]: the `#[repr(transparent)]` attribute is experimental (see issue #43036)
+  --> $DIR/feature-gate-repr_transparent.rs:11:1
+   |
+11 | #[repr(transparent)] //~ error: the `#[repr(transparent)]` attribute is experimental
+   | ^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(repr_transparent)] to the crate attributes to enable
+
+error: aborting due to previous error
+
index 30f2f517115f49ad83381ac6c212ff8acf1a3adf..a74401314a18cb3698e6ac419087d5872bcbd23e 100644 (file)
@@ -12,7 +12,7 @@ help: You can use `as` to change the binding name of the import
 25 |     use a::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times
    |         ^^^^^^^^^^^^^^^^^^
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:56:9
    |
 56 |     use self::foo::bar; //~ ERROR `foo` is ambiguous
@@ -30,7 +30,7 @@ note: `foo` could also refer to the name imported here
    |         ^^^^^^^^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:45:5
    |
 45 |     f::foo(); //~ ERROR `foo` is ambiguous
@@ -48,7 +48,7 @@ note: `foo` could also refer to the name imported here
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:46:5
    |
 46 |     g::foo(); //~ ERROR `foo` is ambiguous
@@ -66,7 +66,7 @@ note: `foo` could also refer to the name imported here
    |             ^^^^
    = note: consider adding an explicit import of `foo` to disambiguate
 
-error: `foo` is ambiguous
+error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:59:9
    |
 59 |         foo::bar(); //~ ERROR `foo` is ambiguous
index 91b0b9756dad93066c1ea1e9a19e8aa0f4f9e8b6..32d78666004c422196b5e60c1f9ba69692753b2b 100644 (file)
@@ -1,4 +1,4 @@
-error: `bar` is ambiguous
+error[E0659]: `bar` is ambiguous
   --> $DIR/macro-paths.rs:25:5
    |
 25 |     bar::m! { //~ ERROR ambiguous
@@ -16,7 +16,7 @@ note: `bar` could also refer to the name imported here
    |         ^^^^^^
    = note: macro-expanded items do not shadow when used in a macro invocation path
 
-error: `baz` is ambiguous
+error[E0659]: `baz` is ambiguous
   --> $DIR/macro-paths.rs:35:5
    |
 35 |     baz::m! { //~ ERROR ambiguous
index 0b67613eb14b63efe6306df2ff7e6249ad69ade3..75294f7bf1256391a89fcb3fc3d709fd9e5f24e8 100644 (file)
@@ -15,7 +15,7 @@ note: `m` could also refer to the macro imported here
 49 |     use two_macros::m;
    |         ^^^^^^^^^^^^^
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:28:5
    |
 28 |     m! { //~ ERROR ambiguous
@@ -33,7 +33,7 @@ note: `m` could also refer to the name imported here
    |         ^^^^^^^^^^^^^
    = note: macro-expanded macro imports do not shadow
 
-error: `m` is ambiguous
+error[E0659]: `m` is ambiguous
   --> $DIR/macros.rs:41:9
    |
 41 |         m! { //~ ERROR ambiguous
index 853ed98c30d4dce672bc10ba3eb0ee8b272d8375..8f4325fa12c72576aa5155ddf414e358e122e266 100644 (file)
@@ -9,7 +9,7 @@ error: `panic` is already in scope
    |
    = note: macro-expanded `macro_rules!`s may not shadow existing macros (see RFC 1560)
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:27:14
    |
 27 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -23,7 +23,7 @@ note: `panic` could refer to the name imported here
    = note: `panic` is also a builtin macro
    = note: consider adding an explicit import of `panic` to disambiguate
 
-error: `panic` is ambiguous
+error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:32:14
    |
 32 |     fn f() { panic!(); } //~ ERROR ambiguous
@@ -37,7 +37,7 @@ note: `panic` could refer to the name imported here
    = note: `panic` is also a builtin macro
    = note: macro-expanded macro imports do not shadow
 
-error: `n` is ambiguous
+error[E0659]: `n` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:61:5
    |
 61 |     n!(); //~ ERROR ambiguous
index 8aea63e0bbdaa3f0656d98f929a8c32405c05917..68127b282ed5484dcf61ced5033e8eb76bdd3a14 100644 (file)
@@ -1,26 +1,18 @@
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:12:5
    |
-12 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:11:9
-   |
 11 | fn func(i: i32) {
-   |         ^
+   |         - `i32` defined here
+12 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error[E0618]: expected function, found `i32`
   --> $DIR/issue-10969.rs:16:5
    |
-16 |     i(); //~ERROR expected function, found `i32`
-   |     ^^^
-   |
-note: defined here
-  --> $DIR/issue-10969.rs:15:9
-   |
 15 |     let i = 0i32;
-   |         ^
+   |         - `i32` defined here
+16 |     i(); //~ERROR expected function, found `i32`
+   |     ^^^ not a function
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-47623.rs b/src/test/ui/issue-47623.rs
new file mode 100644 (file)
index 0000000..0c886fd
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/issue-47623.stderr b/src/test/ui/issue-47623.stderr
new file mode 100644 (file)
index 0000000..c5a42d4
--- /dev/null
@@ -0,0 +1,8 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/issue-47623.rs:11:5
+   |
+11 | use self; //~ERROR `self` imports are only allowed within a { } list
+   |     ^^^^
+
+error: aborting due to previous error
+
index 1ee24e398520bcfde582f57396bb68c2f6f72c51..96e5201716c7173f2be48a72aac924ed94d650ab 100644 (file)
@@ -18,6 +18,8 @@ fn main() {
     //~^ ERROR closure is expected to take
     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
     //~^ ERROR closure is expected to take
+    [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+    //~^ ERROR closure is expected to take
     f(|| panic!());
     //~^ ERROR closure is expected to take
 
@@ -32,6 +34,9 @@ fn main() {
     let bar = |i, x, y| i;
     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
     //~^ ERROR closure is expected to take
+    let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+    //~^ ERROR function is expected to take
 }
 
 fn foo() {}
+fn qux(x: usize, y: usize) {}
index ba25d67d76ef2fc7fb0fff65e6caf7a04ff9fa05..be00ee4d74e7eededd2590ec6468ed33a62e651d 100644 (file)
@@ -14,18 +14,34 @@ error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
    |               |
    |               expected closure that takes 2 arguments
 
-error[E0593]: closure is expected to take 2 arguments, but it takes 1 argument
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
   --> $DIR/closure-arg-count.rs:19:15
    |
 19 |     [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
-   |               ^^^^^^^ ----------------- takes 1 argument
+   |               ^^^^^^^ ----------------- takes a single 2-tuple as argument
    |               |
-   |               expected closure that takes 2 arguments
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+19 |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
+
+error[E0593]: closure is expected to take 2 distinct arguments, but it takes a single 2-tuple as argument
+  --> $DIR/closure-arg-count.rs:21:15
+   |
+21 |     [1, 2, 3].sort_by(|(tuple, tuple2): (usize, _)| panic!());
+   |               ^^^^^^^ ----------------------------- takes a single 2-tuple as argument
+   |               |
+   |               expected closure that takes 2 distinct arguments
+help: change the closure to take multiple arguments instead of a single tuple
+   |
+21 |     [1, 2, 3].sort_by(|tuple, tuple2| panic!());
+   |                       ^^^^^^^^^^^^^^^
 
 error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
-  --> $DIR/closure-arg-count.rs:21:5
+  --> $DIR/closure-arg-count.rs:23:5
    |
-21 |     f(|| panic!());
+23 |     f(|| panic!());
    |     ^ -- takes 0 arguments
    |     |
    |     expected closure that takes 1 argument
@@ -36,46 +52,63 @@ note: required by `f`
 13 | fn f<F: Fn<usize>>(_: F) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
-  --> $DIR/closure-arg-count.rs:24:53
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:26:53
    |
-24 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
-   |                                                     ^^^ ------ help: consider changing the closure to accept a tuple: `|(i, x)|`
+26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i);
+   |                                                     ^^^ ------ takes 2 distinct arguments
    |                                                     |
-   |                                                     expected closure that takes a single tuple as argument
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
 
-error[E0593]: closure is expected to take a single tuple as argument, but it takes 2 distinct arguments
-  --> $DIR/closure-arg-count.rs:26:53
+error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:28:53
    |
-26 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
-   |                                                     ^^^ ------------- help: consider changing the closure to accept a tuple: `|(i, x): (usize, _)|`
+28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i);
+   |                                                     ^^^ ------------- takes 2 distinct arguments
    |                                                     |
-   |                                                     expected closure that takes a single tuple as argument
+   |                                                     expected closure that takes a single 2-tuple as argument
+help: change the closure to accept a tuple instead of individual arguments
+   |
+28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i);
+   |                                                         ^^^^^^^^
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
-  --> $DIR/closure-arg-count.rs:28:53
+  --> $DIR/closure-arg-count.rs:30:53
    |
-28 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
+30 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i);
    |                                                     ^^^ --------- takes 3 distinct arguments
    |                                                     |
    |                                                     expected closure that takes a single 2-tuple as argument
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments
-  --> $DIR/closure-arg-count.rs:30:53
+  --> $DIR/closure-arg-count.rs:32:53
    |
-30 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
+32 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
    |                                                     ^^^ expected function that takes a single 2-tuple as argument
 ...
-37 | fn foo() {}
+41 | fn foo() {}
    | -------- takes 0 arguments
 
 error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments
-  --> $DIR/closure-arg-count.rs:33:53
+  --> $DIR/closure-arg-count.rs:35:53
    |
-32 |     let bar = |i, x, y| i;
+34 |     let bar = |i, x, y| i;
    |               --------- takes 3 distinct arguments
-33 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
+35 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
    |                                                     ^^^ expected closure that takes a single 2-tuple as argument
 
-error: aborting due to 9 previous errors
+error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/closure-arg-count.rs:37:53
+   |
+37 |     let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
+   |                                                     ^^^ expected function that takes a single 2-tuple as argument
+...
+42 | fn qux(x: usize, y: usize) {}
+   | -------------------------- takes 2 distinct arguments
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/nll/generator-distinct-lifetime.rs b/src/test/ui/nll/generator-distinct-lifetime.rs
new file mode 100644 (file)
index 0000000..60f67b1
--- /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.
+
+#![feature(generators, nll)]
+
+// Test for issue #47189. Here, both `s` and `t` are live for the
+// generator's lifetime, but within the generator they have distinct
+// lifetimes. We accept this code -- even though the borrow extends
+// over a yield -- because the data that is borrowed (`*x`) is not
+// stored on the stack.
+
+// must-compile-successfully
+
+fn foo(x: &mut u32) {
+    move || {
+        let s = &mut *x;
+        yield;
+        *s += 1;
+
+        let t = &mut *x;
+        yield;
+        *t += 1;
+    };
+}
+
+fn main() {
+    foo(&mut 0);
+}
diff --git a/src/test/ui/resolve/privacy-enum-ctor.rs b/src/test/ui/resolve/privacy-enum-ctor.rs
new file mode 100644 (file)
index 0000000..08480a0
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod m {
+    pub enum E {
+        Fn(u8),
+        Struct {
+            s: u8,
+        },
+        Unit,
+    }
+
+    pub mod n {
+        pub(in m) enum Z {
+            Fn(u8),
+            Struct {
+                s: u8,
+            },
+            Unit,
+        }
+    }
+
+    use m::n::Z; // OK, only the type is imported
+
+    fn f() {
+        n::Z;
+        //~^ ERROR expected value, found enum `n::Z`
+        Z;
+        //~^ ERROR expected value, found enum `Z`
+        let _: Z = Z::Fn;
+        //~^ ERROR mismatched types
+        let _: Z = Z::Struct;
+        //~^ ERROR expected value, found struct variant `Z::Struct`
+        let _ = Z::Unit();
+        //~^ ERROR expected function, found enum variant `Z::Unit`
+        let _ = Z::Unit {};
+        // This is ok, it is equivalent to not having braces
+    }
+}
+
+use m::E; // OK, only the type is imported
+
+fn main() {
+    let _: E = m::E;
+    //~^ ERROR expected value, found enum `m::E`
+    let _: E = m::E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = m::E::Struct;
+    //~^ ERROR expected value, found struct variant `m::E::Struct`
+    let _: E = m::E::Unit();
+    //~^ ERROR expected function, found enum variant `m::E::Unit`
+    let _: E = E;
+    //~^ ERROR expected value, found enum `E`
+    let _: E = E::Fn;
+    //~^ ERROR mismatched types
+    let _: E = E::Struct;
+    //~^ ERROR expected value, found struct variant `E::Struct`
+    let _: E = E::Unit();
+    //~^ ERROR expected function, found enum variant `E::Unit`
+    let _: Z = m::n::Z;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found enum `m::n::Z`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Fn;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Struct;
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR expected value, found struct variant `m::n::Z::Struct`
+    //~| ERROR enum `Z` is private
+    let _: Z = m::n::Z::Unit {};
+    //~^ ERROR cannot find type `Z` in this scope
+    //~| ERROR enum `Z` is private
+}
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
new file mode 100644 (file)
index 0000000..c4f6d1f
--- /dev/null
@@ -0,0 +1,225 @@
+error[E0423]: expected value, found enum `n::Z`
+  --> $DIR/privacy-enum-ctor.rs:33:9
+   |
+33 |         n::Z;
+   |         ^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found enum `Z`
+  --> $DIR/privacy-enum-ctor.rs:35:9
+   |
+35 |         Z;
+   |         ^ did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0423]: expected value, found struct variant `Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:39:20
+   |
+39 |         let _: Z = Z::Struct;
+   |                    ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `m::E`
+  --> $DIR/privacy-enum-ctor.rs:51:16
+   |
+51 |     let _: E = m::E;
+   |                ^^^-
+   |                   |
+   |                   did you mean `f`?
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `m::E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:55:16
+   |
+55 |     let _: E = m::E::Struct;
+   |                ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`?
+
+error[E0423]: expected value, found enum `E`
+  --> $DIR/privacy-enum-ctor.rs:59:16
+   |
+59 |     let _: E = E;
+   |                ^
+   |
+   = note: did you mean to use one of the following variants?
+           - `E::Fn`
+           - `E::Struct`
+           - `E::Unit`
+help: possible better candidates are found in other modules, you can import them into scope
+   |
+48 | use std::f32::consts::E;
+   |
+48 | use std::f64::consts::E;
+   |
+
+error[E0423]: expected value, found struct variant `E::Struct`
+  --> $DIR/privacy-enum-ctor.rs:63:16
+   |
+63 |     let _: E = E::Struct;
+   |                ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:67:12
+   |
+67 |     let _: Z = m::n::Z;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found enum `m::n::Z`
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+   |
+   = note: did you mean to use one of the following variants?
+           - `m::Z::Fn`
+           - `m::Z::Struct`
+           - `m::Z::Unit`
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:71:12
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:74:12
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0423]: expected value, found struct variant `m::n::Z::Struct`
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`?
+
+error[E0412]: cannot find type `Z` in this scope
+  --> $DIR/privacy-enum-ctor.rs:78:12
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |            ^ did you mean `E`?
+help: possible candidate is found in another module, you can import it into scope
+   |
+48 | use m::n::Z;
+   |
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:67:16
+   |
+67 |     let _: Z = m::n::Z;
+   |                ^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:71:16
+   |
+71 |     let _: Z = m::n::Z::Fn;
+   |                ^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:74:16
+   |
+74 |     let _: Z = m::n::Z::Struct;
+   |                ^^^^^^^^^^^^^^^
+
+error[E0603]: enum `Z` is private
+  --> $DIR/privacy-enum-ctor.rs:78:16
+   |
+78 |     let _: Z = m::n::Z::Unit {};
+   |                ^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:37:20
+   |
+37 |         let _: Z = Z::Fn;
+   |                    ^^^^^ expected enum `m::n::Z`, found fn item
+   |
+   = note: expected type `m::n::Z`
+              found type `fn(u8) -> m::n::Z {m::n::Z::Fn}`
+
+error[E0618]: expected function, found enum variant `Z::Unit`
+  --> $DIR/privacy-enum-ctor.rs:41:17
+   |
+26 |             Unit,
+   |             ---- `Z::Unit` defined here
+...
+41 |         let _ = Z::Unit();
+   |                 ^^^^^^^^^ not a function
+help: `Z::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+41 |         let _ = Z::Unit;
+   |                 ^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:53:16
+   |
+53 |     let _: E = m::E::Fn;
+   |                ^^^^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `m::E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:57:16
+   |
+17 |         Unit,
+   |         ---- `m::E::Unit` defined here
+...
+57 |     let _: E = m::E::Unit();
+   |                ^^^^^^^^^^^^ not a function
+help: `m::E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+57 |     let _: E = m::E::Unit;
+   |                ^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/privacy-enum-ctor.rs:61:16
+   |
+61 |     let _: E = E::Fn;
+   |                ^^^^^ expected enum `m::E`, found fn item
+   |
+   = note: expected type `m::E`
+              found type `fn(u8) -> m::E {m::E::Fn}`
+
+error[E0618]: expected function, found enum variant `E::Unit`
+  --> $DIR/privacy-enum-ctor.rs:65:16
+   |
+17 |         Unit,
+   |         ---- `E::Unit` defined here
+...
+65 |     let _: E = E::Unit();
+   |                ^^^^^^^^^ not a function
+help: `E::Unit` is a unit variant, you need to write it without the parenthesis
+   |
+65 |     let _: E = E::Unit;
+   |                ^^^^^^^
+
+error: aborting due to 23 previous errors
+
index eb6edae738133f1ef26f0504eaeb5d57eb326c89..9029eeb22cd27304ab1b8f7f8df50f8ad69ff93a 100644 (file)
@@ -14,6 +14,9 @@
 
 mod m {
     pub struct S(u8);
+    pub struct S2 {
+        s: u8
+    }
 
     pub mod n {
         pub(in m) struct Z(pub(in m::n) u8);
@@ -22,22 +25,33 @@ pub mod n {
     use m::n::Z; // OK, only the type is imported
 
     fn f() {
-        n::Z; //~ ERROR tuple struct `Z` is private
+        n::Z;
+        //~^ ERROR tuple struct `Z` is private
         Z;
         //~^ ERROR expected value, found struct `Z`
     }
 }
 
 use m::S; // OK, only the type is imported
+use m::S2; // OK, only the type is imported
 
 fn main() {
-    m::S; //~ ERROR tuple struct `S` is private
+    m::S;
+    //~^ ERROR tuple struct `S` is private
+    let _: S = m::S(2);
+    //~^ ERROR tuple struct `S` is private
     S;
     //~^ ERROR expected value, found struct `S`
-    m::n::Z; //~ ERROR tuple struct `Z` is private
+    m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
+
+    S2;
+    //~^ ERROR expected value, found struct `S2`
 
-    xcrate::m::S; //~ ERROR tuple struct `S` is private
+    xcrate::m::S;
+    //~^ ERROR tuple struct `S` is private
     xcrate::S;
     //~^ ERROR expected value, found struct `xcrate::S`
-    xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+    xcrate::m::n::Z;
+    //~^ ERROR tuple struct `Z` is private
 }
index 39bedf59641a80a4bf94944b70e818f56347eb2e..e97a4e4143cc35d06ff4224588b98da7d6451d75 100644 (file)
@@ -1,72 +1,77 @@
 error[E0423]: expected value, found struct `Z`
-  --> $DIR/privacy-struct-ctor.rs:26:9
+  --> $DIR/privacy-struct-ctor.rs:30:9
    |
-26 |         Z;
+30 |         Z;
    |         ^
    |         |
    |         did you mean `S`?
    |         constructor is not visible here due to private fields
-   |         did you mean `Z { /* fields */ }`?
 help: possible better candidate is found in another module, you can import it into scope
    |
-22 |     use m::n::Z;
+25 |     use m::n::Z;
    |
 
 error[E0423]: expected value, found struct `S`
-  --> $DIR/privacy-struct-ctor.rs:35:5
+  --> $DIR/privacy-struct-ctor.rs:43:5
    |
-35 |     S;
-   |     ^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `S { /* fields */ }`?
+43 |     S;
+   |     ^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
+error[E0423]: expected value, found struct `S2`
+  --> $DIR/privacy-struct-ctor.rs:48:5
+   |
+48 |     S2;
+   |     ^^ did you mean `S2 { /* fields */ }`?
+
 error[E0423]: expected value, found struct `xcrate::S`
-  --> $DIR/privacy-struct-ctor.rs:40:5
+  --> $DIR/privacy-struct-ctor.rs:53:5
    |
-40 |     xcrate::S;
-   |     ^^^^^^^^^
-   |     |
-   |     constructor is not visible here due to private fields
-   |     did you mean `xcrate::S { /* fields */ }`?
+53 |     xcrate::S;
+   |     ^^^^^^^^^ constructor is not visible here due to private fields
 help: possible better candidate is found in another module, you can import it into scope
    |
-31 | use m::S;
+35 | use m::S;
    |
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:25:9
+  --> $DIR/privacy-struct-ctor.rs:28:9
    |
-25 |         n::Z; //~ ERROR tuple struct `Z` is private
+28 |         n::Z;
    |         ^^^^
 
 error[E0603]: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:34:5
+  --> $DIR/privacy-struct-ctor.rs:39:5
    |
-34 |     m::S; //~ ERROR tuple struct `S` is private
+39 |     m::S;
    |     ^^^^
 
+error[E0603]: tuple struct `S` is private
+  --> $DIR/privacy-struct-ctor.rs:41:16
+   |
+41 |     let _: S = m::S(2);
+   |                ^^^^
+
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:37:5
+  --> $DIR/privacy-struct-ctor.rs:45:5
    |
-37 |     m::n::Z; //~ ERROR tuple struct `Z` is private
+45 |     m::n::Z;
    |     ^^^^^^^
 
 error[E0603]: tuple struct `S` is private
-  --> $DIR/privacy-struct-ctor.rs:39:5
+  --> $DIR/privacy-struct-ctor.rs:51:5
    |
-39 |     xcrate::m::S; //~ ERROR tuple struct `S` is private
+51 |     xcrate::m::S;
    |     ^^^^^^^^^^^^
 
 error[E0603]: tuple struct `Z` is private
-  --> $DIR/privacy-struct-ctor.rs:42:5
+  --> $DIR/privacy-struct-ctor.rs:55:5
    |
-42 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
+55 |     xcrate::m::n::Z;
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
index aea9fc356bf2e5bcaf9a39348cb98f837d8de211..843d7c20ffd2cf5e0140275f6507b7123cb9ea90 100644 (file)
@@ -2,31 +2,33 @@ error[E0423]: expected function, found self type `Self`
   --> $DIR/tuple-struct-alias.rs:16:17
    |
 16 |         let s = Self(0, 1); //~ ERROR expected function
-   |                 ^^^^ did you mean `Self { /* fields */ }`?
+   |                 ^^^^ not a function
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0532]: expected tuple struct/variant, found self type `Self`
   --> $DIR/tuple-struct-alias.rs:18:13
    |
 18 |             Self(..) => {} //~ ERROR expected tuple struct/variant
-   |             ^^^^ did you mean `Self { /* fields */ }`?
+   |             ^^^^ not a tuple struct/variant
+   |
+   = note: can't use `Self` as a constructor, you must use the implemented struct
 
 error[E0423]: expected function, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:24:13
    |
 24 |     let s = A(0, 1); //~ ERROR expected function
-   |             ^
-   |             |
-   |             did you mean `S`?
-   |             did you mean `A { /* fields */ }`?
+   |             ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error[E0532]: expected tuple struct/variant, found type alias `A`
   --> $DIR/tuple-struct-alias.rs:26:9
    |
 26 |         A(..) => {} //~ ERROR expected tuple struct/variant
-   |         ^
-   |         |
-   |         did you mean `S`?
-   |         did you mean `A { /* fields */ }`?
+   |         ^ did you mean `S`?
+   |
+   = note: can't use a type alias as a constructor
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/suggestions/numeric-cast-2.rs b/src/test/ui/suggestions/numeric-cast-2.rs
new file mode 100644 (file)
index 0000000..2092b6b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 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() -> i32 {
+    4
+}
+fn main() {
+    let x: u16 = foo();
+    //~^ ERROR mismatched types
+    let y: i64 = x + x;
+    //~^ ERROR mismatched types
+    let z: i32 = x + x;
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/numeric-cast-2.stderr b/src/test/ui/suggestions/numeric-cast-2.stderr
new file mode 100644 (file)
index 0000000..90086d2
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:15:18
+   |
+15 |     let x: u16 = foo();
+   |                  ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:17:18
+   |
+17 |     let y: i64 = x + x;
+   |                  ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-2.rs:19:18
+   |
+19 |     let z: i32 = x + x;
+   |                  ^^^^^ expected i32, found u16
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/suggestions/numeric-cast.rs b/src/test/ui/suggestions/numeric-cast.rs
new file mode 100644 (file)
index 0000000..6e14403
--- /dev/null
@@ -0,0 +1,315 @@
+// Copyright 2018 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<N>(_x: N) {}
+
+fn main() {
+    let x_usize: usize = 1;
+    let x_u64: u64 = 2;
+    let x_u32: u32 = 3;
+    let x_u16: u16 = 4;
+    let x_u8: u8 = 5;
+    let x_isize: isize = 6;
+    let x_i64: i64 = 7;
+    let x_i32: i32 = 8;
+    let x_i16: i16 = 9;
+    let x_i8: i8 = 10;
+    let x_f64: f64 = 11.0;
+    let x_f32: f32 = 12.0;
+
+    foo::<usize>(x_usize);
+    foo::<usize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<usize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<isize>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_isize);
+    foo::<isize>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<isize>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u64);
+    foo::<u64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i64);
+    foo::<i64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u32);
+    foo::<u32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i32);
+    foo::<i32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i32>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_u16);
+    foo::<u16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i16>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_i16);
+    foo::<i16>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i16>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<u8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_u8);
+    foo::<u8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<u8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<i8>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_i8);
+    foo::<i8>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<i8>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f64>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f64>(x_f64);
+    foo::<f64>(x_f32);
+    //~^ ERROR mismatched types
+
+    foo::<f32>(x_usize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_u8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_isize);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i32);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i16);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_i8);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f64);
+    //~^ ERROR mismatched types
+    foo::<f32>(x_f32);
+}
diff --git a/src/test/ui/suggestions/numeric-cast.stderr b/src/test/ui/suggestions/numeric-cast.stderr
new file mode 100644 (file)
index 0000000..0ce3d08
--- /dev/null
@@ -0,0 +1,886 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:29:18
+   |
+29 |     foo::<usize>(x_u64);
+   |                  ^^^^^ expected usize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:31:18
+   |
+31 |     foo::<usize>(x_u32);
+   |                  ^^^^^ expected usize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:33:18
+   |
+33 |     foo::<usize>(x_u16);
+   |                  ^^^^^ expected usize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:35:18
+   |
+35 |     foo::<usize>(x_u8);
+   |                  ^^^^ expected usize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:37:18
+   |
+37 |     foo::<usize>(x_isize);
+   |                  ^^^^^^^ expected usize, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:39:18
+   |
+39 |     foo::<usize>(x_i64);
+   |                  ^^^^^ expected usize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:41:18
+   |
+41 |     foo::<usize>(x_i32);
+   |                  ^^^^^ expected usize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:43:18
+   |
+43 |     foo::<usize>(x_i16);
+   |                  ^^^^^ expected usize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:45:18
+   |
+45 |     foo::<usize>(x_i8);
+   |                  ^^^^ expected usize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:47:18
+   |
+47 |     foo::<usize>(x_f64);
+   |                  ^^^^^ expected usize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:49:18
+   |
+49 |     foo::<usize>(x_f32);
+   |                  ^^^^^ expected usize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:52:18
+   |
+52 |     foo::<isize>(x_usize);
+   |                  ^^^^^^^ expected isize, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:54:18
+   |
+54 |     foo::<isize>(x_u64);
+   |                  ^^^^^ expected isize, found u64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:56:18
+   |
+56 |     foo::<isize>(x_u32);
+   |                  ^^^^^ expected isize, found u32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:58:18
+   |
+58 |     foo::<isize>(x_u16);
+   |                  ^^^^^ expected isize, found u16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:60:18
+   |
+60 |     foo::<isize>(x_u8);
+   |                  ^^^^ expected isize, found u8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:63:18
+   |
+63 |     foo::<isize>(x_i64);
+   |                  ^^^^^ expected isize, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:65:18
+   |
+65 |     foo::<isize>(x_i32);
+   |                  ^^^^^ expected isize, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:67:18
+   |
+67 |     foo::<isize>(x_i16);
+   |                  ^^^^^ expected isize, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:69:18
+   |
+69 |     foo::<isize>(x_i8);
+   |                  ^^^^ expected isize, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:71:18
+   |
+71 |     foo::<isize>(x_f64);
+   |                  ^^^^^ expected isize, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:73:18
+   |
+73 |     foo::<isize>(x_f32);
+   |                  ^^^^^ expected isize, found f32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:76:16
+   |
+76 |     foo::<u64>(x_usize);
+   |                ^^^^^^^ expected u64, found usize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:79:16
+   |
+79 |     foo::<u64>(x_u32);
+   |                ^^^^^ expected u64, found u32
+help: you can cast an `u32` to `u64`, which will zero-extend the source value
+   |
+79 |     foo::<u64>(x_u32.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:81:16
+   |
+81 |     foo::<u64>(x_u16);
+   |                ^^^^^ expected u64, found u16
+help: you can cast an `u16` to `u64`, which will zero-extend the source value
+   |
+81 |     foo::<u64>(x_u16.into());
+   |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:83:16
+   |
+83 |     foo::<u64>(x_u8);
+   |                ^^^^ expected u64, found u8
+help: you can cast an `u8` to `u64`, which will zero-extend the source value
+   |
+83 |     foo::<u64>(x_u8.into());
+   |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:85:16
+   |
+85 |     foo::<u64>(x_isize);
+   |                ^^^^^^^ expected u64, found isize
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:87:16
+   |
+87 |     foo::<u64>(x_i64);
+   |                ^^^^^ expected u64, found i64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:89:16
+   |
+89 |     foo::<u64>(x_i32);
+   |                ^^^^^ expected u64, found i32
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:91:16
+   |
+91 |     foo::<u64>(x_i16);
+   |                ^^^^^ expected u64, found i16
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:93:16
+   |
+93 |     foo::<u64>(x_i8);
+   |                ^^^^ expected u64, found i8
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:95:16
+   |
+95 |     foo::<u64>(x_f64);
+   |                ^^^^^ expected u64, found f64
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast.rs:97:16
+   |
+97 |     foo::<u64>(x_f32);
+   |                ^^^^^ expected u64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:100:16
+    |
+100 |     foo::<i64>(x_usize);
+    |                ^^^^^^^ expected i64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:102:16
+    |
+102 |     foo::<i64>(x_u64);
+    |                ^^^^^ expected i64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:104:16
+    |
+104 |     foo::<i64>(x_u32);
+    |                ^^^^^ expected i64, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:106:16
+    |
+106 |     foo::<i64>(x_u16);
+    |                ^^^^^ expected i64, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:108:16
+    |
+108 |     foo::<i64>(x_u8);
+    |                ^^^^ expected i64, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:110:16
+    |
+110 |     foo::<i64>(x_isize);
+    |                ^^^^^^^ expected i64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:113:16
+    |
+113 |     foo::<i64>(x_i32);
+    |                ^^^^^ expected i64, found i32
+help: you can cast an `i32` to `i64`, which will sign-extend the source value
+    |
+113 |     foo::<i64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:115:16
+    |
+115 |     foo::<i64>(x_i16);
+    |                ^^^^^ expected i64, found i16
+help: you can cast an `i16` to `i64`, which will sign-extend the source value
+    |
+115 |     foo::<i64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:117:16
+    |
+117 |     foo::<i64>(x_i8);
+    |                ^^^^ expected i64, found i8
+help: you can cast an `i8` to `i64`, which will sign-extend the source value
+    |
+117 |     foo::<i64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:119:16
+    |
+119 |     foo::<i64>(x_f64);
+    |                ^^^^^ expected i64, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:121:16
+    |
+121 |     foo::<i64>(x_f32);
+    |                ^^^^^ expected i64, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:124:16
+    |
+124 |     foo::<u32>(x_usize);
+    |                ^^^^^^^ expected u32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:126:16
+    |
+126 |     foo::<u32>(x_u64);
+    |                ^^^^^ expected u32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:129:16
+    |
+129 |     foo::<u32>(x_u16);
+    |                ^^^^^ expected u32, found u16
+help: you can cast an `u16` to `u32`, which will zero-extend the source value
+    |
+129 |     foo::<u32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:131:16
+    |
+131 |     foo::<u32>(x_u8);
+    |                ^^^^ expected u32, found u8
+help: you can cast an `u8` to `u32`, which will zero-extend the source value
+    |
+131 |     foo::<u32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:133:16
+    |
+133 |     foo::<u32>(x_isize);
+    |                ^^^^^^^ expected u32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:135:16
+    |
+135 |     foo::<u32>(x_i64);
+    |                ^^^^^ expected u32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:137:16
+    |
+137 |     foo::<u32>(x_i32);
+    |                ^^^^^ expected u32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:139:16
+    |
+139 |     foo::<u32>(x_i16);
+    |                ^^^^^ expected u32, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:141:16
+    |
+141 |     foo::<u32>(x_i8);
+    |                ^^^^ expected u32, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:143:16
+    |
+143 |     foo::<u32>(x_f64);
+    |                ^^^^^ expected u32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:145:16
+    |
+145 |     foo::<u32>(x_f32);
+    |                ^^^^^ expected u32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:148:16
+    |
+148 |     foo::<i32>(x_usize);
+    |                ^^^^^^^ expected i32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:150:16
+    |
+150 |     foo::<i32>(x_u64);
+    |                ^^^^^ expected i32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:152:16
+    |
+152 |     foo::<i32>(x_u32);
+    |                ^^^^^ expected i32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:154:16
+    |
+154 |     foo::<i32>(x_u16);
+    |                ^^^^^ expected i32, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:156:16
+    |
+156 |     foo::<i32>(x_u8);
+    |                ^^^^ expected i32, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:158:16
+    |
+158 |     foo::<i32>(x_isize);
+    |                ^^^^^^^ expected i32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:160:16
+    |
+160 |     foo::<i32>(x_i64);
+    |                ^^^^^ expected i32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:163:16
+    |
+163 |     foo::<i32>(x_i16);
+    |                ^^^^^ expected i32, found i16
+help: you can cast an `i16` to `i32`, which will sign-extend the source value
+    |
+163 |     foo::<i32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:165:16
+    |
+165 |     foo::<i32>(x_i8);
+    |                ^^^^ expected i32, found i8
+help: you can cast an `i8` to `i32`, which will sign-extend the source value
+    |
+165 |     foo::<i32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:167:16
+    |
+167 |     foo::<i32>(x_f64);
+    |                ^^^^^ expected i32, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:169:16
+    |
+169 |     foo::<i32>(x_f32);
+    |                ^^^^^ expected i32, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:172:16
+    |
+172 |     foo::<u16>(x_usize);
+    |                ^^^^^^^ expected u16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:174:16
+    |
+174 |     foo::<u16>(x_u64);
+    |                ^^^^^ expected u16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:176:16
+    |
+176 |     foo::<u16>(x_u32);
+    |                ^^^^^ expected u16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:179:16
+    |
+179 |     foo::<u16>(x_u8);
+    |                ^^^^ expected u16, found u8
+help: you can cast an `u8` to `u16`, which will zero-extend the source value
+    |
+179 |     foo::<u16>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:181:16
+    |
+181 |     foo::<u16>(x_isize);
+    |                ^^^^^^^ expected u16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:183:16
+    |
+183 |     foo::<u16>(x_i64);
+    |                ^^^^^ expected u16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:185:16
+    |
+185 |     foo::<u16>(x_i32);
+    |                ^^^^^ expected u16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:187:16
+    |
+187 |     foo::<u16>(x_i16);
+    |                ^^^^^ expected u16, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:189:16
+    |
+189 |     foo::<u16>(x_i8);
+    |                ^^^^ expected u16, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:191:16
+    |
+191 |     foo::<u16>(x_f64);
+    |                ^^^^^ expected u16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:193:16
+    |
+193 |     foo::<u16>(x_f32);
+    |                ^^^^^ expected u16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:196:16
+    |
+196 |     foo::<i16>(x_usize);
+    |                ^^^^^^^ expected i16, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:198:16
+    |
+198 |     foo::<i16>(x_u64);
+    |                ^^^^^ expected i16, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:200:16
+    |
+200 |     foo::<i16>(x_u32);
+    |                ^^^^^ expected i16, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:202:16
+    |
+202 |     foo::<i16>(x_u16);
+    |                ^^^^^ expected i16, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:204:16
+    |
+204 |     foo::<i16>(x_u8);
+    |                ^^^^ expected i16, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:206:16
+    |
+206 |     foo::<i16>(x_isize);
+    |                ^^^^^^^ expected i16, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:208:16
+    |
+208 |     foo::<i16>(x_i64);
+    |                ^^^^^ expected i16, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:210:16
+    |
+210 |     foo::<i16>(x_i32);
+    |                ^^^^^ expected i16, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:213:16
+    |
+213 |     foo::<i16>(x_i8);
+    |                ^^^^ expected i16, found i8
+help: you can cast an `i8` to `i16`, which will sign-extend the source value
+    |
+213 |     foo::<i16>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:215:16
+    |
+215 |     foo::<i16>(x_f64);
+    |                ^^^^^ expected i16, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:217:16
+    |
+217 |     foo::<i16>(x_f32);
+    |                ^^^^^ expected i16, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:220:15
+    |
+220 |     foo::<u8>(x_usize);
+    |               ^^^^^^^ expected u8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:222:15
+    |
+222 |     foo::<u8>(x_u64);
+    |               ^^^^^ expected u8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:224:15
+    |
+224 |     foo::<u8>(x_u32);
+    |               ^^^^^ expected u8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:226:15
+    |
+226 |     foo::<u8>(x_u16);
+    |               ^^^^^ expected u8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:229:15
+    |
+229 |     foo::<u8>(x_isize);
+    |               ^^^^^^^ expected u8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:231:15
+    |
+231 |     foo::<u8>(x_i64);
+    |               ^^^^^ expected u8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:233:15
+    |
+233 |     foo::<u8>(x_i32);
+    |               ^^^^^ expected u8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:235:15
+    |
+235 |     foo::<u8>(x_i16);
+    |               ^^^^^ expected u8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:237:15
+    |
+237 |     foo::<u8>(x_i8);
+    |               ^^^^ expected u8, found i8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:239:15
+    |
+239 |     foo::<u8>(x_f64);
+    |               ^^^^^ expected u8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:241:15
+    |
+241 |     foo::<u8>(x_f32);
+    |               ^^^^^ expected u8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:244:15
+    |
+244 |     foo::<i8>(x_usize);
+    |               ^^^^^^^ expected i8, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:246:15
+    |
+246 |     foo::<i8>(x_u64);
+    |               ^^^^^ expected i8, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:248:15
+    |
+248 |     foo::<i8>(x_u32);
+    |               ^^^^^ expected i8, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:250:15
+    |
+250 |     foo::<i8>(x_u16);
+    |               ^^^^^ expected i8, found u16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:252:15
+    |
+252 |     foo::<i8>(x_u8);
+    |               ^^^^ expected i8, found u8
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:254:15
+    |
+254 |     foo::<i8>(x_isize);
+    |               ^^^^^^^ expected i8, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:256:15
+    |
+256 |     foo::<i8>(x_i64);
+    |               ^^^^^ expected i8, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:258:15
+    |
+258 |     foo::<i8>(x_i32);
+    |               ^^^^^ expected i8, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:260:15
+    |
+260 |     foo::<i8>(x_i16);
+    |               ^^^^^ expected i8, found i16
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:263:15
+    |
+263 |     foo::<i8>(x_f64);
+    |               ^^^^^ expected i8, found f64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:265:15
+    |
+265 |     foo::<i8>(x_f32);
+    |               ^^^^^ expected i8, found f32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:268:16
+    |
+268 |     foo::<f64>(x_usize);
+    |                ^^^^^^^ expected f64, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:270:16
+    |
+270 |     foo::<f64>(x_u64);
+    |                ^^^^^ expected f64, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:272:16
+    |
+272 |     foo::<f64>(x_u32);
+    |                ^^^^^ expected f64, found u32
+help: you can cast an `u32` to `f64`, producing the floating point representation of the integer
+    |
+272 |     foo::<f64>(x_u32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:274:16
+    |
+274 |     foo::<f64>(x_u16);
+    |                ^^^^^ expected f64, found u16
+help: you can cast an `u16` to `f64`, producing the floating point representation of the integer
+    |
+274 |     foo::<f64>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:276:16
+    |
+276 |     foo::<f64>(x_u8);
+    |                ^^^^ expected f64, found u8
+help: you can cast an `u8` to `f64`, producing the floating point representation of the integer
+    |
+276 |     foo::<f64>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:278:16
+    |
+278 |     foo::<f64>(x_isize);
+    |                ^^^^^^^ expected f64, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:280:16
+    |
+280 |     foo::<f64>(x_i64);
+    |                ^^^^^ expected f64, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:282:16
+    |
+282 |     foo::<f64>(x_i32);
+    |                ^^^^^ expected f64, found i32
+help: you can cast an `i32` to `f64`, producing the floating point representation of the integer
+    |
+282 |     foo::<f64>(x_i32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:284:16
+    |
+284 |     foo::<f64>(x_i16);
+    |                ^^^^^ expected f64, found i16
+help: you can cast an `i16` to `f64`, producing the floating point representation of the integer
+    |
+284 |     foo::<f64>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:286:16
+    |
+286 |     foo::<f64>(x_i8);
+    |                ^^^^ expected f64, found i8
+help: you can cast an `i8` to `f64`, producing the floating point representation of the integer
+    |
+286 |     foo::<f64>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:289:16
+    |
+289 |     foo::<f64>(x_f32);
+    |                ^^^^^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+    |
+289 |     foo::<f64>(x_f32.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:292:16
+    |
+292 |     foo::<f32>(x_usize);
+    |                ^^^^^^^ expected f32, found usize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:294:16
+    |
+294 |     foo::<f32>(x_u64);
+    |                ^^^^^ expected f32, found u64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:296:16
+    |
+296 |     foo::<f32>(x_u32);
+    |                ^^^^^ expected f32, found u32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:298:16
+    |
+298 |     foo::<f32>(x_u16);
+    |                ^^^^^ expected f32, found u16
+help: you can cast an `u16` to `f32`, producing the floating point representation of the integer
+    |
+298 |     foo::<f32>(x_u16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:300:16
+    |
+300 |     foo::<f32>(x_u8);
+    |                ^^^^ expected f32, found u8
+help: you can cast an `u8` to `f32`, producing the floating point representation of the integer
+    |
+300 |     foo::<f32>(x_u8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:302:16
+    |
+302 |     foo::<f32>(x_isize);
+    |                ^^^^^^^ expected f32, found isize
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:304:16
+    |
+304 |     foo::<f32>(x_i64);
+    |                ^^^^^ expected f32, found i64
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:306:16
+    |
+306 |     foo::<f32>(x_i32);
+    |                ^^^^^ expected f32, found i32
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:308:16
+    |
+308 |     foo::<f32>(x_i16);
+    |                ^^^^^ expected f32, found i16
+help: you can cast an `i16` to `f32`, producing the floating point representation of the integer
+    |
+308 |     foo::<f32>(x_i16.into());
+    |                ^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:310:16
+    |
+310 |     foo::<f32>(x_i8);
+    |                ^^^^ expected f32, found i8
+help: you can cast an `i8` to `f32`, producing the floating point representation of the integer
+    |
+310 |     foo::<f32>(x_i8.into());
+    |                ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+   --> $DIR/numeric-cast.rs:312:16
+    |
+312 |     foo::<f32>(x_f64);
+    |                ^^^^^ expected f32, found f64
+
+error: aborting due to 132 previous errors
+
index 4aa096246bcf33b740b401b4634743833ae56024..bc35cbe9fbba64a3fbb2841f980be0511a515f0c 100644 (file)
@@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.0.26"
+version = "0.0.28"
 default-features = false
index a0c3e811a7aa2cc5b69c177f6e08ef11db258672..50f4364e448f73a8101aaf925c41e586c915716e 100644 (file)
@@ -52,12 +52,14 @@ fn main() {
 // Build command implementation
 pub fn build(args: &ArgMatches) -> Result<()> {
     let book_dir = get_book_dir(args);
-    let book = MDBook::new(&book_dir).read_config()?;
+    let mut book = MDBook::new(&book_dir).read_config()?;
 
-    let mut book = match args.value_of("dest-dir") {
-        Some(dest_dir) => book.with_destination(dest_dir),
-        None => book,
-    };
+    // Set this to allow us to catch bugs in advance.
+    book.config.build.create_missing = false;
+
+    if let Some(dest_dir) = args.value_of("dest-dir") {
+        book.config.build.build_dir = PathBuf::from(dest_dir);
+    }
 
     book.build()?;
 
index 6714a447d063b079de8fb2884ded2c8c3e96bc1d..e0e3e22248cd14ebbe0253e9720261a0328bfc59 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6714a447d063b079de8fb2884ded2c8c3e96bc1d
+Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
index 61d71986b03ebc544f2f07fafe6c2f11409516de..eee2902bfb6f736ccdd1a94af68293af1a1544b5 100644 (file)
@@ -69,6 +69,7 @@ fn filter_dirs(path: &Path) -> bool {
         "src/tools/miri",
         "src/librustc/mir/interpret",
         "src/librustc_mir/interpret",
+        "src/target",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }